Implement Issue #11: Initial admin account setup on first deploy
When the database has no users, the UI redirects to /setup and prompts for creation of the first admin account. The setup endpoints are self-disabling — once any user exists, POST /setup/admin returns 403 and the frontend redirects /setup back to /login. The backend uses an atomic transaction to prevent race conditions on concurrent requests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
"git.unsupervised.ca/walkies/internal/notification"
|
||||
"git.unsupervised.ca/walkies/internal/schedule"
|
||||
"git.unsupervised.ca/walkies/internal/server/middleware"
|
||||
"git.unsupervised.ca/walkies/internal/setup"
|
||||
"git.unsupervised.ca/walkies/internal/timeoff"
|
||||
"git.unsupervised.ca/walkies/internal/volunteer"
|
||||
)
|
||||
@@ -34,6 +35,9 @@ func New(db *sql.DB, jwtSecret string, staticDir string) http.Handler {
|
||||
checkinStore := checkin.NewStore(db)
|
||||
checkinHandler := checkin.NewHandler(checkinStore)
|
||||
|
||||
setupStore := setup.NewStore(db)
|
||||
setupHandler := setup.NewHandler(setupStore, authSvc)
|
||||
|
||||
r := chi.NewRouter()
|
||||
r.Use(chimiddleware.Logger)
|
||||
r.Use(chimiddleware.Recoverer)
|
||||
@@ -45,6 +49,10 @@ func New(db *sql.DB, jwtSecret string, staticDir string) http.Handler {
|
||||
r.Post("/auth/login", volunteerHandler.Login)
|
||||
r.Post("/auth/activate", volunteerHandler.Activate)
|
||||
|
||||
// Public setup endpoints (self-disabling once first user exists)
|
||||
r.Get("/setup/status", setupHandler.Status)
|
||||
r.Post("/setup/admin", setupHandler.CreateAdmin)
|
||||
|
||||
// Protected routes
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(middleware.Authenticate(authSvc))
|
||||
|
||||
Reference in New Issue
Block a user