90aacf9ef4
- ключ, подключённый мастером ключа, засчитывается сразу и в мастере, и на главной (сверка справочника шлюза отстаёт) - точка в заголовке шага — то же «выполнено», что в колонке (с «Настроить позже») - выход из мастера — «Выйти из мастера», не «Настроить позже» - шаг «Обновление» — сразу после «Лицензии»; на шаге 1 — указание на него, без второй кнопки - «Далее»/«Назад» со шага вне пути (сделан установщиком) — соседи по порядку глав - последний шаг при несделанном обязательном — «Вернуться к шагу …», не «Перейти к работе» Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
99 lines
4.2 KiB
Go
99 lines
4.2 KiB
Go
package lkgateway
|
|
|
|
// Шаги настройки — одни и те же для мастера и дашборда: дашборд пишет «Требуется настройка — N из M»
|
|
// ровно по шагам мастера (с учётом лицензии), а не по отдельному списку проверок.
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/cryptocli"
|
|
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/nsdadapter"
|
|
)
|
|
|
|
type SetupStep struct {
|
|
Step int
|
|
Title string
|
|
Done bool
|
|
}
|
|
|
|
var setupProbeCache = struct {
|
|
sync.Mutex
|
|
at time.Time
|
|
validata string
|
|
certs int
|
|
}{}
|
|
|
|
// setupProbes — версия Валидаты и число сертификатов (внешние вызовы) с кэшем на минуту.
|
|
func setupProbes(rc *RuntimeConfig) (string, int) {
|
|
setupProbeCache.Lock()
|
|
defer setupProbeCache.Unlock()
|
|
if time.Since(setupProbeCache.at) < time.Minute {
|
|
return setupProbeCache.validata, setupProbeCache.certs
|
|
}
|
|
ctx, cancel := context.WithTimeout(context.Background(), 4*time.Second)
|
|
defer cancel()
|
|
setupProbeCache.validata, _, _ = validataVersion(ctx)
|
|
setupProbeCache.certs = len(ownValidCerts(storeCertsForUI(rc.Snapshot())))
|
|
setupProbeCache.at = time.Now()
|
|
return setupProbeCache.validata, setupProbeCache.certs
|
|
}
|
|
|
|
// keyWizInstalled — мастер ключа дошёл до конца в этом запуске bj (ключ подключён, подпись подтверждена).
|
|
// Сверка справочника шлюза асинхронная и отстаёт; по этой отметке шаг «Ключ подписи» выполнен сразу —
|
|
// и в мастере, и в плашке на главной.
|
|
var keyWizInstalled atomic.Bool
|
|
|
|
// setupSteps — шаги мастера этой установки и выполнены ли они: ровно тот путь и те же
|
|
// правила, что в мастере (wizPath + wizDone), чтобы плашка на главной не расходилась с ним.
|
|
func setupSteps(rc *RuntimeConfig) []SetupStep {
|
|
validata, certs := setupProbes(rc)
|
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
|
defer cancel()
|
|
done := wizDone(ctx, rc, validata, certs > 0 || keyWizInstalled.Load())
|
|
path, _ := wizPath(rc, done, 0)
|
|
var steps []SetupStep
|
|
for _, n := range path {
|
|
steps = append(steps, SetupStep{n, wizStepTitles[n], done[n]})
|
|
}
|
|
return steps
|
|
}
|
|
|
|
// ownValidCerts — свои сертификаты (с закрытым ключом), срок которых не истёк: только они делают шаг
|
|
// «Сертификаты» выполненным (сертификаты НРД и УЦ в хранилище есть и без ключа организации).
|
|
func ownValidCerts(certs []cryptocli.Certificate) []cryptocli.Certificate {
|
|
var out []cryptocli.Certificate
|
|
now := time.Now()
|
|
for _, c := range certs {
|
|
if c.HasPrivateKey && (c.NotAfter.IsZero() || c.NotAfter.After(now)) {
|
|
out = append(out, c)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
// doneOrg — организация и её депозитарные реквизиты в НРД заданы (без них перевод не сформировать).
|
|
func doneOrg(s Settings) bool {
|
|
return orgCode(s) != "" && orgINN(s) != "" && s.NSD.DeponentCode != "" && s.NSD.AccountID != "" && s.NSD.SectionID != ""
|
|
}
|
|
|
|
// doneQuik — подключение к МНП проверено и ключевые объекты M2M видны.
|
|
func doneQuik(s Settings) bool { return s.Quik.Verified && s.Quik.M2MMissing == "" }
|
|
|
|
// doneNSD — адрес ИШ задан и профиль известен bj (неизвестный профиль — молча режим имитации).
|
|
func doneNSD(s Settings) bool {
|
|
if s.NSD.IGWBaseURL == "" || s.NSD.Profile == "" {
|
|
return false
|
|
}
|
|
_, err := nsdadapter.LookupProfile(s.NSD.Profile)
|
|
return err == nil
|
|
}
|
|
|
|
// doneAlerts — оповещения уходят наружу (почта или Zabbix) и резервные копии включены.
|
|
func doneAlerts(s Settings) bool {
|
|
smtp := s.Alerts.SMTP
|
|
return ((smtp.Enabled && smtp.Host != "" && smtp.To != "") || s.Alerts.Zabbix.Enabled) && s.Backup.Enabled
|
|
}
|