diff --git a/deploy/linux/sbin/bj-igate-admin b/deploy/linux/sbin/bj-igate-admin index 30d36d9..107b38e 100755 --- a/deploy/linux/sbin/bj-igate-admin +++ b/deploy/linux/sbin/bj-igate-admin @@ -331,7 +331,11 @@ SQL mine=false; [ -f "$CONF" ] && grep -q "^$B" "$CONF" && mine=true u=$( [ "$mine" = true ] && sed -n "/^$B/,/^$E/p" "$CONF" | sed -n 's/^ *valid users *= *//p' | head -1 ) [ "$manual" = true ] && [ -z "$u" ] && u=$(sed -n '/^\[igate_exchange\]/,/^\[/p' "$CONF" | sed -n 's/^ *valid users *= *//p' | head -1) - echo "{\"ok\":true,\"on\":$( [ "$mine" = true ] || [ "$manual" = true ] && echo true || echo false),\"manual\":$manual,\"user\":$(q "$u"),\"smbd\":$(q "$(systemctl is-active smbd 2>/dev/null)")}"; exit 0 + # куда подключаться из проводника: адрес и имя сервера, открытые папки (test3 / prod) + ip=$(hostname -I 2>/dev/null | awk '{print $1}'); hn=$(hostname -s 2>/dev/null) + sh=""; [ "$mine" = true ] && for n in $(sed -n "/^$B/,/^$E/p" "$CONF" | sed -n 's/^\[\(.*\)\]$/\1/p'); do sh="$sh${sh:+,}$(q "$n")"; done + [ "$manual" = true ] && [ -z "$sh" ] && sh=$(q igate_exchange) + echo "{\"ok\":true,\"on\":$( [ "$mine" = true ] || [ "$manual" = true ] && echo true || echo false),\"manual\":$manual,\"user\":$(q "$u"),\"smbd\":$(q "$(systemctl is-active smbd 2>/dev/null)"),\"ip\":$(q "$ip"),\"host\":$(q "$hn"),\"shares\":[$sh]}"; exit 0 fi [ "$manual" = true ] && err "папка igate_exchange уже открыта вручную в $CONF — bj её не меняет; чтобы управлять из bj, уберите её из smb.conf" if [ "$on" != true ]; then diff --git a/internal/lkgateway/m2mauto.go b/internal/lkgateway/m2mauto.go index 761d874..e2c6a3e 100644 --- a/internal/lkgateway/m2mauto.go +++ b/internal/lkgateway/m2mauto.go @@ -32,6 +32,17 @@ type M2MAutoSettings struct { ChangedBy string `json:"changed_by,omitempty"` } +// migrateM2MAutoDefault — автоматический режим включён по умолчанию (решение 07.10.2026: «Оператор» — запасной +// режим). Установка, где режим ни разу не выбирали, получает «автоматически» с моментом включения сейчас: берутся +// только переводы, пришедшие не раньше чем за сутки до этого. Явный выбор (есть ChangedAt) не трогается. +func migrateM2MAutoDefault(s *Settings, now time.Time) bool { + if s.M2MAuto.Enabled || !s.M2MAuto.ChangedAt.IsZero() { + return false + } + s.M2MAuto = M2MAutoSettings{Enabled: true, ChangedAt: now, ChangedBy: "по умолчанию"} + return true +} + func (r *RuntimeConfig) UpdateM2MAuto(s M2MAutoSettings) error { r.mu.Lock() r.data.M2MAuto = s diff --git a/internal/lkgateway/m2mautodefault_test.go b/internal/lkgateway/m2mautodefault_test.go new file mode 100644 index 0000000..31bc3c3 --- /dev/null +++ b/internal/lkgateway/m2mautodefault_test.go @@ -0,0 +1,33 @@ +package lkgateway + +import ( + "os" + "path/filepath" + "testing" +) + +// Автоматический режим M2M — по умолчанию: где режим не выбирали, он включается и запоминается; +// явный выбор «Оператор» остаётся. +func TestM2MAutoDefaultOn(t *testing.T) { + dir := t.TempDir() + fresh := filepath.Join(dir, "fresh.json") + _ = os.WriteFile(fresh, []byte(`{"nsd":{"profile":"test3-gost"}}`), 0o600) + rc, err := NewRuntimeConfig(fresh) + if err != nil { + t.Fatal(err) + } + a := rc.Snapshot().M2MAuto + if !a.Enabled || a.ChangedAt.IsZero() || a.ChangedBy != "по умолчанию" { + t.Fatalf("не включён по умолчанию: %+v", a) + } + rc2, _ := NewRuntimeConfig(fresh) // записано: при следующем запуске момент включения тот же + if !rc2.Snapshot().M2MAuto.ChangedAt.Equal(a.ChangedAt) { + t.Fatal("момент включения не сохранился") + } + manual := filepath.Join(dir, "manual.json") + _ = os.WriteFile(manual, []byte(`{"m2m_auto":{"enabled":false,"changed_at":"2026-10-01T10:00:00Z","changed_by":"admin"}}`), 0o600) + rc3, _ := NewRuntimeConfig(manual) + if rc3.Snapshot().M2MAuto.Enabled { + t.Fatal("явный выбор «Оператор» перезаписан") + } +} diff --git a/internal/lkgateway/runtimeconfig.go b/internal/lkgateway/runtimeconfig.go index 75512dd..733f1ad 100644 --- a/internal/lkgateway/runtimeconfig.go +++ b/internal/lkgateway/runtimeconfig.go @@ -1,6 +1,7 @@ package lkgateway import ( + "log" "encoding/json" "errors" "os" @@ -364,10 +365,16 @@ func NewRuntimeConfig(path string) (*RuntimeConfig, error) { path = filepath.Join(home, ".bj", "setup.json") } rc := &RuntimeConfig{path: path} - if err := rc.load(); err != nil && !errors.Is(err, os.ErrNotExist) { - return nil, err + loadErr := rc.load() + if loadErr != nil && !errors.Is(loadErr, os.ErrNotExist) { + return nil, loadErr } migrateNotifyRoutes(&rc.data) // и на новой установке: версия маршрутов сохранится с первой записью настроек + if migrateM2MAutoDefault(&rc.data, time.Now()) && loadErr == nil { + if err := rc.save(); err != nil { // момент включения — отсчёт «за сутки до» для автоматики; должен пережить перезапуск + log.Printf("setup: автоматический режим M2M по умолчанию не записан: %v", err) + } + } // Гарантируем разумные дефолты. if rc.data.Crypto.Provider == "" { rc.data.Crypto.Provider = "stub" diff --git a/internal/lkgateway/web/templates/admin_setup.html b/internal/lkgateway/web/templates/admin_setup.html index 753b56c..8f5ba50 100644 --- a/internal/lkgateway/web/templates/admin_setup.html +++ b/internal/lkgateway/web/templates/admin_setup.html @@ -819,6 +819,25 @@ {{end}} +
bj шлёт значение на элемент типа Zabbix trapper (протокол zabbix_sender). В Zabbix заведите host и item-trapper с этим ключом, затем триггер по значению — уведомления настроит сам Zabbix.
Последняя проверка: {{.Settings.Alerts.Zabbix.LastMsg}}
{{end}} +Фоновые компоненты под самоконтролем: при сбое перезапускаются автоматически, при зависании — перезапуск всего сервиса и запись в «Новости». Ниже — живой статус.
@@ -888,28 +907,10 @@ {{/* ============ ОПОВЕЩЕНИЯ ============ */}}Системные события (сбой или зависание фонового компонента, аварийный перезапуск) всегда попадают в ленту «Новости». Дополнительно их можно доставлять наружу — на почту оператору и/или в мониторинг Zabbix, чтобы узнать о проблеме, даже когда интерфейс bj никто не открыл.
+Кому и о чём bj пишет на почту: администратору системы — о сбоях и обновлениях, отделам — о переводах и поручениях. Все события видны и в ленте «Новости»; передать их в мониторинг Zabbix — Настройка → Диагностика.
{{template "smtpCard" .}} -bj шлёт значение на элемент типа Zabbix trapper (протокол zabbix_sender). В Zabbix заведите host и item-trapper с этим ключом, затем триггер по значению — уведомления настроит сам Zabbix.
Последняя проверка: {{.Settings.Alerts.Zabbix.LastMsg}}
{{end}} -Сначала — тестовый контур TEST3; когда переводы на нём проходят, переходите на боевой. У каждого контура свой ключ.
-