aboutsummaryrefslogtreecommitdiffstats
path: root/api/handlers
diff options
context:
space:
mode:
authorLeonardo Bishop <me@leonardobishop.com>2025-08-14 18:07:12 +0100
committerLeonardo Bishop <me@leonardobishop.com>2025-08-14 18:07:12 +0100
commit4697556cac819c47d068819b9fc9c3b4ea84e279 (patch)
treeb832d8fc6b643a8b9d0eeca35c1268e1649da731 /api/handlers
parentdd49c9205bb04844b686b9c3396c40eb49d25826 (diff)
Merge confplanner-web and replace fiber with native net/http
Diffstat (limited to 'api/handlers')
-rw-r--r--api/handlers/calendar.go43
-rw-r--r--api/handlers/favourites.go54
-rw-r--r--api/handlers/ical.go34
-rw-r--r--api/handlers/schedule.go11
-rw-r--r--api/handlers/users.go66
-rw-r--r--api/handlers/util.go28
6 files changed, 101 insertions, 135 deletions
diff --git a/api/handlers/calendar.go b/api/handlers/calendar.go
index 85a9b00..5b14972 100644
--- a/api/handlers/calendar.go
+++ b/api/handlers/calendar.go
@@ -2,22 +2,23 @@ package handlers
import (
"errors"
+ "net/http"
"github.com/LMBishop/confplanner/api/dto"
"github.com/LMBishop/confplanner/pkg/calendar"
- "github.com/gofiber/fiber/v2"
+ "github.com/LMBishop/confplanner/pkg/session"
)
-func GetCalendar(calendarService calendar.Service, baseURL string) fiber.Handler {
+func GetCalendar(calendarService calendar.Service, baseURL string) http.HandlerFunc {
// TODO create config service
- return func(c *fiber.Ctx) error {
- uid := c.Locals("uid").(int32)
+ return dto.WrapResponseFunc(func(w http.ResponseWriter, r *http.Request) error {
+ session := r.Context().Value("session").(*session.UserSession)
- cal, err := calendarService.GetCalendarForUser(uid)
+ cal, err := calendarService.GetCalendarForUser(session.UserID)
if err != nil {
if errors.Is(err, calendar.ErrCalendarNotFound) {
return &dto.ErrorResponse{
- Code: fiber.StatusNotFound,
+ Code: http.StatusNotFound,
Message: "Calendar not found",
}
}
@@ -26,7 +27,7 @@ func GetCalendar(calendarService calendar.Service, baseURL string) fiber.Handler
}
return &dto.OkResponse{
- Code: fiber.StatusOK,
+ Code: http.StatusOK,
Data: &dto.GetCalendarResponse{
ID: cal.ID,
Name: cal.Name,
@@ -34,20 +35,20 @@ func GetCalendar(calendarService calendar.Service, baseURL string) fiber.Handler
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)
+func CreateCalendar(calendarService calendar.Service, baseURL string) http.HandlerFunc {
+ return dto.WrapResponseFunc(func(w http.ResponseWriter, r *http.Request) error {
+ session := r.Context().Value("session").(*session.UserSession)
- cal, err := calendarService.CreateCalendarForUser(uid)
+ cal, err := calendarService.CreateCalendarForUser(session.UserID)
if err != nil {
return err
}
return &dto.OkResponse{
- Code: fiber.StatusCreated,
+ Code: http.StatusCreated,
Data: &dto.CreateCalendarResponse{
ID: cal.ID,
Name: cal.Name,
@@ -55,18 +56,18 @@ func CreateCalendar(calendarService calendar.Service, baseURL string) fiber.Hand
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)
+func DeleteCalendar(calendarService calendar.Service) http.HandlerFunc {
+ return dto.WrapResponseFunc(func(w http.ResponseWriter, r *http.Request) error {
+ session := r.Context().Value("session").(*session.UserSession)
- err := calendarService.DeleteCalendarForUser(uid)
+ err := calendarService.DeleteCalendarForUser(session.UserID)
if err != nil {
if errors.Is(err, calendar.ErrCalendarNotFound) {
return &dto.ErrorResponse{
- Code: fiber.StatusNotFound,
+ Code: http.StatusNotFound,
Message: "Calendar not found",
}
}
@@ -75,7 +76,7 @@ func DeleteCalendar(calendarService calendar.Service) fiber.Handler {
}
return &dto.OkResponse{
- Code: fiber.StatusOK,
+ Code: http.StatusOK,
}
- }
+ })
}
diff --git a/api/handlers/favourites.go b/api/handlers/favourites.go
index 862d366..502cb43 100644
--- a/api/handlers/favourites.go
+++ b/api/handlers/favourites.go
@@ -1,56 +1,58 @@
package handlers
import (
+ "net/http"
+
"github.com/LMBishop/confplanner/api/dto"
"github.com/LMBishop/confplanner/pkg/favourites"
- "github.com/gofiber/fiber/v2"
+ "github.com/LMBishop/confplanner/pkg/session"
"github.com/jackc/pgx/v5/pgtype"
)
-func CreateFavourite(service favourites.Service) fiber.Handler {
- return func(c *fiber.Ctx) error {
+func CreateFavourite(service favourites.Service) http.HandlerFunc {
+ return dto.WrapResponseFunc(func(w http.ResponseWriter, r *http.Request) error {
var request dto.CreateFavouritesRequest
- if err := readBody(c, &request); err != nil {
+ if err := dto.ReadDto(r, &request); err != nil {
return err
}
if request.GUID == nil && request.ID == nil {
return &dto.ErrorResponse{
- Code: fiber.StatusBadRequest,
+ Code: http.StatusBadRequest,
Message: "One of event GUID or event ID must be specified",
}
}
- uid := c.Locals("uid").(int32)
+ session := r.Context().Value("session").(*session.UserSession)
var uuid pgtype.UUID
if request.GUID != nil {
if err := uuid.Scan(*request.GUID); err != nil {
return &dto.ErrorResponse{
- Code: fiber.StatusBadRequest,
+ Code: http.StatusBadRequest,
Message: "Bad event GUID",
}
}
}
- createdFavourite, err := service.CreateFavouriteForUser(uid, uuid, request.ID)
+ createdFavourite, err := service.CreateFavouriteForUser(session.UserID, uuid, request.ID)
if err != nil {
return err
}
return &dto.OkResponse{
- Code: fiber.StatusCreated,
+ Code: http.StatusCreated,
Data: &dto.CreateFavouritesResponse{
ID: createdFavourite.ID,
},
}
- }
+ })
}
-func GetFavourites(service favourites.Service) fiber.Handler {
- return func(c *fiber.Ctx) error {
- uid := c.Locals("uid").(int32)
+func GetFavourites(service favourites.Service) http.HandlerFunc {
+ return dto.WrapResponseFunc(func(w http.ResponseWriter, r *http.Request) error {
+ session := r.Context().Value("session").(*session.UserSession)
- favourites, err := service.GetFavouritesForUser(uid)
+ favourites, err := service.GetFavouritesForUser(session.UserID)
if err != nil {
return err
}
@@ -64,41 +66,41 @@ func GetFavourites(service favourites.Service) fiber.Handler {
}
return &dto.OkResponse{
- Code: fiber.StatusOK,
+ Code: http.StatusOK,
Data: favouritesResponse,
}
- }
+ })
}
-func DeleteFavourite(service favourites.Service) fiber.Handler {
- return func(c *fiber.Ctx) error {
+func DeleteFavourite(service favourites.Service) http.HandlerFunc {
+ return dto.WrapResponseFunc(func(w http.ResponseWriter, r *http.Request) error {
var request dto.DeleteFavouritesRequest
- if err := readBody(c, &request); err != nil {
+ if err := dto.ReadDto(r, &request); err != nil {
return err
}
if request.GUID == nil && request.ID == nil {
return &dto.ErrorResponse{
- Code: fiber.StatusBadRequest,
+ Code: http.StatusBadRequest,
Message: "One of event GUID or event ID must be specified",
}
}
- uid := c.Locals("uid").(int32)
+ session := r.Context().Value("session").(*session.UserSession)
var err error
var uuid pgtype.UUID
if err := uuid.Scan(*request.GUID); err != nil {
return &dto.ErrorResponse{
- Code: fiber.StatusBadRequest,
+ Code: http.StatusBadRequest,
Message: "Bad event GUID",
}
}
- err = service.DeleteFavouriteForUserByEventDetails(uid, uuid, request.ID)
+ err = service.DeleteFavouriteForUserByEventDetails(session.UserID, uuid, request.ID)
if err != nil {
if err == favourites.ErrNotFound {
return &dto.ErrorResponse{
- Code: fiber.StatusNotFound,
+ Code: http.StatusNotFound,
Message: "Favourite not found",
}
}
@@ -106,7 +108,7 @@ func DeleteFavourite(service favourites.Service) fiber.Handler {
}
return &dto.OkResponse{
- Code: fiber.StatusOK,
+ Code: http.StatusOK,
}
- }
+ })
}
diff --git a/api/handlers/ical.go b/api/handlers/ical.go
index 52dfcdb..bcbf42b 100644
--- a/api/handlers/ical.go
+++ b/api/handlers/ical.go
@@ -2,43 +2,47 @@ package handlers
import (
"crypto/subtle"
+ "net/http"
"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")
+func GetIcal(icalService ical.Service, calendarService calendar.Service) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ name := r.URL.Query().Get("name")
+ key := r.URL.Query().Get("key")
if name == "" || key == "" {
- return &dto.ErrorResponse{
- Code: fiber.StatusBadRequest,
+ dto.WriteDto(w, r, &dto.ErrorResponse{
+ Code: http.StatusBadRequest,
Message: "Both name and key must be specified",
- }
+ })
+ return
}
calendar, err := calendarService.GetCalendarByName(name)
if err != nil {
- return err
+ dto.WriteDto(w, r, err)
+ return
}
if subtle.ConstantTimeCompare([]byte(key), []byte(calendar.Key)) != 1 {
- return &dto.ErrorResponse{
- Code: fiber.StatusUnauthorized,
+ dto.WriteDto(w, r, &dto.ErrorResponse{
+ Code: http.StatusUnauthorized,
Message: "Invalid key",
- }
+ })
+ return
}
ical, err := icalService.GenerateIcalForCalendar(*calendar)
if err != nil {
- return err
+ dto.WriteDto(w, r, err)
+ return
}
- c.Set("Content-Type", "text/calendar")
- return c.SendString(ical)
+ w.Header().Add("Content-Type", "text/calendar")
+ w.Write([]byte(ical))
}
}
diff --git a/api/handlers/schedule.go b/api/handlers/schedule.go
index 46589ab..061e6f9 100644
--- a/api/handlers/schedule.go
+++ b/api/handlers/schedule.go
@@ -1,25 +1,26 @@
package handlers
import (
+ "net/http"
+
"github.com/LMBishop/confplanner/api/dto"
"github.com/LMBishop/confplanner/pkg/schedule"
- "github.com/gofiber/fiber/v2"
"github.com/golang-cz/nilslice"
)
-func GetSchedule(service schedule.Service) fiber.Handler {
- return func(c *fiber.Ctx) error {
+func GetSchedule(service schedule.Service) http.HandlerFunc {
+ return dto.WrapResponseFunc(func(w http.ResponseWriter, r *http.Request) error {
schedule, lastUpdated, err := service.GetSchedule()
if err != nil {
return err
}
return &dto.OkResponse{
- Code: fiber.StatusOK,
+ Code: http.StatusOK,
Data: &dto.GetScheduleResponse{
Schedule: nilslice.Initialize(*schedule),
LastUpdated: lastUpdated,
},
}
- }
+ })
}
diff --git a/api/handlers/users.go b/api/handlers/users.go
index deda9ca..efb2e29 100644
--- a/api/handlers/users.go
+++ b/api/handlers/users.go
@@ -2,18 +2,17 @@ package handlers
import (
"errors"
- "time"
+ "net/http"
"github.com/LMBishop/confplanner/api/dto"
+ "github.com/LMBishop/confplanner/pkg/session"
"github.com/LMBishop/confplanner/pkg/user"
- "github.com/gofiber/fiber/v2"
- "github.com/gofiber/fiber/v2/middleware/session"
)
-func Register(service user.Service) fiber.Handler {
- return func(c *fiber.Ctx) error {
+func Register(service user.Service) http.HandlerFunc {
+ return dto.WrapResponseFunc(func(w http.ResponseWriter, r *http.Request) error {
var request dto.RegisterRequest
- if err := readBody(c, &request); err != nil {
+ if err := dto.ReadDto(r, &request); err != nil {
return err
}
@@ -21,12 +20,12 @@ func Register(service user.Service) fiber.Handler {
if err != nil {
if errors.Is(err, user.ErrUserExists) {
return &dto.ErrorResponse{
- Code: fiber.StatusConflict,
+ Code: http.StatusConflict,
Message: "User with that username already exists",
}
} else if errors.Is(err, user.ErrNotAcceptingRegistrations) {
return &dto.ErrorResponse{
- Code: fiber.StatusForbidden,
+ Code: http.StatusForbidden,
Message: "This service is not currently accepting registrations",
}
}
@@ -35,18 +34,18 @@ func Register(service user.Service) fiber.Handler {
}
return &dto.OkResponse{
- Code: fiber.StatusCreated,
+ Code: http.StatusCreated,
Data: &dto.RegisterResponse{
ID: createdUser.ID,
},
}
- }
+ })
}
-func Login(service user.Service, store *session.Store) fiber.Handler {
- return func(c *fiber.Ctx) error {
+func Login(service user.Service, store session.Service) http.HandlerFunc {
+ return dto.WrapResponseFunc(func(w http.ResponseWriter, r *http.Request) error {
var request dto.LoginRequest
- if err := readBody(c, &request); err != nil {
+ if err := dto.ReadDto(r, &request); err != nil {
return err
}
@@ -57,56 +56,43 @@ func Login(service user.Service, store *session.Store) fiber.Handler {
if user == nil {
return &dto.ErrorResponse{
- Code: fiber.StatusBadRequest,
+ Code: http.StatusBadRequest,
Message: "Username and password combination not found",
}
}
- s, err := store.Get(c)
+ session, err := store.Create(user.ID, user.Username, r.RemoteAddr, r.UserAgent())
if err != nil {
return err
}
- if s.Fresh() {
- uid := user.ID
- sid := s.ID()
-
- s.Set("uid", uid)
- s.Set("sid", sid)
- s.Set("ip", c.Context().RemoteIP().String())
- s.Set("login", time.Unix(time.Now().Unix(), 0).UTC().String())
- s.Set("ua", string(c.Request().Header.UserAgent()))
-
- err = s.Save()
- if err != nil {
- return err
- }
+ cookie := &http.Cookie{
+ Name: "confplanner_session",
+ Value: session.Token,
}
+ http.SetCookie(w, cookie)
return &dto.OkResponse{
- Code: fiber.StatusOK,
+ Code: http.StatusOK,
Data: &dto.LoginResponse{
ID: user.ID,
Username: user.Username,
},
}
- }
+ })
}
-func Logout(store *session.Store) fiber.Handler {
- return func(c *fiber.Ctx) error {
- s, err := store.Get(c)
- if err != nil {
- return err
- }
+func Logout(store session.Service) http.HandlerFunc {
+ return dto.WrapResponseFunc(func(w http.ResponseWriter, r *http.Request) error {
+ session := r.Context().Value("session").(*session.UserSession)
- err = s.Destroy()
+ err := store.Destroy(session.SessionID)
if err != nil {
return err
}
return &dto.OkResponse{
- Code: fiber.StatusNoContent,
+ Code: http.StatusNoContent,
}
- }
+ })
}
diff --git a/api/handlers/util.go b/api/handlers/util.go
deleted file mode 100644
index b0cf344..0000000
--- a/api/handlers/util.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package handlers
-
-import (
- "fmt"
-
- "github.com/go-playground/validator/v10"
- "github.com/gofiber/fiber/v2"
-)
-
-var validate = validator.New(validator.WithRequiredStructEnabled())
-
-func readBody(c *fiber.Ctx, request interface{}) error {
- if err := c.BodyParser(request); err != nil {
- return &fiber.Error{
- Code: fiber.StatusBadRequest,
- Message: fmt.Errorf("Invalid request (%w)", err).Error(),
- }
- }
-
- if err := validate.Struct(request); err != nil {
- return &fiber.Error{
- Code: fiber.StatusBadRequest,
- Message: err.Error(),
- }
- }
-
- return nil
-}