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)) }