Fix BASE_URL config loading, add tasks/projects; robust .env path resolution

- Config: try ENV_FILE, .env, ../.env for loading; trim trailing slash from BaseURL
- Log BASE_URL at server startup for verification
- .env.example: document BASE_URL
- Tasks, projects, tags, migrations and related API/handlers

Made-with: Cursor
This commit is contained in:
Michilis
2026-03-09 18:57:51 +00:00
parent 75105b8b46
commit bd24545b7b
61 changed files with 6595 additions and 90 deletions

View File

@@ -13,18 +13,24 @@ import (
)
type Handlers struct {
Auth *handlers.AuthHandler
User *handlers.UserHandler
Calendar *handlers.CalendarHandler
Sharing *handlers.SharingHandler
Event *handlers.EventHandler
Reminder *handlers.ReminderHandler
Attendee *handlers.AttendeeHandler
Contact *handlers.ContactHandler
Availability *handlers.AvailabilityHandler
Booking *handlers.BookingHandler
APIKey *handlers.APIKeyHandler
ICS *handlers.ICSHandler
Auth *handlers.AuthHandler
User *handlers.UserHandler
Calendar *handlers.CalendarHandler
Sharing *handlers.SharingHandler
Event *handlers.EventHandler
Reminder *handlers.ReminderHandler
Attendee *handlers.AttendeeHandler
Contact *handlers.ContactHandler
Availability *handlers.AvailabilityHandler
Booking *handlers.BookingHandler
APIKey *handlers.APIKeyHandler
ICS *handlers.ICSHandler
Task *handlers.TaskHandler
Project *handlers.ProjectHandler
Tag *handlers.TagHandler
TaskDependency *handlers.TaskDependencyHandler
TaskReminder *handlers.TaskReminderHandler
TaskWebhook *handlers.TaskWebhookHandler
}
func NewRouter(h Handlers, authMW *mw.AuthMiddleware, rateLimiter *mw.RateLimiter, cfg *config.Config) *chi.Mux {
@@ -152,6 +158,68 @@ func NewRouter(h Handlers, authMW *mw.AuthMiddleware, rateLimiter *mw.RateLimite
})
})
// Tasks
r.Route("/tasks", func(r chi.Router) {
r.With(mw.RequireScope("tasks", "read")).Get("/", h.Task.List)
r.With(mw.RequireScope("tasks", "write")).Post("/", h.Task.Create)
r.Route("/{id}", func(r chi.Router) {
r.With(mw.RequireScope("tasks", "read")).Get("/", h.Task.Get)
r.With(mw.RequireScope("tasks", "write")).Put("/", h.Task.Update)
r.With(mw.RequireScope("tasks", "write")).Delete("/", h.Task.Delete)
r.With(mw.RequireScope("tasks", "write")).Post("/complete", h.Task.MarkComplete)
r.With(mw.RequireScope("tasks", "write")).Post("/uncomplete", h.Task.MarkUncomplete)
r.With(mw.RequireScope("tasks", "read")).Get("/subtasks", h.Task.ListSubtasks)
r.Route("/dependencies", func(r chi.Router) {
r.With(mw.RequireScope("tasks", "read")).Get("/", h.TaskDependency.ListBlockers)
r.With(mw.RequireScope("tasks", "write")).Post("/", h.TaskDependency.Add)
r.With(mw.RequireScope("tasks", "write")).Delete("/{blocksTaskId}", h.TaskDependency.Remove)
})
r.Route("/reminders", func(r chi.Router) {
r.With(mw.RequireScope("tasks", "read")).Get("/", h.TaskReminder.List)
r.With(mw.RequireScope("tasks", "write")).Post("/", h.TaskReminder.Add)
r.With(mw.RequireScope("tasks", "write")).Delete("/{reminderId}", h.TaskReminder.Delete)
})
})
})
// Projects
r.Route("/projects", func(r chi.Router) {
r.With(mw.RequireScope("tasks", "read")).Get("/", h.Project.List)
r.With(mw.RequireScope("tasks", "write")).Post("/", h.Project.Create)
r.Route("/{id}", func(r chi.Router) {
r.With(mw.RequireScope("tasks", "read")).Get("/", h.Project.Get)
r.With(mw.RequireScope("tasks", "write")).Put("/", h.Project.Update)
r.With(mw.RequireScope("tasks", "write")).Delete("/", h.Project.Delete)
r.With(mw.RequireScope("tasks", "write")).Post("/share", h.Project.Share)
r.With(mw.RequireScope("tasks", "read")).Get("/members", h.Project.ListMembers)
})
})
// Tags
r.Route("/tags", func(r chi.Router) {
r.With(mw.RequireScope("tasks", "read")).Get("/", h.Tag.List)
r.With(mw.RequireScope("tasks", "write")).Post("/", h.Tag.Create)
r.Route("/{id}", func(r chi.Router) {
r.With(mw.RequireScope("tasks", "read")).Get("/", h.Tag.Get)
r.With(mw.RequireScope("tasks", "write")).Put("/", h.Tag.Update)
r.With(mw.RequireScope("tasks", "write")).Delete("/", h.Tag.Delete)
r.With(mw.RequireScope("tasks", "write")).Post("/attach/{taskId}", h.Tag.AttachToTask)
r.With(mw.RequireScope("tasks", "write")).Delete("/detach/{taskId}", h.Tag.DetachFromTask)
})
})
// Task Webhooks
r.Route("/webhooks", func(r chi.Router) {
r.With(mw.RequireScope("tasks", "read")).Get("/", h.TaskWebhook.List)
r.With(mw.RequireScope("tasks", "write")).Post("/", h.TaskWebhook.Create)
r.With(mw.RequireScope("tasks", "write")).Delete("/{id}", h.TaskWebhook.Delete)
})
// Availability
r.With(mw.RequireScope("availability", "read")).Get("/availability", h.Availability.Get)
})