fix(web): restore administration notification sections
CI / validate (pull_request) Successful in 25m57s

This commit is contained in:
2026-08-14 14:22:00 +02:00
parent 483d93e6de
commit 83b9545c35
6 changed files with 49 additions and 11 deletions
+5 -5
View File
@@ -193,7 +193,7 @@ func (s *server) notificationForm(w http.ResponseWriter, r *http.Request) {
return
}
s.recordAudit(r, actor, "notification.channel.update", "allowed", map[string]string{"target_id": value.ID, "channel_type": value.Type})
http.Redirect(w, r, "/settings#notifications", http.StatusSeeOther)
http.Redirect(w, r, "/administration#notifications", http.StatusSeeOther)
}
func (s *server) notificationLanguageForm(w http.ResponseWriter, r *http.Request) {
actor, ok := s.requireRecentAdmin(w, r, false)
@@ -217,7 +217,7 @@ func (s *server) notificationTestForm(w http.ResponseWriter, r *http.Request) {
return
}
s.recordAudit(r, actor, "notification.channel.test", "allowed", map[string]string{"target_id": r.PathValue("id"), "event_type": "notification.test"})
http.Redirect(w, r, "/settings#notifications", http.StatusSeeOther)
http.Redirect(w, r, "/administration#notifications", http.StatusSeeOther)
}
func (s *server) notificationDeleteForm(w http.ResponseWriter, r *http.Request) {
actor, ok := s.requireRecentAdmin(w, r, false)
@@ -229,7 +229,7 @@ func (s *server) notificationDeleteForm(w http.ResponseWriter, r *http.Request)
return
}
s.recordAudit(r, actor, "notification.channel.delete", "allowed", map[string]string{"target_id": r.PathValue("id")})
http.Redirect(w, r, "/settings#notifications", http.StatusSeeOther)
http.Redirect(w, r, "/administration#notifications", http.StatusSeeOther)
}
func (s *server) auditPolicyForm(w http.ResponseWriter, r *http.Request) {
actor, ok := s.requireRecentAdmin(w, r, false)
@@ -243,7 +243,7 @@ func (s *server) auditPolicyForm(w http.ResponseWriter, r *http.Request) {
return
}
s.recordAudit(r, actor, "audit.policy.update", "allowed", nil)
http.Redirect(w, r, "/settings#audit", http.StatusSeeOther)
http.Redirect(w, r, "/administration#audit", http.StatusSeeOther)
}
func (s *server) auditPurgeForm(w http.ResponseWriter, r *http.Request) {
actor, ok := s.requireRecentAdmin(w, r, false)
@@ -265,5 +265,5 @@ func (s *server) auditPurgeForm(w http.ResponseWriter, r *http.Request) {
return
}
s.recordAudit(r, actor, "audit.purge", "allowed", map[string]string{"deleted_count": strconv.FormatInt(n, 10)})
http.Redirect(w, r, "/settings#audit", http.StatusSeeOther)
http.Redirect(w, r, "/administration#audit", http.StatusSeeOther)
}
+8
View File
@@ -48,6 +48,14 @@ func init() {
messages[language][key] = value
}
}
for language, values := range map[string]map[string]string{
"en": {"settings.notification_general": "General", "settings.notification_language_help": "Choose the language used in delivered notifications.", "settings.notification_email": "Email / SMTP", "settings.notification_discord": "Discord", "settings.notification_gotify": "Gotify", "settings.sender_name": "Sender name", "settings.sender_email": "Sender email", "settings.smtp_server": "SMTP server", "settings.port": "Port", "settings.username": "Username", "settings.password": "Password", "settings.password_retain": "leave empty to retain on edit", "settings.tls_mode": "TLS mode", "settings.test_recipient": "Test recipient (optional)", "settings.save_smtp": "Save SMTP", "settings.webhook_url": "Webhook URL", "settings.save_discord": "Save Discord", "settings.gotify_help": "Create an application in Gotify, then enter its server URL and application token here.", "settings.server_url": "Server URL", "settings.application_token": "Application token", "settings.save_gotify": "Save Gotify", "settings.configured": "configured", "settings.not_configured": "not configured"},
"fr": {"settings.notification_general": "Général", "settings.notification_language_help": "Choisissez la langue utilisée pour les notifications envoyées.", "settings.notification_email": "E-mail / SMTP", "settings.notification_discord": "Discord", "settings.notification_gotify": "Gotify", "settings.sender_name": "Nom de l'expéditeur", "settings.sender_email": "E-mail de l'expéditeur", "settings.smtp_server": "Serveur SMTP", "settings.port": "Port", "settings.username": "Nom d'utilisateur", "settings.password": "Mot de passe", "settings.password_retain": "laissez vide pour le conserver lors d'une modification", "settings.tls_mode": "Mode TLS", "settings.test_recipient": "Destinataire de test (facultatif)", "settings.save_smtp": "Enregistrer SMTP", "settings.webhook_url": "URL du webhook", "settings.save_discord": "Enregistrer Discord", "settings.gotify_help": "Créez une application dans Gotify, puis saisissez ici l'URL du serveur et le jeton de l'application.", "settings.server_url": "URL du serveur", "settings.application_token": "Jeton d'application", "settings.save_gotify": "Enregistrer Gotify", "settings.configured": "configuré", "settings.not_configured": "non configuré"},
} {
for key, value := range values {
messages[language][key] = value
}
}
}
type languageOption struct {
+2 -2
View File
@@ -624,7 +624,7 @@ func (s *server) globalLabelsForm(w http.ResponseWriter, r *http.Request) {
}
}
}
http.Redirect(w, r, "/settings#containers", http.StatusSeeOther)
http.Redirect(w, r, "/administration#containers", http.StatusSeeOther)
}
func mustLifecycleInstances(ctx context.Context, repository repository) []instance.StoredInstance {
@@ -2054,7 +2054,7 @@ func (s *server) adminPageData(w http.ResponseWriter, r *http.Request, title, ac
s.problem(w, http.StatusForbidden, message("error.csrf"))
return pageData{}, false
}
return pageData{Title: localized(s.language(r, user.Language), strings.ToLower(active)+".title"), Language: s.language(r, user.Language), User: user, CSRFToken: csrf.Value, IsAdmin: true, ActivePage: active}, true
return pageData{Title: localized(s.language(r, user.Language), strings.ToLower(active)+".title"), Language: s.language(r, user.Language), Languages: supportedLanguageOptions(), User: user, CSRFToken: csrf.Value, IsAdmin: true, ActivePage: active}, true
}
func statusClass(state string) string {
+13 -2
View File
@@ -351,8 +351,19 @@ func TestNotificationAndAuditAdministration(t *testing.T) {
}
settings := request(t, handler, http.MethodGet, "/administration", []*http.Cookie{cookie, &http.Cookie{Name: csrfCookie, Value: session.CSRFToken}})
assertStatus(t, settings, http.StatusOK)
if !strings.Contains(settings.Body.String(), "Notification channels") || !strings.Contains(settings.Body.String(), "Web access") {
t.Fatal("settings UI sections missing")
settingsBody := settings.Body.String()
for _, expected := range []string{
"Notification channels", "Web access", "href=\"#audit\"", "href=\"/audit\"",
"id=\"notifications\"", "id=\"notification-general\"", "id=\"email\"", "id=\"discord\"", "id=\"gotify\"",
} {
if !strings.Contains(settingsBody, expected) {
t.Fatalf("settings UI section %q missing", expected)
}
}
notificationLanguage := formRequest(t, handler, "/admin/notification-language", url.Values{"csrf_token": {session.CSRFToken}, "language": {"fr"}}, cookie, &http.Cookie{Name: csrfCookie, Value: session.CSRFToken})
assertStatus(t, notificationLanguage, http.StatusSeeOther)
if got := notificationLanguage.Result().Header.Get("Location"); got != "/administration#notifications" {
t.Fatalf("notification language redirect = %q", got)
}
usersPage := request(t, handler, http.MethodGet, "/administration/users", []*http.Cookie{cookie, &http.Cookie{Name: csrfCookie, Value: session.CSRFToken}})
assertStatus(t, usersPage, http.StatusOK)
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -30,5 +30,5 @@ func (s *server) webAccessForm(w http.ResponseWriter, r *http.Request) {
s.problem(w, http.StatusInternalServerError, localized(s.language(r, user.Language), "error.internal"))
return
}
http.Redirect(w, r, "/settings#web-access", http.StatusSeeOther)
http.Redirect(w, r, "/administration#web-access", http.StatusSeeOther)
}