DEPO: FTV_M2M_JOB ставится WITH EXECUTE AS SYSDBA — обработка от SYSDBA и при вызове из bj, и джобой SQL Agent
22.10.2026, первый боевой входящий перевод на 9: в режиме «процедуру вызывает bj» процедуры работали правами bj_user, Fancy отказал «Создание документа запрещено для данного пользователя» (FU_HAVE_RIGHT пропускает только SYSDBA%), поручение в DEPO не создалось. На тесте была джоба SQL Agent (dbo → execute as SYSDBA). Новый отпечаток процедур — плашка «Применить скрипты» на установках. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
package lkgateway
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// FTV_M2M_JOB ставится с WITH EXECUTE AS 'SYSDBA' — обработка от SYSDBA и при вызове из bj; остальные — как есть.
|
||||
func TestDepoProcInstallBodyExecAs(t *testing.T) {
|
||||
var f FancyMSSQLSettings
|
||||
job := depoProcInstallBody(f, "FTV_M2M_JOB")
|
||||
if !strings.Contains(job, "with execute as 'SYSDBA'\nas\n") {
|
||||
t.Fatalf("JOB без EXECUTE AS:\n%s", job[:200])
|
||||
}
|
||||
if strings.Index(job, "with execute as") > strings.Index(job, "set nocount on") {
|
||||
t.Fatal("EXECUTE AS не перед телом процедуры")
|
||||
}
|
||||
if depoProcInstallBody(f, "FTV_M2M_PROCESS_CREATE") != depoProcEffective(f, "FTV_M2M_PROCESS_CREATE") {
|
||||
t.Fatal("CREATE изменён")
|
||||
}
|
||||
f.DepoProcOverrides = map[string]string{"FTV_M2M_JOB": "CREATE OR ALTER procedure dbo.FTV_M2M_JOB\nWITH EXECUTE AS OWNER\nas\nselect 1"}
|
||||
if got := depoProcInstallBody(f, "FTV_M2M_JOB"); strings.Count(strings.ToLower(got), "execute as") != 1 {
|
||||
t.Fatalf("второй EXECUTE AS к правке под клиента: %s", got)
|
||||
}
|
||||
}
|
||||
@@ -78,6 +78,33 @@ func depoProcEffective(f FancyMSSQLSettings, name string) string {
|
||||
return embeddedProcBody(name)
|
||||
}
|
||||
|
||||
// depoProcInstallBody — текст процедуры, который bj устанавливает: depoProcEffective, а у FTV_M2M_JOB —
|
||||
// с WITH EXECUTE AS '<пользователь процедур>' (обычно SYSDBA). Процедуры Фонтвьель переходят на SYSDBA только
|
||||
// при вызове от dbo (джоба SQL Agent); вызванные bj, они работали правами bj_user, и Fancy отказывал:
|
||||
// «Создание документа запрещено для данного пользователя» (FU_HAVE_RIGHT пропускает только SYSDBA%;
|
||||
// 22.10.2026, первый боевой входящий перевод на 9). С EXECUTE AS на JOB обработка идёт от SYSDBA при любом
|
||||
// способе запуска — джобой SQL Agent или из bj.
|
||||
func depoProcInstallBody(f FancyMSSQLSettings, name string) string {
|
||||
body := depoProcEffective(f, name)
|
||||
if name != "FTV_M2M_JOB" || withExecAsRe.MatchString(body) {
|
||||
return body
|
||||
}
|
||||
user := depoProcExecAsUser(f)
|
||||
if !depoLoginRe.MatchString(user) {
|
||||
return body
|
||||
}
|
||||
loc := procAsLineRe.FindStringIndex(body)
|
||||
if loc == nil {
|
||||
return body
|
||||
}
|
||||
return body[:loc[0]] + "with execute as '" + user + "'\n" + body[loc[0]:]
|
||||
}
|
||||
|
||||
var (
|
||||
withExecAsRe = regexp.MustCompile(`(?i)\bwith\s+execute\s+as\b`)
|
||||
procAsLineRe = regexp.MustCompile(`(?im)^[ \t]*as[ \t]*\r?$`) // строка «as» перед телом процедуры
|
||||
)
|
||||
|
||||
// depoProcOrderText — порядок установки коротко: WIRING→OPERATION→UPDATE_HANDBOOK→…
|
||||
func depoProcOrderText(sep string) string {
|
||||
var parts []string
|
||||
@@ -103,7 +130,7 @@ func depoProcsHash(f FancyMSSQLSettings) string {
|
||||
}
|
||||
h.Write([]byte("grant db_datawriter\n")) // 22.10.2026: роль записи логину bj — новый отпечаток, плашка на установках
|
||||
for _, p := range depoProcInstallOrder {
|
||||
h.Write([]byte(p.Name + "\n" + strings.TrimSpace(depoProcEffective(f, p.Name)) + "\n"))
|
||||
h.Write([]byte(p.Name + "\n" + strings.TrimSpace(depoProcInstallBody(f, p.Name)) + "\n"))
|
||||
}
|
||||
return hex.EncodeToString(h.Sum(nil))[:16]
|
||||
}
|
||||
@@ -141,7 +168,7 @@ func depoProcsScriptFor(f FancyMSSQLSettings, db, login string) string {
|
||||
fmt.Fprintf(&b, "/* ===== структура: %s ===== */\n%s;\nGO\n\n", fx.Name, fx.SQL)
|
||||
}
|
||||
for _, p := range depoProcInstallOrder {
|
||||
body := depoProcEffective(f, p.Name)
|
||||
body := depoProcInstallBody(f, p.Name)
|
||||
if strings.TrimSpace(body) == "" {
|
||||
continue
|
||||
}
|
||||
@@ -173,7 +200,7 @@ func depoProcsInstallInto(ctx context.Context, adm, f FancyMSSQLSettings, dbName
|
||||
}
|
||||
}
|
||||
for _, p := range depoProcInstallOrder {
|
||||
body := depoProcEffective(f, p.Name)
|
||||
body := depoProcInstallBody(f, p.Name)
|
||||
if strings.TrimSpace(body) == "" {
|
||||
return fmt.Errorf("пустой текст процедуры %s", p.Name)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user