Лента событий: убраны уведомления о сроках чужих сертификатов
После запуска (вместе с первой проверкой сроков) из ленты и главной уходят уведомления «Сертификат ключа организации…» по сертификатам не нашей организации и «Сертификат НРД/биржи в справочнике ИШ…» — на 9 их 22, все по чужим (Сбербанк и др.). Свои остаются. RuntimeConfig.RemoveNews. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
@@ -220,6 +220,37 @@ func certExpiryText(c NSDStoreCert, kind string, days int, until time.Time) (str
|
|||||||
who, until.Format("02.01.2006"))
|
who, until.Format("02.01.2006"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var certNewsSerialRe = regexp.MustCompile(`серийный номер ([0-9A-Fa-f]+)`)
|
||||||
|
|
||||||
|
// certNewsCleanup — убрать из ленты уведомления о сроках чужих сертификатов (до 22.10.2026 «своим» считался
|
||||||
|
// любой сертификат участника в справочнике ИШ) и сертификатов НРД/биржи: остаются только по своим.
|
||||||
|
func certNewsCleanup(rc *RuntimeConfig) {
|
||||||
|
s := rc.Snapshot()
|
||||||
|
if strings.TrimSpace(ourOrgINN(s)) == "" || len(s.NSDCerts.LastStore) == 0 {
|
||||||
|
return // не знаем, чьи сертификаты наши, — ничего не трогаем
|
||||||
|
}
|
||||||
|
own := map[string]bool{}
|
||||||
|
for _, c := range ownStoreCerts(s) {
|
||||||
|
own[normSerial(c.Serial)] = true
|
||||||
|
}
|
||||||
|
n := rc.RemoveNews(func(it NewsItem) bool {
|
||||||
|
if it.Kind != "system" || !strings.HasPrefix(it.Title, "Сертификат ") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if strings.Contains(it.Title, "в справочнике ИШ") {
|
||||||
|
return true // сертификаты НРД/биржи — больше не уведомляем
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(it.Title, "Сертификат ключа организации") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
m := certNewsSerialRe.FindStringSubmatch(it.Body)
|
||||||
|
return m != nil && !own[normSerial(m[1])]
|
||||||
|
})
|
||||||
|
if n > 0 {
|
||||||
|
log.Printf("cert-expiry: из ленты убрано %d уведомлений о сроках чужих сертификатов", n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// StartCertExpiryWatch — проверка сроков раз в 6 часов (первая — через 3 минуты после запуска).
|
// StartCertExpiryWatch — проверка сроков раз в 6 часов (первая — через 3 минуты после запуска).
|
||||||
func StartCertExpiryWatch(rc *RuntimeConfig) func() {
|
func StartCertExpiryWatch(rc *RuntimeConfig) func() {
|
||||||
stop := make(chan struct{})
|
stop := make(chan struct{})
|
||||||
@@ -231,6 +262,7 @@ func StartCertExpiryWatch(rc *RuntimeConfig) func() {
|
|||||||
case <-stop:
|
case <-stop:
|
||||||
return
|
return
|
||||||
case <-t.C:
|
case <-t.C:
|
||||||
|
certNewsCleanup(rc)
|
||||||
certExpiryTick(rc)
|
certExpiryTick(rc)
|
||||||
t.Reset(6 * time.Hour)
|
t.Reset(6 * time.Hour)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -837,3 +837,37 @@ func TestKeyInstallProblem(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Из ленты уходят уведомления о сроках чужих сертификатов и сертификатов НРД/биржи; свои остаются.
|
||||||
|
func TestCertNewsCleanup(t *testing.T) {
|
||||||
|
rc, err := NewRuntimeConfig(filepath.Join(t.TempDir(), "setup.json"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
nsd := rc.Snapshot().NSD
|
||||||
|
nsd.OrgINN = "7703807489"
|
||||||
|
_ = rc.UpdateNSD(nsd)
|
||||||
|
certs := rc.Snapshot().NSDCerts
|
||||||
|
certs.LastStore = []NSDStoreCert{
|
||||||
|
{Kind: "x509", Subject: "O=ООО ИК Фонтвьель,CN=Лапшина,INN=007703807489", SubjectCN: "Лапшина", Serial: "AA"},
|
||||||
|
{Kind: "x509", Subject: "O=ПАО Сбербанк,CN=Исакова,INN=007707083893", SubjectCN: "Исакова", Serial: "BB"},
|
||||||
|
}
|
||||||
|
_ = rc.UpdateNSDCerts(certs)
|
||||||
|
for i, it := range []NewsItem{
|
||||||
|
{Title: "Сертификат ключа организации истекает через 30 дн.", Body: "Сертификат «Лапшина» (издатель «УЦ», серийный номер AA) действует"},
|
||||||
|
{Title: "Сертификат ключа организации истекает сегодня", Body: "Сертификат «Исакова» (издатель «УЦ», серийный номер BB) действует"},
|
||||||
|
{Title: "Сертификат Московская Биржа в справочнике ИШ истекает через 3 дн.", Body: "…"},
|
||||||
|
{Title: "Служба «служба ключей Валидаты» не работает", Body: "…"},
|
||||||
|
} {
|
||||||
|
it.ID, it.Kind = fmt.Sprintf("n%d", i), "system"
|
||||||
|
_ = rc.AddNews(it)
|
||||||
|
}
|
||||||
|
certNewsCleanup(rc)
|
||||||
|
var titles []string
|
||||||
|
for _, it := range rc.Snapshot().News.Items {
|
||||||
|
titles = append(titles, it.Title)
|
||||||
|
}
|
||||||
|
if len(titles) != 2 || !strings.Contains(strings.Join(titles, "|"), "30 дн.") || !strings.Contains(strings.Join(titles, "|"), "Валидаты") {
|
||||||
|
t.Fatalf("осталось: %q", titles)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -664,6 +664,27 @@ func (r *RuntimeConfig) AddNews(item NewsItem) error {
|
|||||||
return r.save()
|
return r.save()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveNews удаляет из ленты события, для которых drop вернул true; сколько удалено.
|
||||||
|
func (r *RuntimeConfig) RemoveNews(drop func(NewsItem) bool) int {
|
||||||
|
r.mu.Lock()
|
||||||
|
kept := r.data.News.Items[:0:0]
|
||||||
|
for _, it := range r.data.News.Items {
|
||||||
|
if !drop(it) {
|
||||||
|
kept = append(kept, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n := len(r.data.News.Items) - len(kept)
|
||||||
|
if n > 0 {
|
||||||
|
r.data.News.Items = kept
|
||||||
|
r.data.UpdatedAt = time.Now()
|
||||||
|
}
|
||||||
|
r.mu.Unlock()
|
||||||
|
if n > 0 {
|
||||||
|
_ = r.save()
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
// DismissNews помечает новость скрытой по ID (не удаляет — для аудита).
|
// DismissNews помечает новость скрытой по ID (не удаляет — для аудита).
|
||||||
func (r *RuntimeConfig) DismissNews(id string) error {
|
func (r *RuntimeConfig) DismissNews(id string) error {
|
||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
|
|||||||
Reference in New Issue
Block a user