Учёт DEPO: имя базы обязательно, bj базу по серверу не ищет

Имя базы DEPO задаёт клиент — скрипт и подготовка логином администратора
работают только с ней. Автопоиск по серверу убран (экран, скрипт, подготовка,
проверка подключения, старый экран conn), выбор из нескольких найденных баз —
тоже. Вместо поиска — защита от опечатки: скрипт (SQL Server и PostgreSQL),
подготовка и проверка подключения сначала убеждаются, что в названной базе
есть учётные таблицы OD_FACES и OD_RESTS, иначе останавливаются, ничего не
меняя.

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:18:15 +03:00
parent 237203f29a
commit 35f70a1b49
8 changed files with 118 additions and 219 deletions
+21 -65
View File
@@ -49,15 +49,15 @@ func wizDepoGo(w http.ResponseWriter, r *http.Request, sub, msg string, ok bool)
}
// wizardDepoConn — POST /admin/setup/wizard-depo/conn: сохранить подключение и сразу проверить его. Имя базы
// DEPO клиент не вводит: bj находит её на сервере сам (depoDiscover); вручную — только в «Дополнительно».
// DEPO клиент задаёт сам — bj по серверу не ищет, только проверяет, что это база DEPO.
func (h *setupHandlers) wizardDepoConn(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost || !requireDepo(w, r) {
return
}
s := h.fancyFromForm(r)
manual := strings.TrimSpace(r.FormValue("depo_database"))
if manual != "" && !validDBName(manual) {
wizDepoGo(w, r, "conn", "имя базы DEPO — только латинские буквы, цифры и _, начинается с буквы", false)
if !validDBName(manual) {
wizDepoGo(w, r, "conn", "укажите имя базы DEPO — латинские буквы, цифры и _, начинается с буквы", false)
return
}
if s.Server == "" || s.User == "" {
@@ -74,23 +74,10 @@ func (h *setupHandlers) wizardDepoConn(w http.ResponseWriter, r *http.Request) {
wizDepoGo(w, r, "conn", "к серверу подключиться не удалось — "+err.Error()+". Проверьте адрес, порт, логин и пароль.", false)
return
}
db, how := manual, "указана вручную"
if db == "" {
found, err := depoDiscover(ctx, s)
switch {
case err != nil:
wizDepoGo(w, r, "conn", "сервер отвечает, но список баз получить не удалось — "+err.Error()+". Укажите базу DEPO вручную (ниже, «Дополнительно»).", false)
return
case len(found) == 0:
wizDepoGo(w, r, "conn", "на сервере не найдена база учёта DEPO (Fancy), доступная логину "+s.User+
": нет базы с таблицами "+strings.Join(depoMarkerTables, " и ")+". Проверьте, что логину выдан доступ к базе DEPO, или укажите её вручную («Дополнительно»).", false)
return
case len(found) > 1:
http.Redirect(w, r, "/admin/wizard?step=3&sub=conn&cands="+url.QueryEscape(strings.Join(found, ","))+
"&flash="+url.QueryEscape("На сервере несколько баз DEPO — выберите, с какой работает bj."), http.StatusSeeOther)
return
}
db, how = found[0], "найдена на сервере"
db := manual
if err := depoCheckIsDepo(ctx, s, db); err != nil {
wizDepoGo(w, r, "conn", err.Error(), false)
return
}
if db != s.DepoDatabase {
s.DepoTablesCheck, s.DepoTablesCheckOK = "", false
@@ -100,22 +87,7 @@ func (h *setupHandlers) wizardDepoConn(w http.ResponseWriter, r *http.Request) {
wizDepoGo(w, r, "conn", "не сохранилось: "+err.Error(), false)
return
}
if _, err := fancyPing(ctx, s, db); err != nil {
wizDepoGo(w, r, "conn", "сервер отвечает, но база "+db+" недоступна этим логином — "+err.Error(), false)
return
}
wizDepoGo(w, r, "tables", "подключение к "+s.Server+" работает; база DEPO — "+db+" ("+how+")", true)
}
// depoCands — базы DEPO для выбора на экране «Подключение» (из адреса после поиска на сервере).
func depoCands(v string) []string {
var out []string
for _, n := range strings.Split(v, ",") {
if n = strings.TrimSpace(n); validDBName(n) {
out = append(out, n)
}
}
return out
wizDepoGo(w, r, "tables", "подключение к "+s.Server+" работает; база DEPO — "+db, true)
}
// wizardDepoTables — POST /admin/setup/wizard-depo/tables: создать таблицы (bj) или проверить созданные
@@ -236,8 +208,8 @@ func (h *setupHandlers) wizardDepoRecheck(w http.ResponseWriter, r *http.Request
wizDepoGo(w, r, "done", "всё перепроверено", true)
}
// depoSetupForm — сервер DEPO и способ обработки из формы экрана «Подготовка базы» (логин bj не трогается;
// пустой адрес сервера не ошибка — скрипту он не нужен, подключению проверяют вызывающие).
// depoSetupForm — сервер DEPO, имя базы (обязательно) и способ обработки из формы экрана «Подготовка базы»
// (логин bj не трогается; пустой адрес сервера не ошибка — скрипту он не нужен, подключению проверяют вызывающие).
func (h *setupHandlers) depoSetupForm(r *http.Request) (FancyMSSQLSettings, string, bool, string) {
s := h.rc.Snapshot().Fancy
dbType := "mssql"
@@ -263,15 +235,12 @@ func (h *setupHandlers) depoSetupForm(r *http.Request) (FancyMSSQLSettings, stri
s.DepoJobMode = "sql-auto"
}
db := strings.TrimSpace(r.FormValue("depo_database"))
if db != "" && !validDBName(db) {
if db == "" { // bj по серверу базу не ищет: с какой базой работать, клиент говорит сам
return s, "", agent, "укажите имя базы DEPO — как она называется на сервере"
}
if !validDBName(db) {
return s, "", agent, "имя базы DEPO — только латинские буквы, цифры и _, начинается с буквы"
}
if db == "" {
db = s.DepoDatabase
}
if dbType == "postgres" && db == "" {
return s, "", agent, "для PostgreSQL укажите имя базы DEPO"
}
return s, db, agent, ""
}
@@ -374,13 +343,12 @@ func (h *setupHandlers) wizardDepoSetup(w http.ResponseWriter, r *http.Request)
return
}
depoEnsureLogin(&s)
found, err := depoSetupRun(ctx, s, db, au, r.FormValue("admin_password"), s.User, s.Password, agent)
if err != nil {
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)
return
}
s.DepoDatabase, s.DepoTablesMode = found, "auto"
note = "база " + found + " подготовлена: логин " + s.User + ", таблицы обмена, права"
s.DepoTablesMode = "auto"
note = "база " + db + " подготовлена: логин " + s.User + ", таблицы обмена, права"
if agent {
note += ", задание " + depoJobName
}
@@ -405,9 +373,7 @@ func (h *setupHandlers) wizardDepoSetup(w http.ResponseWriter, r *http.Request)
return
}
}
if db != "" {
s.DepoDatabase = db
}
s.DepoDatabase = db
if err := h.rc.UpdateFancy(s); err != nil {
wizDepoGo(w, r, "setup", "не сохранилось: "+err.Error(), false)
return
@@ -416,19 +382,9 @@ func (h *setupHandlers) wizardDepoSetup(w http.ResponseWriter, r *http.Request)
wizDepoGo(w, r, "setup", note+"войти логином "+s.User+" не удалось — "+quikErrorDetail(err)+". Выполнен ли скрипт на сервере "+s.Server+"?", false)
return
}
if s.DepoDatabase == "" { // база не указана и скрипт её нашёл сам — найти и нам
found, err := depoDiscover(ctx, s)
switch {
case err != nil || len(found) == 0:
wizDepoGo(w, r, "setup", "логину "+s.User+" не видна ни одна база DEPO — выполнен ли скрипт? Можно вписать имя базы в поле «Имя базы»", false)
return
case len(found) > 1:
http.Redirect(w, r, "/admin/wizard?step=3&sub=setup&cands="+url.QueryEscape(strings.Join(found, ","))+
"&flash="+url.QueryEscape("Логину bj видны несколько баз DEPO — выберите нужную и проверьте ещё раз."), http.StatusSeeOther)
return
}
s.DepoDatabase = found[0]
_ = h.rc.UpdateFancy(s)
if err := depoCheckIsDepo(ctx, s, db); err != nil { // имя базы задал клиент — та ли это база
wizDepoGo(w, r, "setup", note+err.Error(), false)
return
}
msg, ok := depoTablesCheck(ctx, s)
h.saveDepoTablesCheck(msg, ok)