Учёт DEPO: скрипт снова выполняется; логин bj виден в обоих способах; новые логин и пароль — только после проверки входа

- EXEC(...) в T-SQL склеивает только строки и переменные: REPLACE/QUOTENAME внутри
  давали ошибку 102, и SQL Server отклонял весь скрипт (.06.4–.06.6). Команда входа
  собирается в @sql заранее; тест ловит вызовы функций внутри EXEC; живая проверка
  синтаксиса на SQL Server без выполнения (SET PARSEONLY) — TestDepoSetupScriptParseLive.
- «Логин bj / Пароль bj» и в способе «Дать логин администратора»: на общем сервере
  bj_user может быть занят другим bj — подготовка сменила бы ему пароль. Предупреждение.
- Показ скрипта на странице ничего не сохраняет. Логин и пароль из выданного скрипта
  и из «Проверить подключение» хранятся черновиком (DepoNewUser/DepoNewPass) и
  становятся рабочими только после успешного входа: службы bj с неверным паролем
  за минуты блокировали логин на сервере (CHECK_POLICY) — у всех, кто им пользуется.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
zuevav
2026-10-06 15:35:36 +03:00
parent 13c252ae3d
commit 7af6cdf2f6
7 changed files with 190 additions and 27 deletions
+30 -8
View File
@@ -253,9 +253,10 @@ func depoEnsureLogin(s *FancyMSSQLSettings) {
}
}
// depoScriptCreds — логин и пароль bj с экрана «Отдать скрипт администратору» (поля видны и меняются;
// пустой пароль — bj придумает сам). Возвращает текст ошибки.
func depoScriptCreds(r *http.Request, s *FancyMSSQLSettings) string {
// depoBjCreds — логин и пароль bj с экрана подготовки. Видны в обоих способах — «логин администратора» и
// «скрипт»: на общем сервере SQL логин bj_user может быть уже занят другим bj (подготовка сменила бы ему
// пароль) — тогда вписывают другое имя. Пустой пароль — bj придумает сам. Возвращает текст ошибки.
func depoBjCreds(r *http.Request, s *FancyMSSQLSettings) string {
if u := strings.TrimSpace(r.FormValue("bj_user")); u != "" {
if !depoLoginRe.MatchString(u) {
return "логин bj — латинские буквы, цифры, точка, дефис и _"
@@ -289,7 +290,7 @@ func (h *setupHandlers) wizardDepoScript(w http.ResponseWriter, r *http.Request)
}
s, db, agent, bad := h.depoSetupForm(r)
if bad == "" {
bad = depoScriptCreds(r, &s)
bad = depoBjCreds(r, &s)
}
if bad != "" {
fail(bad)
@@ -297,8 +298,10 @@ func (h *setupHandlers) wizardDepoScript(w http.ResponseWriter, r *http.Request)
}
depoEnsureLogin(&s)
s.DepoTablesMode = "script"
if s.Server != "" { // скрипт собирается и до адреса сервера (экран обновляет его на ходу) — без адреса не сохраняем
if err := h.rc.UpdateFancy(s); err != nil {
// показ на странице (экран пересобирает скрипт на ходу) ничего не сохраняет; файл — уходит администратору:
// запомнить логин и пароль из него, но только черновиком — в работу они пойдут после проверки входа
if !view && s.Server != "" {
if err := h.rc.UpdateFancy(depoDraft(s, h.rc.Snapshot().Fancy)); err != nil {
fail("не сохранилось: " + err.Error())
return
}
@@ -318,12 +321,22 @@ func (h *setupHandlers) wizardDepoScript(w http.ResponseWriter, r *http.Request)
_, _ = w.Write([]byte(body))
}
// depoDraft — настройки экрана с логином и паролем bj черновиком: рабочими остаются прежние (saved), новые —
// в DepoNewUser/DepoNewPass до успешного входа.
func depoDraft(s, saved FancyMSSQLSettings) FancyMSSQLSettings {
d := s
d.User, d.Password = saved.User, saved.Password
d.DepoNewUser, d.DepoNewPass = s.User, s.Password
return d
}
// wizardDepoSetup — POST /admin/setup/wizard-depo/setup: подготовить базу (mode=auto — bj сам логином
// администратора), проверить после скрипта (mode=script) или с готовым логином (mode=existing).
func (h *setupHandlers) wizardDepoSetup(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost || !requireDepo(w, r) {
return
}
saved := h.rc.Snapshot().Fancy
s, db, agent, bad := h.depoSetupForm(r)
if bad == "" && s.Server == "" {
bad = "укажите адрес сервера DEPO"
@@ -342,6 +355,10 @@ func (h *setupHandlers) wizardDepoSetup(w http.ResponseWriter, r *http.Request)
wizDepoGo(w, r, "setup", "введите логин и пароль администратора SQL (они используются один раз и не сохраняются)", false)
return
}
if bad := depoBjCreds(r, &s); bad != "" {
wizDepoGo(w, r, "setup", bad, false)
return
}
depoEnsureLogin(&s)
if err := depoSetupRun(ctx, s, db, au, r.FormValue("admin_password"), s.User, s.Password, agent); err != nil {
wizDepoGo(w, r, "setup", "база не подготовлена — "+err.Error(), false)
@@ -363,7 +380,7 @@ func (h *setupHandlers) wizardDepoSetup(w http.ResponseWriter, r *http.Request)
s.User, s.Password = u, r.FormValue("password")
}
default: // script — администратор выполнил скрипт: логин и пароль bj — с экрана (они же в настройках)
if bad := depoScriptCreds(r, &s); bad != "" {
if bad := depoBjCreds(r, &s); bad != "" {
wizDepoGo(w, r, "setup", bad, false)
return
}
@@ -374,7 +391,7 @@ func (h *setupHandlers) wizardDepoSetup(w http.ResponseWriter, r *http.Request)
}
}
s.DepoDatabase = db
if err := h.rc.UpdateFancy(s); err != nil {
if err := h.rc.UpdateFancy(depoDraft(s, saved)); err != nil {
wizDepoGo(w, r, "setup", "не сохранилось: "+err.Error(), false)
return
}
@@ -382,6 +399,11 @@ func (h *setupHandlers) wizardDepoSetup(w http.ResponseWriter, r *http.Request)
wizDepoGo(w, r, "setup", note+"войти логином "+s.User+" не удалось — "+quikErrorDetail(err)+". Выполнен ли скрипт на сервере "+s.Server+"?", false)
return
}
s.DepoNewUser, s.DepoNewPass = "", "" // вход проверен — логин и пароль в работу
if err := h.rc.UpdateFancy(s); err != nil {
wizDepoGo(w, r, "setup", "не сохранилось: "+err.Error(), false)
return
}
if err := depoCheckIsDepo(ctx, s, db); err != nil { // имя базы задал клиент — та ли это база
wizDepoGo(w, r, "setup", note+err.Error(), false)
return