Мастер, QUIK: короткое письмо в ARQA с внешним адресом, памятка администратору, понятный выбор работы с QUIK
- Письмо в ARQA: организация просит подключить модуль неторговых поручений, выдать логин и пароль и разрешить подключение с нашего внешнего адреса — о bj и внутреннем устройстве ни слова. Внешний адрес bj узнаёт у сервера лицензий (GET /v1/ip, раз в час); пометка — убедиться, что адрес постоянный. - Под письмом — «Памятка администратору QUIK» (классы, логин InstrEu, справочник, перезапуск модуля) со ссылкой на подробную инструкцию. - Вместо свёрнутого «Автоматический цикл M2M — выключен · настроить» и справочника под раскрытием: после проверки подключения — «Как bj работает с QUIK»: «Только сверка» или «Автоматически» (+ торговый счёт), сохраняется сразу; справочник — строкой состояния с напоминанием о перезапуске. До проверки — одна строка. Тонкая настройка — в «Настройка → QUIK», мастер её не трогает. - Проверка МНП: ошибка сертификата (x509, «doesn't contain any IP SANs») — подсказка включить «Доверять сертификату сервера», «Дополнительно» раскрывается. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi
This commit is contained in:
@@ -462,6 +462,13 @@ func TestDumpOnboardingPages(t *testing.T) {
|
||||
h.renderWizard(w, httptest.NewRequest(http.MethodGet, fmt.Sprintf("/admin/wizard?step=%d", step), nil))
|
||||
_ = os.WriteFile(filepath.Join(dir, fmt.Sprintf("wizard-%02d.html", step)), w.Body.Bytes(), 0o644)
|
||||
}
|
||||
// шаг QUIK после проверки подключения — выбор «Как bj работает с QUIK»
|
||||
q := rc.Snapshot().Quik
|
||||
q.Server, q.User, q.Verified = "91.209.122.88", "BROKER_88", true
|
||||
_ = rc.UpdateQuik(q)
|
||||
w := httptest.NewRecorder()
|
||||
h.renderWizard(w, httptest.NewRequest(http.MethodGet, "/admin/wizard?step=5", nil))
|
||||
_ = os.WriteFile(filepath.Join(dir, "wizard-05-verified.html"), w.Body.Bytes(), 0o644)
|
||||
var b strings.Builder
|
||||
d := PrepareData{page: page{Title: "Подготовка модулей", Active: "wizard"}, Tenant: "АО «Пример Инвест»", Plan: "enterprise", Until: "поддержка до 06.10.2027", Next: "/admin/wizard?step=12", Flash: "Администратор создан."}
|
||||
if err := a.prepare.ExecuteTemplate(&b, "layout", d); err != nil {
|
||||
@@ -644,3 +651,82 @@ func TestSaveOrgWithRequisites(t *testing.T) {
|
||||
t.Fatalf("неверный счёт — ничего не сохраняется: %+v", s)
|
||||
}
|
||||
}
|
||||
|
||||
// Письмо в ARQA — коротко: организация просит подключить модуль, выдать логин и пароль и разрешить подключение
|
||||
// с нашего внешнего адреса; о bj и внутреннем устройстве ни слова. Внешний адрес неизвестен — место для него.
|
||||
func TestArqaLetter(t *testing.T) {
|
||||
publicIPState.Lock()
|
||||
publicIPState.ip, publicIPState.at = "195.239.71.22", time.Now()
|
||||
publicIPState.Unlock()
|
||||
defer func() {
|
||||
publicIPState.Lock()
|
||||
publicIPState.ip, publicIPState.at = "", time.Time{}
|
||||
publicIPState.Unlock()
|
||||
}()
|
||||
var s Settings
|
||||
s.NSD.OrgName, s.NSD.OrgINN, s.NSD.OrgCode = "ООО \"ИК \"Фонтвьель\"", "7703807489", "MC0413600000"
|
||||
l, ok := letterFor(s, "arqa")
|
||||
if !ok {
|
||||
t.Fatal("нет письма arqa")
|
||||
}
|
||||
for _, bad := range []string{"Bridge", "bj", "InstrEu", "sp_NewInstrSec", "M2MDepoRecipients", "10.10."} {
|
||||
if strings.Contains(l.Body, bad) {
|
||||
t.Fatalf("в письме лишнее %q:\n%s", bad, l.Body)
|
||||
}
|
||||
}
|
||||
for _, want := range []string{"7703807489", "просит", "логин и пароль", "с нашего адреса 195.239.71.22 [убедитесь, что это постоянный внешний адрес"} {
|
||||
if !strings.Contains(l.Body, want) {
|
||||
t.Fatalf("в письме нет %q:\n%s", want, l.Body)
|
||||
}
|
||||
}
|
||||
publicIPState.Lock()
|
||||
publicIPState.ip = ""
|
||||
publicIPState.Unlock()
|
||||
if l, _ := letterFor(s, "arqa"); !strings.Contains(l.Body, "[постоянный внешний IP-адрес вашего сервера") {
|
||||
t.Fatalf("внешний адрес неизвестен — место для него:\n%s", l.Body)
|
||||
}
|
||||
}
|
||||
|
||||
// Мастер, QUIK: один выбор вместо набора флажков; тонкая настройка не трогается. Ошибка сертификата — подсказка.
|
||||
func TestQuikModeAndCertHint(t *testing.T) {
|
||||
priv := testLicenseKey(t)
|
||||
rc := testRC(t)
|
||||
now := time.Now().UTC()
|
||||
tok := signTestLicense(t, priv, &license.License{Schema: 1, ID: "lic-1", Tenant: "Тест", Product: "bj-server", Plan: license.PlanPro,
|
||||
IssuedAt: now, ExpiresAt: now.Add(30 * 24 * time.Hour), ContractUntil: now.AddDate(1, 0, 0), Features: []string{"updates", "quik-mnp"}})
|
||||
if err := rc.SaveLicense(LicenseSettings{Key: tok}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
old := globalRC
|
||||
globalRC = rc
|
||||
defer func() { globalRC = old }()
|
||||
q := rc.Snapshot().Quik
|
||||
q.PollTerminal, q.SecOut, q.ClientCodeMap = true, "RUROUTM2M", map[string]string{"БР-1": "BR1"}
|
||||
if err := rc.UpdateQuik(q); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h := &setupHandlers{rc: rc}
|
||||
post := func(form url.Values) string {
|
||||
r := httptest.NewRequest(http.MethodPost, "/admin/setup/quik/mode", strings.NewReader(form.Encode()))
|
||||
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
r.Header.Set("X-BJ-Ajax", "1")
|
||||
w := httptest.NewRecorder()
|
||||
h.saveQuikMode(w, r)
|
||||
return w.Body.String()
|
||||
}
|
||||
if msg := post(url.Values{"mode": {"auto"}, "account": {"L01-00000F00"}}); !strings.Contains(msg, "автоматически") {
|
||||
t.Fatalf("ответ: %q", msg)
|
||||
}
|
||||
s := rc.Snapshot().Quik
|
||||
if !s.WritesEnabled || !s.AutoOut || !s.AutoIn || s.Account != "L01-00000F00" || !s.PollTerminal || s.SecOut != "RUROUTM2M" || s.ClientCodeMap["БР-1"] != "BR1" {
|
||||
t.Fatalf("автоматически: %+v", s)
|
||||
}
|
||||
post(url.Values{"mode": {"check"}})
|
||||
if s := rc.Snapshot().Quik; s.WritesEnabled || s.AutoOut || s.AutoIn || s.Account != "L01-00000F00" {
|
||||
t.Fatalf("только сверка (счёт не стирается): %+v", s)
|
||||
}
|
||||
if !quikCertError(errors.New("TLS Handshake failed: tls: failed to verify certificate: x509: cannot validate certificate for 91.209.122.88 because it doesn't contain any IP SANs")) ||
|
||||
quikCertError(errors.New("mssql: login error: Login failed for user 'BROKER_88'")) {
|
||||
t.Fatal("ошибка сертификата распознаётся, ошибка логина — нет")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user