Files
bookhoard/internal/router/auth.go
T
John O'Keefe df556d8208
Release / build-and-push (push) Successful in 3m4s
feat(auth): data-driven password requirement checkers
GET /api/auth/password-rules (public, pre-auth) exposes the ACTIVE
complexity config from the settings registry; password_validation.ts
now fetches it and generates the checklist rows per active rule —
inactive requirements no longer linger as fake tasks, and the min
length mirrors the admin's setting instead of a hardcoded 8.

Surfaces: register, setup, admin create-user (Users page), profile
password change (self + admin variants, now gated on checklist pass;
misleading minlength=6 dropped — the server was always the enforcer).

Verified live: flip min_length=12 / number+special off via the
settings API → endpoint + register/profile/admin checklists re-render
row-for-row; enforcement follows (short rejected, rule-valid accepted
without digits/specials); restore defaults → checklists return.
2026-10-14 11:08:12 -04:00

50 lines
1.8 KiB
Go

package router
import (
"bookhoard/internal/handlers"
"github.com/labstack/echo/v5"
)
func registerAuthRoutes(cfg *Config, rateLimitMiddleware echo.MiddlewareFunc) {
e := cfg.Echo
// Auth routes (no auth required, but rate limited)
e.POST("/api/auth/register", rateLimitMiddleware(cfg.AuthHandler.Register))
e.POST("/api/auth/login", rateLimitMiddleware(cfg.AuthHandler.Login))
e.GET("/api/auth/password-rules", cfg.AuthHandler.GetPasswordRules)
// JWT middleware for protected routes
jwtMiddleware := createJWTMiddleware(cfg)
// Create protected route group
protected := e.Group("/api", jwtMiddleware)
// Protected auth routes
protected.GET("/auth/profile", cfg.AuthHandler.GetProfile)
// Refresh token endpoint (no authentication required - uses refresh token from body)
e.POST("/api/auth/refresh", cfg.AuthHandler.RefreshAccessToken)
// Logout endpoint (optional authentication - can revoke tokens if provided)
e.POST("/api/auth/logout", cfg.AuthHandler.Logout)
// Auth update routes
authGroup := e.Group("/api/auth", createJWTMiddleware(cfg))
authGroup.PUT("/password", cfg.AuthHandler.UpdatePassword)
authGroup.PUT("/theme", cfg.AuthHandler.UpdateTheme)
// Profile management (combined handlers - self-edit)
authGroup.PUT("/profile", cfg.AuthHandler.UpdateProfile)
authGroup.DELETE("/profile", cfg.AuthHandler.DeleteUser)
// Admin-only routes (same handlers with URL param)
admin := protected.Group("/auth", handlers.AdminMiddleware)
admin.GET("/users", cfg.AuthHandler.ListUsers)
admin.POST("/users", cfg.AuthHandler.AdminCreateUser)
admin.PUT("/users/:id/max-devices", cfg.AuthHandler.UpdateUserMaxDevices)
admin.PUT("/profile/:id", cfg.AuthHandler.UpdateProfile)
admin.PUT("/password/:id", cfg.AuthHandler.UpdatePassword)
admin.DELETE("/profile/:id", cfg.AuthHandler.DeleteUser)
}