4eb18388db
- Add OAuth2 client for Authentik integration - Implement JWT token generation and validation - Add refresh token support with database storage - Update database schema with oauth_subject, oauth_provider, and refresh_tokens table - Create auth package with config, jwt, oauth, and token management - Add OAuth endpoints: /auth/login, /auth/callback, /auth/refresh, /auth/logout - Update AuthMiddleware to support both JWT and API key authentication - Add user helper functions for OAuth user creation and retrieval - Add .env.example with OAuth configuration template API keys still work for CLI compatibility while JWT tokens support web/mobile clients.
88 lines
2.1 KiB
Go
88 lines
2.1 KiB
Go
package api
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"git.jnss.me/joakim/opal/internal/api/handlers"
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/go-chi/chi/v5/middleware"
|
|
)
|
|
|
|
// Server represents the API server
|
|
type Server struct {
|
|
router chi.Router
|
|
addr string
|
|
}
|
|
|
|
// NewServer creates a new API server
|
|
func NewServer(addr string) *Server {
|
|
s := &Server{
|
|
router: chi.NewRouter(),
|
|
addr: addr,
|
|
}
|
|
s.setupRoutes()
|
|
return s
|
|
}
|
|
|
|
// setupRoutes configures all API routes
|
|
func (s *Server) setupRoutes() {
|
|
r := s.router
|
|
|
|
// Global middleware
|
|
r.Use(middleware.Logger)
|
|
r.Use(middleware.Recoverer)
|
|
r.Use(CORSMiddleware())
|
|
|
|
// Health check (no auth required)
|
|
r.Get("/health", func(w http.ResponseWriter, r *http.Request) {
|
|
JSON(w, http.StatusOK, map[string]string{"status": "ok"})
|
|
})
|
|
|
|
// OAuth endpoints (no auth required)
|
|
r.Get("/auth/login", handlers.GetLoginURL)
|
|
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())
|
|
|
|
// Tasks
|
|
r.Route("/tasks", func(r chi.Router) {
|
|
r.Get("/", handlers.ListTasks)
|
|
r.Post("/", handlers.CreateTask)
|
|
r.Get("/{uuid}", handlers.GetTask)
|
|
r.Put("/{uuid}", handlers.UpdateTask)
|
|
r.Delete("/{uuid}", handlers.DeleteTask)
|
|
r.Post("/{uuid}/complete", handlers.CompleteTask)
|
|
r.Post("/{uuid}/start", handlers.StartTask)
|
|
r.Post("/{uuid}/stop", handlers.StopTask)
|
|
|
|
// Tags
|
|
r.Get("/{uuid}/tags", handlers.GetTaskTags)
|
|
r.Post("/{uuid}/tags", handlers.AddTaskTag)
|
|
r.Delete("/{uuid}/tags/{tag}", handlers.RemoveTaskTag)
|
|
})
|
|
|
|
// Metadata
|
|
r.Get("/tags", handlers.ListAllTags)
|
|
r.Get("/projects", handlers.ListProjects)
|
|
|
|
// Sync endpoints
|
|
r.Post("/sync/changes", handlers.GetChanges)
|
|
r.Post("/sync/push", handlers.PushChanges)
|
|
|
|
// Key management
|
|
r.Get("/auth/keys", handlers.ListAPIKeys)
|
|
r.Delete("/auth/keys/{id}", handlers.RevokeAPIKey)
|
|
})
|
|
}
|
|
|
|
// Start starts the HTTP server
|
|
func (s *Server) Start() error {
|
|
fmt.Printf("Starting opal API server on %s\n", s.addr)
|
|
return http.ListenAndServe(s.addr, s.router)
|
|
}
|