ba0cfc08e3
- Added database schema for users, api_keys, sync_state, change_log, and sync_config - Implemented API key generation and validation with bcrypt hashing - Created Chi-based REST API server with endpoints for: - Task CRUD operations (create, read, update, delete) - Task actions (complete, start, stop) - Tag management (list, add, remove) - Projects listing - Health check endpoint - Added middleware for authentication and CORS - Implemented change log tracking with triggers (key:value format) - Added configurable change log retention (default 30 days) - Created server CLI commands (opal server start, opal server keygen) - Dependencies added: golang.org/x/crypto/bcrypt, github.com/go-chi/chi/v5
82 lines
1.9 KiB
Go
82 lines
1.9 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"})
|
|
})
|
|
|
|
// 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)
|
|
}
|