Анкета участника M2M: отправка через шлюз только в боевом контуре
Требование: в тест анкету не слать, подача только в бою. send_igw теперь пропускается лишь при боевом канале ИШ (Channel=PROD, профиль prod-*); в тестовом/гостевом контуре отправка через шлюз заблокирована (кнопка disabled + явный статус, серверная проверка isProdIGW как defense-in-depth). Скачивание XML и письмо на M2MOST@nsd.ru остаются доступны везде. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XG3zNMMf2LMoDpXo22mwMX
This commit is contained in:
@@ -31,6 +31,12 @@ const participantFormRecipient = "M2MOST@nsd.ru"
|
|||||||
var pfINNRe = regexp.MustCompile(`^\d{10}$`)
|
var pfINNRe = regexp.MustCompile(`^\d{10}$`)
|
||||||
var pfCodeRe = regexp.MustCompile(`^MC\d{10}$`)
|
var pfCodeRe = regexp.MustCompile(`^MC\d{10}$`)
|
||||||
|
|
||||||
|
// isProdIGW — текущий канал ИШ боевой. Анкету участника в НРД шлём ТОЛЬКО в бою:
|
||||||
|
// в тестовом/гостевом контуре отправка через шлюз заблокирована.
|
||||||
|
func isProdIGW(channel string) bool {
|
||||||
|
return strings.HasPrefix(strings.ToUpper(strings.TrimSpace(channel)), "PROD")
|
||||||
|
}
|
||||||
|
|
||||||
// participantFormData — поля анкеты (юридические реквизиты организации).
|
// participantFormData — поля анкеты (юридические реквизиты организации).
|
||||||
type participantFormData struct {
|
type participantFormData struct {
|
||||||
INN string
|
INN string
|
||||||
@@ -287,6 +293,8 @@ func registerParticipantForm(mux *http.ServeMux, rc *RuntimeConfig, igwClient *i
|
|||||||
flash, flashKind = "Анкета не прошла проверку — исправьте поля ниже.", "err"
|
flash, flashKind = "Анкета не прошла проверку — исправьте поля ниже.", "err"
|
||||||
case igwClient == nil || igwChannel == "":
|
case igwClient == nil || igwChannel == "":
|
||||||
flash, flashKind = "Боевой ИШ не настроен (раздел «НРД», профиль prod-*). Отправка через шлюз недоступна — переключитесь в боевой контур.", "err"
|
flash, flashKind = "Боевой ИШ не настроен (раздел «НРД», профиль prod-*). Отправка через шлюз недоступна — переключитесь в боевой контур.", "err"
|
||||||
|
case !isProdIGW(igwChannel):
|
||||||
|
flash, flashKind = "Сейчас выбран тестовый контур. Анкету участника шлём только в боевом контуре — переключитесь на профиль prod-* («НРД») и повторите.", "err"
|
||||||
default:
|
default:
|
||||||
body, encErr := participantFormBytes(d)
|
body, encErr := participantFormBytes(d)
|
||||||
if encErr != nil {
|
if encErr != nil {
|
||||||
@@ -311,11 +319,11 @@ func registerParticipantForm(mux *http.ServeMux, rc *RuntimeConfig, igwClient *i
|
|||||||
}
|
}
|
||||||
|
|
||||||
xmlPreview := participantFormXML(d)
|
xmlPreview := participantFormXML(d)
|
||||||
participantFormRender(w, d, errs, action, flash, flashKind, xmlPreview, igwClient != nil && igwChannel != "")
|
participantFormRender(w, d, errs, action, flash, flashKind, xmlPreview, igwClient != nil && igwChannel != "", isProdIGW(igwChannel))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func participantFormRender(w http.ResponseWriter, d participantFormData, errs []string, action, flash, flashKind, xmlPreview string, igwReady bool) {
|
func participantFormRender(w http.ResponseWriter, d participantFormData, errs []string, action, flash, flashKind, xmlPreview string, igwConfigured, igwProd bool) {
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
inp := func(name, label, val, ph string) string {
|
inp := func(name, label, val, ph string) string {
|
||||||
return `<label>` + label + `<input name="` + name + `" value="` + html.EscapeString(val) + `" placeholder="` + ph + `"></label>`
|
return `<label>` + label + `<input name="` + name + `" value="` + html.EscapeString(val) + `" placeholder="` + ph + `"></label>`
|
||||||
@@ -335,9 +343,14 @@ func participantFormRender(w http.ResponseWriter, d participantFormData, errs []
|
|||||||
flashHTML = `<div class="` + cls + `">` + html.EscapeString(flash) + `</div>`
|
flashHTML = `<div class="` + cls + `">` + html.EscapeString(flash) + `</div>`
|
||||||
}
|
}
|
||||||
igwBtn := `<button type="submit" name="action" value="send_igw" class="primary">Отправить через шлюз (боевой ИШ)</button>`
|
igwBtn := `<button type="submit" name="action" value="send_igw" class="primary">Отправить через шлюз (боевой ИШ)</button>`
|
||||||
igwStatus := `<p class="note">Боевой ИШ: <b style="color:#2a7a2a">настроен</b> — анкету можно отправить через шлюз (#M2MPF).</p>`
|
igwStatus := `<p class="note">Боевой контур: <b style="color:#2a7a2a">да</b> — анкету можно отправить через шлюз (#M2MPF).</p>`
|
||||||
if !igwReady {
|
if !igwProd {
|
||||||
igwStatus = `<p class="note">Боевой ИШ: <b style="color:#b00">не настроен</b> (раздел «НРД», профиль <code>prod-*</code>). Пока доступны «Скачать» и «Отправить письмом».</p>`
|
igwBtn = `<button type="button" class="primary" disabled title="Доступно только в боевом контуре">Отправить через шлюз (только в бою)</button>`
|
||||||
|
if igwConfigured {
|
||||||
|
igwStatus = `<p class="note">Контур <b>тестовый</b> — анкету участника в НРД шлём <b>только в боевом</b> контуре. Переключитесь на профиль <code>prod-*</code> («НРД»). Пока доступны «Скачать» и «Отправить письмом».</p>`
|
||||||
|
} else {
|
||||||
|
igwStatus = `<p class="note">Боевой ИШ: <b style="color:#b00">не настроен</b> (раздел «НРД», профиль <code>prod-*</code>). Пока доступны «Скачать» и «Отправить письмом».</p>`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
page := `<!doctype html><html lang="ru"><head><meta charset="utf-8"><title>Регистрация участника M2M</title>
|
page := `<!doctype html><html lang="ru"><head><meta charset="utf-8"><title>Регистрация участника M2M</title>
|
||||||
<style>body{font:14px/1.5 system-ui,Arial;margin:24px;max-width:900px;color:#111}
|
<style>body{font:14px/1.5 system-ui,Arial;margin:24px;max-width:900px;color:#111}
|
||||||
|
|||||||
Reference in New Issue
Block a user