diff --git a/internal/lkgateway/admin.go b/internal/lkgateway/admin.go index e670f45..ccc2174 100644 --- a/internal/lkgateway/admin.go +++ b/internal/lkgateway/admin.go @@ -53,6 +53,8 @@ var templateFuncs = template.FuncMap{ "quikCodeMap": quikClientCodeMapText, "curUser": authTemplateFuncs["curUser"], "can": authTemplateFuncs["can"], + "devOn": authTemplateFuncs["devOn"], + "devLicensed": authTemplateFuncs["devLicensed"], "authOpen": authOpen, "roleTitle": roleTitle, "stageCls": func(r depoQueueRow) string { c, _ := r.StageRu(); return c }, diff --git a/internal/lkgateway/auth.go b/internal/lkgateway/auth.go index 3b2bf07..e6ab9bb 100644 --- a/internal/lkgateway/auth.go +++ b/internal/lkgateway/auth.go @@ -1272,15 +1272,18 @@ func registerUsersSetup(mux *http.ServeMux, h *setupHandlers) { mux.HandleFunc("/admin/setup/auth", h.saveAuth) mux.HandleFunc("/admin/setup/auth/test", h.testAD) mux.HandleFunc("/admin/setup/auth/recheck", h.recheckAD) + mux.HandleFunc("/admin/dev-toggle", devToggle) // личный выключатель режима разработки } // ---------- функции шаблонов ---------- // authTemplateFuncs — заглушки, переопределяются в render на текущего пользователя. var authTemplateFuncs = template.FuncMap{ - "curUser": func() *User { return nil }, - "can": func(perm string) bool { return true }, - "authOpen": authOpen, + "curUser": func() *User { return nil }, + "can": func(perm string) bool { return true }, + "authOpen": authOpen, + "devOn": func() bool { return devMode(globalRC) }, // режим действует для текущего пользователя + "devLicensed": func() bool { return devMode(globalRC) }, // режим разрешён лицензией (для баннера) } // renderFor — выполняет layout с функциями, привязанными к текущему пользователю. @@ -1290,11 +1293,14 @@ func renderFor(w http.ResponseWriter, t *template.Template, data any) error { if err != nil { return t.ExecuteTemplate(w, "layout", data) } + on := devOnFor(u) t2.Funcs(template.FuncMap{ - "curUser": func() *User { return u }, + "curUser": func() *User { return u }, + "devOn": func() bool { return on }, + "devLicensed": func() bool { return devMode(globalRC) }, "can": func(perm string) bool { if perm == "dev" { - return devMode(globalRC) && (authOpen() || u.Can("settings")) + return on && (authOpen() || u.Can("settings")) } if authOpen() { return true diff --git a/internal/lkgateway/devbanner.go b/internal/lkgateway/devbanner.go new file mode 100644 index 0000000..93180c3 --- /dev/null +++ b/internal/lkgateway/devbanner.go @@ -0,0 +1,57 @@ +package lkgateway + +// devbanner.go — баннер режима разработки в шапке. +// +// Режим разработки разрешает сервер лицензий (dev_until в ключе). Пока он разрешён, в +// шапке висит баннер; нажатие на него выключает режим визуально для этого пользователя +// (служебные разделы прячутся, имитации не показываются) и включает обратно. Это личная +// настройка сотрудника, а не состояние системы: лицензия по-прежнему разрешает режим. +// Когда лицензия режим не разрешает, баннера нет и выключатель ни на что не влияет. + +import ( + "net/http" + "sync" +) + +// devOff — пользователи, выключившие режим разработки у себя (по логину; без +// авторизации — пустой логин). Хранится в памяти: после перезапуска режим снова включён. +var devOff = struct { + mu sync.Mutex + m map[string]bool +}{m: map[string]bool{}} + +func devUserKey(u *User) string { + if u == nil { + return "" + } + return u.Login +} + +// devOnFor — режим разработки действует для пользователя: разрешён лицензией и не выключен им. +func devOnFor(u *User) bool { + if !devMode(globalRC) { + return false + } + devOff.mu.Lock() + defer devOff.mu.Unlock() + return !devOff.m[devUserKey(u)] +} + +// devToggle — POST /admin/dev-toggle: переключить режим у себя и вернуться на ту же страницу. +func devToggle(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "method", http.StatusMethodNotAllowed) + return + } + if devMode(globalRC) { + key := devUserKey(currentUser(w)) + devOff.mu.Lock() + devOff.m[key] = !devOff.m[key] + devOff.mu.Unlock() + } + dest := safeReturnPath(r.FormValue("return_to")) + if dest == "" { + dest = "/admin" + } + http.Redirect(w, r, dest, http.StatusSeeOther) +} diff --git a/internal/lkgateway/web/templates/admin_claim.html b/internal/lkgateway/web/templates/admin_claim.html index d2c5c08..7807048 100644 --- a/internal/lkgateway/web/templates/admin_claim.html +++ b/internal/lkgateway/web/templates/admin_claim.html @@ -58,7 +58,7 @@ {{end}} -{{if .DevMode}}{{with .Claim.TestResult}} +{{if devOn}}{{with .Claim.TestResult}}
В трансферных таблицах пока нет переводов. Они появятся при входящем/исходящем переводе M2M{{if .DevMode}} или при прогоне «Тестирование M2M → выгрузка истории в DEPO»{{end}}.
+В трансферных таблицах пока нет переводов. Они появятся при входящем/исходящем переводе M2M{{if devOn}} или при прогоне «Тестирование M2M → выгрузка истории в DEPO»{{end}}.
{{end}} diff --git a/internal/lkgateway/web/templates/admin_help.html b/internal/lkgateway/web/templates/admin_help.html index c7ba487..6802582 100644 --- a/internal/lkgateway/web/templates/admin_help.html +++ b/internal/lkgateway/web/templates/admin_help.html @@ -26,7 +26,7 @@ИШ НРД ({{if .DevMode}}профили GUEST/TEST3/PROD{{else}}тестовый и боевой контуры{{end}}), команда Fansy (ETL в staging), уведомления (e-mail, Yandex Messenger, Telegram), порядок согласования.
+ИШ НРД ({{if devOn}}профили GUEST/TEST3/PROD{{else}}тестовый и боевой контуры{{end}}), команда Fansy (ETL в staging), уведомления (e-mail, Yandex Messenger, Telegram), порядок согласования.
Исходящий перевод по бумажному поручению клиента: ввод, сверка с учётной и торговой системами, обязательные отметки, отправка, поручение 16, документы НРД.
- {{if .DevMode}} + {{if devOn}}Робот НРД на TEST3 (код MC0012500000), 4 тестовых сценария (отказ / принять все / частично / встречный перевод), управление через DocumentSeries и DocumentNumber, тестовые наборы депозитариев и кодов ошибок.
Полная схема: bj-server → ИШ (на Astra Linux ВМ) → ONYX (НРД) → {{if .DevMode}}робот-автотест{{else}}депозитарий-контрагент{{end}}. Кто на чьей стороне, какое СКЗИ, какие сертификаты, FAQ.
+Полная схема: bj-server → ИШ (на Astra Linux ВМ) → ONYX (НРД) → {{if devOn}}робот-автотест{{else}}депозитарий-контрагент{{end}}. Кто на чьей стороне, какое СКЗИ, какие сертификаты, FAQ.
Только от УЦ Московской Биржи (ca.moex.com). Сертификаты других УЦ ИШ не примет. УЦ МБ выпускает сертификаты только для организаций, подключённых к ЭДО НРД (по договору).
Включать нужно один вариант, иначе процедура будет вызываться параллельно из двух мест. Просьба к разработчику: сделать FTV_M2M_JOB безопасной при повторном/параллельном вызове (обработка только строк со STATE='TODO', блокировка строки на время обработки) — тогда случайное двойное включение не навредит.
Кнопкой «Выгрузить историю в DEPO» на вкладке «Тестирование» bj записал в трансферные таблицы все переводы, проведённые на TEST3 (робот НРД и банк Зенит): 78 переводов, 252 события с реальными датами. Джоба bj2depo создала по каждому документ в DEPO (D_CLISER_M2M + строки), сама определила контрагента, депонента, бумагу и место хранения. Что при этом выяснилось:
curl -u "lk-user:lk-password" \ -H "Content-Type: application/json" \ http://10.10.10.22:8080/api/v1/back_office/claims/- {{if .DevMode}}
На M2 (дев-стенд) аутентификация отключена; включится на M3 — параллельно с подключением реального ЛК.
{{end}} + {{if devOn}}На M2 (дев-стенд) аутентификация отключена; включится на M3 — параллельно с подключением реального ЛК.
{{end}}На дев-стенде доступен lk-emulator на порту 8083 — имитация ЛК. Он сам регистрирует свой URL в bj-server как callback-приёмник.
@@ -146,8 +146,8 @@ LISTEN=127.0.0.1:8099 ./bj-lk {{end}}ЛК должен подписать заявление XMLDSig (ГОСТ или RSA) и положить в поле signed_document (base64). Мы проверяем подпись через crypto-service — см. инструкцию по криптографии.
На M2 проверка подписи отключена (stub). На M3-M4 включится после подключения СКЗИ.
{{end}} + {{if devOn}}На M2 проверка подписи отключена (stub). На M3-M4 включится после подключения СКЗИ.
{{end}}https://gost-t3.nsd.ru/onyx-ms/OnyxEdoWSService/OnyxEdoБез настроенного ИШ система работает в mock-режиме: bj-server эмитирует синтетический Decision через 3 секунды для каждой заявки. Это удобно для дев-демо и не требует подключения к НРД.
{{else}}Пока ИШ не настроен, обмен с НРД не выполняется: поручения в НРД не отправляются.
{{end}} + {{if devOn}}Без настроенного ИШ система работает в mock-режиме: bj-server эмитирует синтетический Decision через 3 секунды для каждой заявки. Это удобно для дев-демо и не требует подключения к НРД.
{{else}}Пока ИШ не настроен, обмен с НРД не выполняется: поручения в НРД не отправляются.
{{end}}| Внешняя сторона | Что согласовать |
|---|---|
| НРД (Национальный расчётный депозитарий) | {{if .DevMode}}Тестовые сертификаты GUEST/TEST3{{else}}Сертификаты для тестового и боевого контуров{{end}}, дистрибутив ИШ, доступ к личному кабинету УЦ НРД |
| Команда ЛК (ESIA Finance) | Базовый URL ЛК, Basic-auth учётные данные, {{if .DevMode}}очерёдность подключения (сначала эмулятор, потом реальный ЛК){{else}}окружения ЛК (тест и бой){{end}} |
| НРД (Национальный расчётный депозитарий) | {{if devOn}}Тестовые сертификаты GUEST/TEST3{{else}}Сертификаты для тестового и боевого контуров{{end}}, дистрибутив ИШ, доступ к личному кабинету УЦ НРД |
| Команда ЛК (ESIA Finance) | Базовый URL ЛК, Basic-auth учётные данные, {{if devOn}}очерёдность подключения (сначала эмулятор, потом реальный ЛК){{else}}окружения ЛК (тест и бой){{end}} |
| Команда Fansy | Контракт docs/fansy-contract/v1/, SLA, окна обслуживания, IP-allowlist |
| Брокеры-контрагенты MOST | БКС (ИНН 5406121446), Ренессанс (7709258228), Альфа-Банк (7728168971){{if .DevMode}} — уже в seed{{end}} |
| Брокеры-контрагенты MOST | БКС (ИНН 5406121446), Ренессанс (7709258228), Альфа-Банк (7728168971){{if devOn}} — уже в seed{{end}} |
Переводов ещё нет. {{if .DevMode}}Нажмите «Новый перевод», чтобы создать первый.{{else}}Они появятся с заявками из личного кабинета, а поручение клиента можно ввести вручную — «Новый перевод».{{end}}
+Переводов ещё нет. {{if devOn}}Нажмите «Новый перевод», чтобы создать первый.{{else}}Они появятся с заявками из личного кабинета, а поручение клиента можно ввести вручную — «Новый перевод».{{end}}
{{end}}Входящих переводов нет. Они появляются, когда другая сторона инициирует перевод к нам{{if .DevMode}} (напр. робот НРД в сценарии 3333 «Выступить принимающей стороной»){{end}}.
+Входящих переводов нет. Они появляются, когда другая сторона инициирует перевод к нам{{if devOn}} (напр. робот НРД в сценарии 3333 «Выступить принимающей стороной»){{end}}.
{{end}}🔄 Страница обновляется автоматически при появлении нового входящего.
Проверки по регламенту депозитария (инвестор, торговый счёт депо, бумага на обслуживании, договор не ИИС, блокировки). Ответ контрагенту НЕ отправлен — это только рекомендация; она подставлена в форму ниже, проверьте и нажмите «Отправить решение».
@@ -73,7 +73,7 @@Решение уже отправлено {{if .DevMode}}роботу{{else}}контрагенту через НРД{{end}}. Ниже — что было выбрано по каждой бумаге.
+Решение уже отправлено {{if devOn}}роботу{{else}}контрагенту через НРД{{end}}. Ниже — что было выбрано по каждой бумаге.
| ReferenceId | Код НРД / ISIN | Кол-во | Счёт зачисления | Решение |
|---|
По каждой бумаге выберите: принять (зачислим на наш депо-счёт из настроек НРД) или отказать (с кодом отказа). Решение уйдёт {{if .DevMode}}роботу{{else}}контрагенту через НРД{{end}} одним сообщением M2MTransferDecision.
+По каждой бумаге выберите: принять (зачислим на наш депо-счёт из настроек НРД) или отказать (с кодом отказа). Решение уйдёт {{if devOn}}роботу{{else}}контрагенту через НРД{{end}} одним сообщением M2MTransferDecision.
- {{if .DevMode}}{{/* подсказки по сценариям робота НРД — только в режиме разработки */}} + {{if devOn}}{{/* подсказки по сценариям робота НРД — только в режиме разработки */}}