add optional prefix to url

This commit is contained in:
nahakubuilde
2025-08-26 20:55:08 +01:00
parent 6fb6054803
commit e8658f5aab
25 changed files with 196 additions and 127 deletions

View File

@@ -20,6 +20,11 @@ const sessionCookieName = "gobsidian_session"
// LoginPage renders the login form
func (h *Handlers) LoginPage(c *gin.Context) {
// If already authenticated, redirect to home (respect URL prefix)
if isAuthenticated(c) {
c.Redirect(http.StatusFound, h.config.URLPrefix+"/")
return
}
token, _ := c.Get("csrf_token")
c.HTML(http.StatusOK, "login", gin.H{
"app_name": h.config.AppName,
@@ -128,7 +133,7 @@ func isAllDigits(s string) bool {
func (h *Handlers) MFALoginPage(c *gin.Context) {
session, _ := h.store.Get(c.Request, sessionCookieName)
if _, ok := session.Values["mfa_user_id"]; !ok {
c.Redirect(http.StatusFound, "/editor/login")
c.Redirect(http.StatusFound, h.config.URLPrefix+"/editor/login")
return
}
token, _ := c.Get("csrf_token")
@@ -161,7 +166,7 @@ func (h *Handlers) MFALoginVerify(c *gin.Context) {
session, _ := h.store.Get(c.Request, sessionCookieName)
uidAny, ok := session.Values["mfa_user_id"]
if !ok {
c.Redirect(http.StatusFound, "/editor/login")
c.Redirect(http.StatusFound, h.config.URLPrefix+"/editor/login")
return
}
uid, _ := uidAny.(int64)
@@ -188,14 +193,14 @@ func (h *Handlers) MFALoginVerify(c *gin.Context) {
delete(session.Values, "mfa_user_id")
session.Values["user_id"] = uid
_ = session.Save(c.Request, c.Writer)
c.Redirect(http.StatusFound, "/")
c.Redirect(http.StatusFound, h.config.URLPrefix+"/")
}
// ProfileMFASetupPage shows QR and input to verify during enrollment
func (h *Handlers) ProfileMFASetupPage(c *gin.Context) {
uidPtr := getUserIDPtr(c)
if uidPtr == nil {
c.Redirect(http.StatusFound, "/editor/login")
c.Redirect(http.StatusFound, h.config.URLPrefix+"/editor/login")
return
}
// ensure enrollment exists, otherwise create one
@@ -329,7 +334,7 @@ func (h *Handlers) LoginPost(c *gin.Context) {
session, _ := h.store.Get(c.Request, sessionCookieName)
session.Values["mfa_user_id"] = user.ID
_ = session.Save(c.Request, c.Writer)
c.Redirect(http.StatusFound, "/editor/mfa")
c.Redirect(http.StatusFound, h.config.URLPrefix+"/editor/mfa")
return
}
@@ -340,7 +345,7 @@ func (h *Handlers) LoginPost(c *gin.Context) {
session, _ := h.store.Get(c.Request, sessionCookieName)
session.Values["user_id"] = user.ID
_ = session.Save(c.Request, c.Writer)
c.Redirect(http.StatusFound, "/editor/profile/mfa/setup")
c.Redirect(http.StatusFound, h.config.URLPrefix+"/editor/profile/mfa/setup")
return
}
@@ -349,7 +354,7 @@ func (h *Handlers) LoginPost(c *gin.Context) {
session.Values["user_id"] = user.ID
_ = session.Save(c.Request, c.Writer)
c.Redirect(http.StatusFound, "/")
c.Redirect(http.StatusFound, h.config.URLPrefix+"/")
}
// LogoutPost clears the session
@@ -357,5 +362,5 @@ func (h *Handlers) LogoutPost(c *gin.Context) {
session, _ := h.store.Get(c.Request, sessionCookieName)
session.Options.MaxAge = -1
_ = session.Save(c.Request, c.Writer)
c.Redirect(http.StatusFound, "/editor/login")
c.Redirect(http.StatusFound, h.config.URLPrefix+"/editor/login")
}

View File

@@ -142,9 +142,9 @@ func (h *Handlers) CreateNoteHandler(c *gin.Context) {
}
// Redirect based on extension
redirect := "/note/" + notePath
redirect := h.config.URLPrefix + "/note/" + notePath
if strings.ToLower(ext) != "md" {
redirect = "/view_text/" + notePath
redirect = h.config.URLPrefix + "/view_text/" + notePath
}
c.JSON(http.StatusOK, gin.H{
@@ -297,7 +297,7 @@ func (h *Handlers) EditNoteHandler(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "Note saved successfully",
"redirect": "/note/" + notePath,
"redirect": h.config.URLPrefix + "/note/" + notePath,
})
}

View File

@@ -344,7 +344,7 @@ func (h *Handlers) ProfilePage(c *gin.Context) {
// Must be authenticated; middleware ensures user_id is set
uidPtr := getUserIDPtr(c)
if uidPtr == nil {
c.Redirect(http.StatusFound, "/editor/login")
c.Redirect(http.StatusFound, h.config.URLPrefix+"/editor/login")
return
}
@@ -477,7 +477,7 @@ func (h *Handlers) PostProfileEnableMFA(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"success": true, "setup": true, "redirect": "/editor/profile/mfa/setup"})
c.JSON(http.StatusOK, gin.H{"success": true, "setup": true, "redirect": h.config.URLPrefix+"/editor/profile/mfa/setup"})
}
// PostProfileDisableMFA clears the user's MFA secret
@@ -611,16 +611,18 @@ func (h *Handlers) AdminEnableUserMFA(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid user id"})
return
}
// Create or replace an enrollment so user is prompted on next login
// Admin enable: set a new secret directly so MFA is immediately enabled
secret, err := generateBase32Secret()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to generate secret"})
return
}
if _, err := h.authSvc.DB.Exec(`INSERT OR REPLACE INTO mfa_enrollments (user_id, secret) VALUES (?, ?)`, id, secret); err != nil {
if _, err := h.authSvc.DB.Exec(`UPDATE users SET mfa_secret = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?`, secret, id); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Remove any pending enrollment rows
_, _ = h.authSvc.DB.Exec(`DELETE FROM mfa_enrollments WHERE user_id = ?`, id)
c.JSON(http.StatusOK, gin.H{"success": true})
}
@@ -890,7 +892,7 @@ func (h *Handlers) PostEditTextHandler(c *gin.Context) {
return
}
c.JSON(http.StatusOK, gin.H{"success": true, "redirect": "/view_text/" + filePath})
c.JSON(http.StatusOK, gin.H{"success": true, "redirect": h.config.URLPrefix + "/view_text/" + filePath})
}
func New(cfg *config.Config, store *sessions.CookieStore, authSvc *auth.Service) *Handlers {

View File

@@ -30,10 +30,9 @@ func (h *Handlers) SettingsPageHandler(c *gin.Context) {
"notes_tree": notesTree,
"active_path": []string{},
"current_note": nil,
"breadcrumbs": []gin.H{
{"name": "/", "url": "/"},
{"name": "Settings", "url": ""},
},
"breadcrumbs": utils.GenerateBreadcrumbs(""),
"Authenticated": isAuthenticated(c),
"IsAdmin": isAdmin(c),
"ContentTemplate": "settings_content",
"ScriptsTemplate": "settings_scripts",
"Page": "settings",