diff --git a/README.md b/README.md index f1ec8ad..f60ca97 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ PATH = data/gobsidian.db REQUIRE_ADMIN_ACTIVATION = true REQUIRE_EMAIL_CONFIRMATION = false MFA_ENABLED_BY_DEFAULT = false +LOGIN_AND_EDITS = true [SECURITY] PWD_FAILURES_THRESHOLD = 5 diff --git a/internal/config/config.go b/internal/config/config.go index 294eaed..441b4ab 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -45,6 +45,7 @@ type Config struct { RequireAdminActivation bool RequireEmailConfirmation bool MFAEnabledByDefault bool + LoginAndEdits bool // Security settings (failed-login thresholds and auto-ban config) PwdFailuresThreshold int @@ -92,6 +93,7 @@ var defaultConfig = map[string]map[string]string{ "REQUIRE_ADMIN_ACTIVATION": "true", "REQUIRE_EMAIL_CONFIRMATION": "false", "MFA_ENABLED_BY_DEFAULT": "false", + "LOGIN_AND_EDITS": "true", }, "SECURITY": { "PWD_FAILURES_THRESHOLD": "5", @@ -219,6 +221,7 @@ func Load() (*Config, error) { config.RequireAdminActivation, _ = authSection.Key("REQUIRE_ADMIN_ACTIVATION").Bool() config.RequireEmailConfirmation, _ = authSection.Key("REQUIRE_EMAIL_CONFIRMATION").Bool() config.MFAEnabledByDefault, _ = authSection.Key("MFA_ENABLED_BY_DEFAULT").Bool() + config.LoginAndEdits, _ = authSection.Key("LOGIN_AND_EDITS").Bool() // Load SECURITY section secSection := cfg.Section("SECURITY") @@ -395,6 +398,8 @@ func (c *Config) SaveSetting(section, key, value string) error { c.RequireEmailConfirmation = value == "true" case "MFA_ENABLED_BY_DEFAULT": c.MFAEnabledByDefault = value == "true" + case "LOGIN_AND_EDITS": + c.LoginAndEdits = value == "true" } case "SECURITY": switch key { diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index 19259c1..7ee7ff2 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -972,6 +972,7 @@ func (h *Handlers) IndexHandler(c *gin.Context) { "breadcrumbs": utils.GenerateBreadcrumbs(""), "allowed_image_extensions": h.config.AllowedImageExtensions, "allowed_file_extensions": h.config.AllowedFileExtensions, + "LoginAndEdits": h.config.LoginAndEdits, "Authenticated": isAuthenticated(c), "IsAdmin": isAdmin(c), "ContentTemplate": "folder_content", diff --git a/internal/server/middleware.go b/internal/server/middleware.go index 5b7bd28..96cedbb 100644 --- a/internal/server/middleware.go +++ b/internal/server/middleware.go @@ -13,6 +13,18 @@ import ( const csrfSessionKey = "csrf_token" +// RequireLoginAndEdits blocks access if LoginAndEdits setting is false. +func (s *Server) RequireLoginAndEdits() gin.HandlerFunc { + return func(c *gin.Context) { + if !s.config.LoginAndEdits { + c.Redirect(http.StatusFound, s.config.URLPrefix+"/?error=not_found") + c.Abort() + return + } + c.Next() + } +} + func (s *Server) randomToken(n int) (string, error) { b := make([]byte, n) if _, err := rand.Read(b); err != nil { diff --git a/internal/server/server.go b/internal/server/server.go index 8c9e30b..8cacf70 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -105,15 +105,15 @@ func (s *Server) setupRoutes() { r.GET("/view_text/*path", h.ViewTextHandler) // Auth routes - r.GET("/editor/login", h.LoginPage) - r.POST("/editor/login", s.CSRFRequire(), h.LoginPost) + r.GET("/editor/login", s.RequireLoginAndEdits(), h.LoginPage) + r.POST("/editor/login", s.RequireLoginAndEdits(), s.CSRFRequire(), h.LoginPost) r.POST("/editor/logout", s.RequireAuth(), s.CSRFRequire(), h.LogoutPost) // MFA challenge routes (no auth yet, but CSRF) - r.GET("/editor/mfa", s.CSRFRequire(), h.MFALoginPage) - r.POST("/editor/mfa", s.CSRFRequire(), h.MFALoginVerify) + r.GET("/editor/mfa", s.RequireLoginAndEdits(), s.CSRFRequire(), h.MFALoginPage) + r.POST("/editor/mfa", s.RequireLoginAndEdits(), s.CSRFRequire(), h.MFALoginVerify) - // New /editor group protected by auth + CSRF - editor := r.Group("/editor", s.RequireAuth(), s.CSRFRequire()) + // New /editor group protected by auth + CSRF + LoginAndEdits + editor := r.Group("/editor", s.RequireLoginAndEdits(), s.RequireAuth(), s.CSRFRequire()) { editor.GET("/create", h.CreateNotePageHandler) editor.POST("/create", h.CreateNoteHandler) diff --git a/web/templates/base.html b/web/templates/base.html index 20e4130..e74c330 100644 --- a/web/templates/base.html +++ b/web/templates/base.html @@ -308,9 +308,11 @@ {{else}} + {{if .LoginAndEdits}} + {{end}} {{end}}