feat(admin): implement full admin dashboard structure
This commit is contained in:
102
lib/server/admin.go
Normal file
102
lib/server/admin.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"warpbox/lib/config"
|
||||
)
|
||||
|
||||
const adminSessionCookie = "warpbox_admin_session"
|
||||
const adminSessionMarker = "1"
|
||||
|
||||
func (app *App) adminLoginEnabled() bool {
|
||||
return app.config.AdminLoginEnabled(app.config.AdminPassword != "")
|
||||
}
|
||||
|
||||
func (app *App) adminAuthMiddleware(ctx *gin.Context) {
|
||||
if !app.adminLoginEnabled() {
|
||||
ctx.Redirect(http.StatusSeeOther, "/")
|
||||
ctx.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
token, err := ctx.Cookie(adminSessionCookie)
|
||||
if err != nil || token != app.adminSessionToken() {
|
||||
ctx.Redirect(http.StatusSeeOther, "/admin/login")
|
||||
ctx.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Next()
|
||||
}
|
||||
|
||||
func (app *App) adminSessionToken() string {
|
||||
// A simple deterministic token derived from the admin credentials.
|
||||
// This will improve when proper user/session storage is added.
|
||||
return app.config.AdminUsername + ":" + app.config.AdminPassword
|
||||
}
|
||||
|
||||
func (app *App) handleAdminLogin(ctx *gin.Context) {
|
||||
if !app.adminLoginEnabled() {
|
||||
ctx.Redirect(http.StatusSeeOther, "/")
|
||||
return
|
||||
}
|
||||
|
||||
// Already logged in.
|
||||
if token, err := ctx.Cookie(adminSessionCookie); err == nil && token == app.adminSessionToken() {
|
||||
ctx.Redirect(http.StatusSeeOther, "/admin/dashboard")
|
||||
return
|
||||
}
|
||||
|
||||
ctx.HTML(http.StatusOK, "admin/login.html", gin.H{})
|
||||
}
|
||||
|
||||
func (app *App) handleAdminLoginPost(ctx *gin.Context) {
|
||||
if !app.adminLoginEnabled() {
|
||||
ctx.Redirect(http.StatusSeeOther, "/")
|
||||
return
|
||||
}
|
||||
|
||||
username := strings.TrimSpace(ctx.PostForm("username"))
|
||||
password := ctx.PostForm("password")
|
||||
|
||||
if username != app.config.AdminUsername || password != app.config.AdminPassword {
|
||||
ctx.HTML(http.StatusUnauthorized, "admin/login.html", gin.H{
|
||||
"ErrorMessage": "Invalid username or password.",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
secure := app.config.AdminCookieSecure
|
||||
maxAge := int(app.config.SessionTTLSeconds)
|
||||
|
||||
ctx.SetCookie(adminSessionCookie, app.adminSessionToken(), maxAge, "/admin", "", secure, true)
|
||||
ctx.Redirect(http.StatusSeeOther, "/admin/dashboard")
|
||||
}
|
||||
|
||||
func (app *App) handleAdminLogout(ctx *gin.Context) {
|
||||
secure := app.config.AdminCookieSecure
|
||||
ctx.SetCookie(adminSessionCookie, "", -1, "/admin", "", secure, true)
|
||||
ctx.Redirect(http.StatusSeeOther, "/admin/login")
|
||||
}
|
||||
|
||||
func (app *App) handleAdminDashboard(ctx *gin.Context) {
|
||||
if !app.adminLoginEnabled() {
|
||||
ctx.Redirect(http.StatusSeeOther, "/")
|
||||
return
|
||||
}
|
||||
|
||||
dashboardEnabled := config.AdminEnabledTrue
|
||||
if cfgVal := app.config.AdminEnabled; cfgVal == config.AdminEnabledAuto || cfgVal == config.AdminEnabledTrue {
|
||||
dashboardEnabled = cfgVal
|
||||
}
|
||||
|
||||
ctx.HTML(http.StatusOK, "admin/dashboard.html", gin.H{
|
||||
"AdminUsername": app.config.AdminUsername,
|
||||
"AdminEmail": app.config.AdminEmail,
|
||||
"DashboardEnabled": string(dashboardEnabled),
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user