diff --git a/internal/server/locale.go b/internal/server/locale.go index 1caa10a..9ba4227 100644 --- a/internal/server/locale.go +++ b/internal/server/locale.go @@ -116,6 +116,10 @@ var _translations = map[string]map[string]string{ "admin.runCleanup": "Запустить безопасную очистку", "admin.downloadDiagnostics": "Скачать диагностику", "admin.vaultPrivacy": "Содержимое файлов и операции не отображаются в диагностике.", + "admin.general": "Общие настройки", + "admin.serverName": "Название сервера", + "admin.allowRegistration": "Разрешить публичную регистрацию", + "admin.smtpConfigured": "SMTP настраивается отдельно и пароль никогда не возвращается в форму.", "user.account": "Моя учётная запись", "user.devices": "Подключённые устройства", "user.noDevices": "Устройств пока нет", @@ -355,6 +359,10 @@ var _translations = map[string]map[string]string{ "admin.runCleanup": "Run safe cleanup", "admin.downloadDiagnostics": "Download diagnostics", "admin.vaultPrivacy": "File contents and operations are not displayed in diagnostics.", + "admin.general": "General settings", + "admin.serverName": "Server name", + "admin.allowRegistration": "Allow public registration", + "admin.smtpConfigured": "SMTP is configured separately and its password is never returned to a form.", "user.account": "My account", "user.devices": "Connected devices", "user.noDevices": "No devices yet", diff --git a/internal/server/server.go b/internal/server/server.go index a25b99d..c6c15d0 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -39,6 +39,9 @@ func NewServer(dbPath, dataDir string, cfg *Config) (*Server, error) { if cfg == nil { cfg = DefaultConfig() } + if cfg.path == "" { + cfg.path = filepath.Join(dataDir, "config.yml") + } if err := cfg.normalize(); err != nil { return nil, fmt.Errorf("config: %w", err) } diff --git a/internal/server/web/templates/admin_settings.html b/internal/server/web/templates/admin_settings.html new file mode 100644 index 0000000..976317e --- /dev/null +++ b/internal/server/web/templates/admin_settings.html @@ -0,0 +1,2 @@ +{{define "admin_settings"}}{{template "layout" .}}{{end}} +{{define "content"}}

{{t .Locale "admin.settings"}}

{{t .Locale "admin.settings"}}

{{t .Locale "admin.general"}}

{{t .Locale "admin.smtpTitle"}}

{{t .Locale "admin.smtpConfigured"}}

{{t .Locale "common.back"}}
{{end}} diff --git a/internal/server/web_admin.go b/internal/server/web_admin.go index a4c1f7a..b39aaf6 100644 --- a/internal/server/web_admin.go +++ b/internal/server/web_admin.go @@ -141,6 +141,10 @@ func (s *Server) handleAdminWeb(w http.ResponseWriter, r *http.Request) { s.renderWebError(w, r, http.StatusInternalServerError, "error.internal", "/admin/dashboard") return } + if page == "settings" { + s.renderPage(w, r, "admin_settings", data) + return + } s.renderPage(w, r, "admin", data) } @@ -330,6 +334,27 @@ func (s *Server) handleAdminWebAction(w http.ResponseWriter, r *http.Request) { } action := r.FormValue("action") switch action { + case "web-settings": + if !s.adminReauth(r, session.SubjectID) { + s.renderWebError(w, r, http.StatusForbidden, "error.invalidCredentials", "/admin/settings") + return + } + locale := r.FormValue("default_locale") + if locale != "ru" && locale != "en" { + locale = "en" + } + s.cfg.mu.Lock() + s.cfg.Web.DefaultLocale = locale + s.cfg.Web.AllowRegistration = r.FormValue("allow_registration") == "on" + s.cfg.Web.ServerName = strings.TrimSpace(r.FormValue("server_name")) + err := s.cfg.saveLocked() + s.cfg.mu.Unlock() + if err != nil { + jsonInternalError(w, err) + return + } + s.auditLog("web_settings_updated", "", "", s.clientIP(r), "updated by administrator") + http.Redirect(w, r, "/admin/settings", http.StatusSeeOther) case "toggle-user": if !s.adminReauth(r, session.SubjectID) { s.renderWebError(w, r, http.StatusForbidden, "error.invalidCredentials", "/admin/users") diff --git a/internal/server/web_render.go b/internal/server/web_render.go index 924bf70..c7c4e99 100644 --- a/internal/server/web_render.go +++ b/internal/server/web_render.go @@ -20,6 +20,7 @@ type webRenderer struct { type webPage struct { Locale string LocalePreference string + DefaultLocale string Title string ServerName string CurrentPath string @@ -111,7 +112,7 @@ func newWebRenderer() (*webRenderer, error) { return nil, err } renderer := &webRenderer{templates: make(map[string]*template.Template)} - for _, page := range []string{"home", "login", "register", "forgot", "reset", "confirm", "message", "error", "admin_login", "dashboard", "admin", "admin_create_user", "vault_detail"} { + for _, page := range []string{"home", "login", "register", "forgot", "reset", "confirm", "message", "error", "admin_login", "dashboard", "admin", "admin_create_user", "vault_detail", "admin_settings"} { clone, err := layout.Clone() if err != nil { return nil, err @@ -139,6 +140,7 @@ func (s *Server) renderPageStatus(w http.ResponseWriter, r *http.Request, page s } data.Locale = s.webLocale(r) data.LocalePreference = s.webLocalePreference(r) + data.DefaultLocale = s.cfg.Web.DefaultLocale data.ServerName = s.cfg.Web.ServerName data.CurrentPath = r.URL.Path data.CurrentURL = r.URL.RequestURI()