feat: replace mock mode with real backend dev mode

Add --dev flag to `opal server start` that disables auth (injects
userID=1 for all requests) and exposes a /auth/dev-session endpoint,
so the frontend can develop against a real backend without OAuth
config. Remove VITE_MOCK_MODE and all mock data/branches from the
frontend stores. Add scripts/dev.sh to start both services locally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-17 17:07:34 +01:00
parent 80ea17227d
commit d51c6da18d
8 changed files with 111 additions and 468 deletions
+10
View File
@@ -73,6 +73,16 @@ func GetUserID(r *http.Request) int {
return userID
}
// DevAuthMiddleware always injects userID=1 into context — for local dev only
func DevAuthMiddleware() func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), userIDKey, 1)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
}
// CORSMiddleware adds CORS headers for future web frontend
func CORSMiddleware() func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
+35 -12
View File
@@ -11,15 +11,17 @@ import (
// Server represents the API server
type Server struct {
router chi.Router
addr string
router chi.Router
addr string
devMode bool
}
// NewServer creates a new API server
func NewServer(addr string) *Server {
func NewServer(addr string, devMode bool) *Server {
s := &Server{
router: chi.NewRouter(),
addr: addr,
router: chi.NewRouter(),
addr: addr,
devMode: devMode,
}
s.setupRoutes()
return s
@@ -39,16 +41,37 @@ func (s *Server) setupRoutes() {
JSON(w, http.StatusOK, map[string]string{"status": "ok"})
})
// OAuth endpoints (no auth required)
r.Get("/auth/login", handlers.GetLoginURL)
r.Get("/auth/callback", handlers.OAuthCallback)
r.Post("/auth/callback", handlers.OAuthCallback)
r.Post("/auth/refresh", handlers.RefreshToken)
r.Post("/auth/logout", handlers.Logout)
if s.devMode {
// Dev mode: fake session endpoint so the frontend can "log in"
r.Get("/auth/dev-session", func(w http.ResponseWriter, r *http.Request) {
JSON(w, http.StatusOK, map[string]interface{}{
"access_token": "dev-token",
"refresh_token": "",
"expires_at": 9999999999,
"token_type": "bearer",
"user": map[string]interface{}{
"id": 1,
"username": "dev",
"email": "dev@localhost",
},
})
})
} else {
// OAuth endpoints (no auth required)
r.Get("/auth/login", handlers.GetLoginURL)
r.Get("/auth/callback", handlers.OAuthCallback)
r.Post("/auth/callback", handlers.OAuthCallback)
r.Post("/auth/refresh", handlers.RefreshToken)
r.Post("/auth/logout", handlers.Logout)
}
// Protected routes
r.Group(func(r chi.Router) {
r.Use(AuthMiddleware())
if s.devMode {
r.Use(DevAuthMiddleware())
} else {
r.Use(AuthMiddleware())
}
// Tasks
r.Route("/tasks", func(r chi.Router) {