diff options
| author | Leonardo Bishop <me@leonardobishop.com> | 2025-01-20 02:56:25 +0000 |
|---|---|---|
| committer | Leonardo Bishop <me@leonardobishop.com> | 2025-01-20 02:56:25 +0000 |
| commit | dc55f9c0097e1c36b85d7666071b840b902920e9 (patch) | |
| tree | c8c8ae10a9e134810b3361aabc8a9d426d813808 /api | |
| parent | 5e7ce6cbae81a1b6e46fe6738dc10039a06bec95 (diff) | |
Add calendar support
Diffstat (limited to 'api')
| -rw-r--r-- | api/dto/calendar.go | 15 | ||||
| -rw-r--r-- | api/handlers/calendar.go | 81 | ||||
| -rw-r--r-- | api/handlers/ical.go | 43 | ||||
| -rw-r--r-- | api/handlers/schedule.go | 2 | ||||
| -rw-r--r-- | api/router.go | 11 |
5 files changed, 150 insertions, 2 deletions
diff --git a/api/dto/calendar.go b/api/dto/calendar.go new file mode 100644 index 0000000..33da621 --- /dev/null +++ b/api/dto/calendar.go @@ -0,0 +1,15 @@ +package dto + +type GetCalendarResponse struct { + ID int32 `json:"id"` + Name string `json:"name"` + Key string `json:"key"` + URL string `json:"url"` +} + +type CreateCalendarResponse struct { + ID int32 `json:"id"` + Name string `json:"name"` + Key string `json:"key"` + URL string `json:"url"` +} diff --git a/api/handlers/calendar.go b/api/handlers/calendar.go new file mode 100644 index 0000000..85a9b00 --- /dev/null +++ b/api/handlers/calendar.go @@ -0,0 +1,81 @@ +package handlers + +import ( + "errors" + + "github.com/LMBishop/confplanner/api/dto" + "github.com/LMBishop/confplanner/pkg/calendar" + "github.com/gofiber/fiber/v2" +) + +func GetCalendar(calendarService calendar.Service, baseURL string) fiber.Handler { + // TODO create config service + return func(c *fiber.Ctx) error { + uid := c.Locals("uid").(int32) + + cal, err := calendarService.GetCalendarForUser(uid) + if err != nil { + if errors.Is(err, calendar.ErrCalendarNotFound) { + return &dto.ErrorResponse{ + Code: fiber.StatusNotFound, + Message: "Calendar not found", + } + } + + return err + } + + return &dto.OkResponse{ + Code: fiber.StatusOK, + Data: &dto.GetCalendarResponse{ + ID: cal.ID, + Name: cal.Name, + Key: cal.Key, + URL: baseURL + "/calendar/ical?name=" + cal.Name + "&key=" + cal.Key, + }, + } + } +} + +func CreateCalendar(calendarService calendar.Service, baseURL string) fiber.Handler { + return func(c *fiber.Ctx) error { + uid := c.Locals("uid").(int32) + + cal, err := calendarService.CreateCalendarForUser(uid) + if err != nil { + return err + } + + return &dto.OkResponse{ + Code: fiber.StatusCreated, + Data: &dto.CreateCalendarResponse{ + ID: cal.ID, + Name: cal.Name, + Key: cal.Key, + URL: baseURL + "/calendar/ical?name=" + cal.Name + "&key=" + cal.Key, + }, + } + } +} + +func DeleteCalendar(calendarService calendar.Service) fiber.Handler { + return func(c *fiber.Ctx) error { + uid := c.Locals("uid").(int32) + + err := calendarService.DeleteCalendarForUser(uid) + if err != nil { + if errors.Is(err, calendar.ErrCalendarNotFound) { + return &dto.ErrorResponse{ + Code: fiber.StatusNotFound, + Message: "Calendar not found", + } + } + + return err + } + + return &dto.OkResponse{ + Code: fiber.StatusOK, + } + } +} diff --git a/api/handlers/ical.go b/api/handlers/ical.go new file mode 100644 index 0000000..c4b3989 --- /dev/null +++ b/api/handlers/ical.go @@ -0,0 +1,43 @@ +package handlers + +import ( + "crypto/subtle" + + "github.com/LMBishop/confplanner/api/dto" + "github.com/LMBishop/confplanner/pkg/calendar" + "github.com/LMBishop/confplanner/pkg/ical" + "github.com/gofiber/fiber/v2" +) + +func GetIcal(icalService ical.Service, calendarService calendar.Service) fiber.Handler { + return func(c *fiber.Ctx) error { + name := c.Query("name") + key := c.Query("key") + + if name == "" || key == "" { + return &dto.ErrorResponse{ + Code: fiber.StatusBadRequest, + Message: "Both name and key must be specified", + } + } + + calendar, err := calendarService.GetCalendarByName(name) + if err != nil { + return err + } + + if subtle.ConstantTimeCompare([]byte(key), []byte(calendar.Key)) != 1 { + return &dto.ErrorResponse{ + Code: fiber.StatusUnauthorized, + Message: "Invalid key", + } + } + + ical, err := icalService.GenerateIcalForCalendar(*calendar) + if err != nil { + return err + } + + return c.SendString(ical) + } +} diff --git a/api/handlers/schedule.go b/api/handlers/schedule.go index fd3a183..46589ab 100644 --- a/api/handlers/schedule.go +++ b/api/handlers/schedule.go @@ -18,7 +18,7 @@ func GetSchedule(service schedule.Service) fiber.Handler { Code: fiber.StatusOK, Data: &dto.GetScheduleResponse{ Schedule: nilslice.Initialize(*schedule), - LastUpdated: *lastUpdated, + LastUpdated: lastUpdated, }, } } diff --git a/api/router.go b/api/router.go index 82a29b1..dc7e487 100644 --- a/api/router.go +++ b/api/router.go @@ -8,7 +8,9 @@ import ( "github.com/LMBishop/confplanner/api/dto" "github.com/LMBishop/confplanner/api/handlers" "github.com/LMBishop/confplanner/api/middleware" + "github.com/LMBishop/confplanner/pkg/calendar" "github.com/LMBishop/confplanner/pkg/favourites" + "github.com/LMBishop/confplanner/pkg/ical" "github.com/LMBishop/confplanner/pkg/schedule" "github.com/LMBishop/confplanner/pkg/user" "github.com/gofiber/fiber/v2" @@ -19,9 +21,11 @@ type ApiServices struct { UserService user.Service FavouritesService favourites.Service ScheduleService schedule.Service + CalendarService calendar.Service + IcalService ical.Service } -func NewServer(apiServices ApiServices) *fiber.App { +func NewServer(apiServices ApiServices, baseURL string) *fiber.App { sessionStore := session.New(session.Config{ Expiration: 24 * time.Hour, KeyLookup: "cookie:confplanner_session", @@ -63,5 +67,10 @@ func NewServer(apiServices ApiServices) *fiber.App { app.Get("/schedule", requireAuthenticated, handlers.GetSchedule(apiServices.ScheduleService)) + app.Get("/calendar", requireAuthenticated, handlers.GetCalendar(apiServices.CalendarService, baseURL)) + app.Post("/calendar", requireAuthenticated, handlers.CreateCalendar(apiServices.CalendarService, baseURL)) + app.Delete("/calendar", requireAuthenticated, handlers.DeleteCalendar(apiServices.CalendarService)) + app.Use("/calendar/ical", handlers.GetIcal(apiServices.IcalService, apiServices.CalendarService)) + return app } |
