7981105cec
Процедуры Фонтвьель, вызванные bj (FTV_M2M_JOB → EVENTS → UPDATE_HANDBOOK, CREATE, OPERATION), пишут в таблицы Fancy правами логина bj. На 9 у bj_user был только db_datareader — «Запрещено разрешение INSERT на объект OD_OBJECTS» (событие HANDBOOK, 22.10.2026); упали бы и поручения M2M. На тесте — db_datareader + db_datawriter. Роль выдаётся в наборе «Применить скрипты» (права администратора БД; новый отпечаток — плашка на установках), в скачиваемом скрипте процедур, в скрипте логина и при подготовке трансферных таблиц (первичная установка). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
125 lines
5.9 KiB
Go
125 lines
5.9 KiB
Go
package lkgateway
|
|
|
|
// Логин bj в базе DEPO (05.10.2026): на шаге «Подключение» мастера — что нужно и скрипт для администратора
|
|
// СУБД. Скрипт создаёт логин (SQL Server) / роль (PostgreSQL) и даёт чтение учётных таблиц DEPO; права на
|
|
// таблицы обмена FTV_M2M* выдаёт скрипт таблиц на следующем шаге (или bj, если таблицы создаёт сам).
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
)
|
|
|
|
// depoLoginScript — скрипт создания логина bj. pg — PostgreSQL; db — база DEPO; login — имя логина;
|
|
// pass — пароль из поля мастера (пусто — заглушка, администратор впишет сам). Пароль только вставляется
|
|
// в текст скрипта, нигде не сохраняется.
|
|
func depoLoginScript(pg bool, db, login, pass string) string {
|
|
if !validDBName(db) {
|
|
db = depoDefaultDatabase
|
|
}
|
|
if !depoLoginRe.MatchString(login) {
|
|
login = "bj_user"
|
|
}
|
|
pw := "ЗАМЕНИТЕ_НА_ПАРОЛЬ"
|
|
if pass != "" {
|
|
pw = strings.ReplaceAll(pass, "'", "''") // строковый литерал SQL: одинарная кавычка удваивается
|
|
}
|
|
var b strings.Builder
|
|
if pg {
|
|
fmt.Fprintf(&b, `-- Bridge&Join: роль (логин) для bj в базе DEPO. PostgreSQL 10 и новее.
|
|
-- Выполнить суперпользователем или владельцем базы, например:
|
|
-- psql -h <сервер> -U postgres -f bj-depo-login-postgres.sql
|
|
-- Пароль — из поля мастера; если там пусто, замените ЗАМЕНИТЕ_НА_ПАРОЛЬ на свой. Скрипт с паролем не храните.
|
|
-- Права: только подключение и чтение учётных таблиц DEPO. Запись — только в таблицы обмена FTV_M2M*,
|
|
-- её выдаёт скрипт таблиц на следующем шаге мастера.
|
|
|
|
DO $$ BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '%[2]s') THEN
|
|
CREATE ROLE "%[2]s" LOGIN PASSWORD '%[3]s';
|
|
END IF;
|
|
END $$;
|
|
|
|
GRANT CONNECT ON DATABASE "%[1]s" TO "%[2]s";
|
|
|
|
\c "%[1]s"
|
|
GRANT USAGE ON SCHEMA public TO "%[2]s";
|
|
GRANT SELECT ON ALL TABLES IN SCHEMA public TO "%[2]s";
|
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO "%[2]s";
|
|
`, db, login, pw)
|
|
return b.String()
|
|
}
|
|
fmt.Fprintf(&b, `-- Bridge&Join: логин для bj в базе DEPO. Microsoft SQL Server.
|
|
-- Выполнить в SSMS или sqlcmd под логином с правами sysadmin (или securityadmin + db_owner в базе %[1]s).
|
|
-- Пароль — из поля мастера; если там пусто, замените ЗАМЕНИТЕ_НА_ПАРОЛЬ на свой. Скрипт с паролем не храните.
|
|
-- Права: чтение учётных таблиц DEPO (db_datareader) и запись (db_datawriter) — процедуры обработки M2M
|
|
-- (FTV_M2M_JOB и др.), которые вызывает bj, создают документы, операции и юрлица Fancy правами этого логина.
|
|
-- Таблицы обмена FTV_M2M* выдаёт скрипт таблиц на следующем шаге мастера. Скрипт можно запускать повторно.
|
|
|
|
USE [master];
|
|
GO
|
|
|
|
IF SUSER_ID(N'%[2]s') IS NULL
|
|
CREATE LOGIN [%[2]s] WITH PASSWORD = N'%[3]s', CHECK_POLICY = ON, DEFAULT_DATABASE = [%[1]s];
|
|
GO
|
|
|
|
USE [%[1]s];
|
|
GO
|
|
|
|
IF USER_ID(N'%[2]s') IS NULL CREATE USER [%[2]s] FOR LOGIN [%[2]s];
|
|
GO
|
|
|
|
-- Пользователь базы мог остаться от прежнего логина (база восстановлена из копии с другого сервера
|
|
-- или логин пересоздан): привязываем его к текущему логину, иначе вход в базу не пройдёт.
|
|
IF EXISTS (SELECT 1 FROM sys.database_principals WHERE name = N'%[2]s' AND sid <> SUSER_SID(N'%[2]s'))
|
|
ALTER USER [%[2]s] WITH LOGIN = [%[2]s];
|
|
GO
|
|
|
|
IF IS_ROLEMEMBER(N'db_datareader', N'%[2]s') = 0 ALTER ROLE db_datareader ADD MEMBER [%[2]s];
|
|
GO
|
|
|
|
IF IS_ROLEMEMBER(N'db_datawriter', N'%[2]s') = 0 ALTER ROLE db_datawriter ADD MEMBER [%[2]s];
|
|
GO
|
|
`, db, login, pw)
|
|
return b.String()
|
|
}
|
|
|
|
// fancyDepoLoginScript — GET /admin/setup/fancy/depo-login/script.sql?type=mssql|postgres&db=…&login=…
|
|
// Без параметров — по сохранённым настройкам; download=0 — показать текстом (предпросмотр в мастере).
|
|
func (h *setupHandlers) fancyDepoLoginScript(w http.ResponseWriter, r *http.Request) {
|
|
s := h.rc.Snapshot().Fancy
|
|
_ = r.ParseForm() // пароль приходит только в теле POST, не в адресе
|
|
q := r.Form
|
|
pg := s.IsPostgres()
|
|
if t := q.Get("type"); t != "" {
|
|
pg = t == "postgres"
|
|
}
|
|
db := strings.TrimSpace(q.Get("db"))
|
|
if db == "" {
|
|
db = s.DepoDB()
|
|
}
|
|
login := strings.TrimSpace(q.Get("login"))
|
|
if login == "" {
|
|
login = pickStr(strings.TrimSpace(s.User), "bj_user")
|
|
}
|
|
pass := ""
|
|
if r.Method == http.MethodPost {
|
|
pass = r.PostForm.Get("password")
|
|
}
|
|
w.Header().Set("Cache-Control", "no-store")
|
|
body := depoLoginScript(pg, db, login, pass)
|
|
name := "bj-depo-login-mssql.sql"
|
|
if pg {
|
|
name = "bj-depo-login-postgres.sql"
|
|
} else {
|
|
body = "\uFEFF" + body // SSMS без BOM читает кириллицу в комментариях как ANSI
|
|
}
|
|
if q.Get("download") == "0" {
|
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
|
_, _ = w.Write([]byte(strings.TrimPrefix(body, "\uFEFF")))
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/sql; charset=utf-8")
|
|
w.Header().Set("Content-Disposition", `attachment; filename="`+name+`"`)
|
|
_, _ = w.Write([]byte(body))
|
|
}
|