diff options
| author | Leonardo Bishop <me@leonardobishop.com> | 2025-08-14 18:07:12 +0100 |
|---|---|---|
| committer | Leonardo Bishop <me@leonardobishop.com> | 2025-08-14 18:07:12 +0100 |
| commit | 4697556cac819c47d068819b9fc9c3b4ea84e279 (patch) | |
| tree | b832d8fc6b643a8b9d0eeca35c1268e1649da731 /api | |
| parent | dd49c9205bb04844b686b9c3396c40eb49d25826 (diff) | |
Merge confplanner-web and replace fiber with native net/http
Diffstat (limited to 'api')
| -rw-r--r-- | api/dto/response.go | 17 | ||||
| -rw-r--r-- | api/dto/util.go | 54 | ||||
| -rw-r--r-- | api/handlers/calendar.go | 43 | ||||
| -rw-r--r-- | api/handlers/favourites.go | 54 | ||||
| -rw-r--r-- | api/handlers/ical.go | 34 | ||||
| -rw-r--r-- | api/handlers/schedule.go | 11 | ||||
| -rw-r--r-- | api/handlers/users.go | 66 | ||||
| -rw-r--r-- | api/handlers/util.go | 28 | ||||
| -rw-r--r-- | api/middleware/auth.go | 62 | ||||
| -rw-r--r-- | api/router.go | 78 |
10 files changed, 224 insertions, 223 deletions
diff --git a/api/dto/response.go b/api/dto/response.go index 43f98bd..2c13218 100644 --- a/api/dto/response.go +++ b/api/dto/response.go @@ -2,20 +2,37 @@ package dto import "fmt" +type Response interface { + Error() string + Status() int +} + type OkResponse struct { Code int `json:"code"` Data interface{} `json:"data,omitempty"` } +var _ Response = (*OkResponse)(nil) + type ErrorResponse struct { Code int `json:"code"` Message string `json:"message"` } +var _ Response = (*ErrorResponse)(nil) + +func (r *OkResponse) Status() int { + return r.Code +} + func (r *OkResponse) Error() string { return fmt.Sprintf("HTTP status %d", r.Code) } +func (r *ErrorResponse) Status() int { + return r.Code +} + func (r *ErrorResponse) Error() string { return fmt.Sprintf("HTTP status %d: %s", r.Code, r.Message) } diff --git a/api/dto/util.go b/api/dto/util.go new file mode 100644 index 0000000..cb3ea52 --- /dev/null +++ b/api/dto/util.go @@ -0,0 +1,54 @@ +package dto + +import ( + "encoding/json" + "fmt" + "log/slog" + "net/http" + + "github.com/go-playground/validator/v10" +) + +var validate = validator.New(validator.WithRequiredStructEnabled()) + +func ReadDto(r *http.Request, o interface{}) Response { + decoder := json.NewDecoder(r.Body) + if err := decoder.Decode(o); err != nil { + return &ErrorResponse{ + Code: http.StatusBadRequest, + Message: fmt.Errorf("Invalid request (%w)", err).Error(), + } + } + + if err := validate.Struct(o); err != nil { + return &ErrorResponse{ + Code: http.StatusBadRequest, + Message: err.Error(), + } + } + + return nil +} + +func WrapResponseFunc(dtoFunc func(http.ResponseWriter, *http.Request) error) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + WriteDto(w, r, dtoFunc(w, r)) + } +} + +func WriteDto(w http.ResponseWriter, r *http.Request, o error) { + if o, ok := o.(Response); ok { + data, err := json.Marshal(o) + if err != nil { + w.WriteHeader(500) + slog.Error("could not serialise JSON", "error", err) + return + } + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(o.Status()) + w.Write(data) + } else { + w.WriteHeader(500) + slog.Error("internal server error handling request", "error", o) + } +} 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 -} diff --git a/api/middleware/auth.go b/api/middleware/auth.go index 611276a..eb362b0 100644 --- a/api/middleware/auth.go +++ b/api/middleware/auth.go @@ -1,46 +1,52 @@ package middleware import ( + "context" "errors" + "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 RequireAuthenticated(service user.Service, store *session.Store) fiber.Handler { - return func(c *fiber.Ctx) error { - s, err := store.Get(c) - if err != nil { - return err - } - - if s.Fresh() || len(s.Keys()) == 0 { - return &dto.ErrorResponse{ - Code: fiber.StatusUnauthorized, - Message: "Unauthorized", +func MustAuthenticate(service user.Service, store session.Service) func(http.HandlerFunc) http.HandlerFunc { + return func(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var sessionToken string + for _, cookie := range r.Cookies() { + if cookie.Name == "confplanner_session" { + sessionToken = cookie.Value + break + } } - } - uid := s.Get("uid").(int32) + s := store.GetByToken(sessionToken) + if s == nil { + dto.WriteDto(w, r, &dto.ErrorResponse{ + Code: http.StatusUnauthorized, + Message: "Unauthorized", + }) + return + } - fetchedUser, err := service.GetUserByID(uid) - if err != nil { - if errors.Is(err, user.ErrUserNotFound) { - s.Destroy() - return &dto.ErrorResponse{ - Code: fiber.StatusUnauthorized, - Message: "Invalid session", + _, err := service.GetUserByID(s.UserID) + if err != nil { + if errors.Is(err, user.ErrUserNotFound) { + store.Destroy(s.SessionID) + dto.WriteDto(w, r, &dto.ErrorResponse{ + Code: http.StatusForbidden, + Message: "Invalid session", + }) + return } - } - return err - } + return + } - c.Locals("uid", uid) - c.Locals("username", fetchedUser.Username) + ctx := context.WithValue(r.Context(), "session", s) - return c.Next() + next(w, r.WithContext(ctx)) + } } } diff --git a/api/router.go b/api/router.go index 99c79c7..423529f 100644 --- a/api/router.go +++ b/api/router.go @@ -1,22 +1,16 @@ package api import ( - "crypto/rand" - "encoding/hex" - "errors" - "log/slog" - "time" + "net/http" - "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/session" "github.com/LMBishop/confplanner/pkg/user" - "github.com/gofiber/fiber/v2" - "github.com/gofiber/fiber/v2/middleware/session" ) type ApiServices struct { @@ -25,64 +19,28 @@ type ApiServices struct { ScheduleService schedule.Service CalendarService calendar.Service IcalService ical.Service + SessionService session.Service } -func NewServer(apiServices ApiServices, baseURL string) *fiber.App { - sessionStore := session.New(session.Config{ - Expiration: 7 * 24 * time.Hour, - KeyGenerator: generateSessionToken, - KeyLookup: "cookie:confplanner_session", - CookieSameSite: "Strict", - CookieSecure: true, - }) +func NewServer(apiServices ApiServices, baseURL string) *http.ServeMux { + mustAuthenticate := middleware.MustAuthenticate(apiServices.UserService, apiServices.SessionService) - app := fiber.New(fiber.Config{ - ErrorHandler: func(ctx *fiber.Ctx, err error) error { - var ok *dto.OkResponse - if errors.As(err, &ok) { - return ctx.Status(ok.Code).JSON(ok) - } + mux := http.NewServeMux() - var e *dto.ErrorResponse - if errors.As(err, &e) { - return ctx.Status(e.Code).JSON(e) - } + mux.HandleFunc("POST /register", handlers.Register(apiServices.UserService)) + mux.HandleFunc("POST /login", handlers.Login(apiServices.UserService, apiServices.SessionService)) + mux.HandleFunc("POST /logout", mustAuthenticate(handlers.Register(apiServices.UserService))) - slog.Error("fiber runtime error", "error", err, "URL", ctx.OriginalURL()) - return ctx.Status(500).JSON(dto.ErrorResponse{ - Code: 500, - Message: "Internal Server Error", - }) - }, - AppName: "confplanner", - }) + mux.HandleFunc("GET /favourites", mustAuthenticate(handlers.GetFavourites(apiServices.FavouritesService))) + mux.HandleFunc("POST /favourites", mustAuthenticate(handlers.CreateFavourite(apiServices.FavouritesService))) + mux.HandleFunc("DELETE /favourites", mustAuthenticate(handlers.DeleteFavourite(apiServices.FavouritesService))) - // app.Use(cors.New()) + mux.HandleFunc("GET /schedule", mustAuthenticate(handlers.GetSchedule(apiServices.ScheduleService))) - requireAuthenticated := middleware.RequireAuthenticated(apiServices.UserService, sessionStore) + mux.HandleFunc("GET /calendar", mustAuthenticate(handlers.GetCalendar(apiServices.CalendarService, baseURL))) + mux.HandleFunc("POST /calendar", mustAuthenticate(handlers.CreateCalendar(apiServices.CalendarService, baseURL))) + mux.HandleFunc("DELETE /calendar", mustAuthenticate(handlers.DeleteCalendar(apiServices.CalendarService))) + mux.HandleFunc("/calendar/ical", handlers.GetIcal(apiServices.IcalService, apiServices.CalendarService)) - app.Post("/register", handlers.Register(apiServices.UserService)) - app.Post("/login", handlers.Login(apiServices.UserService, sessionStore)) - app.Post("/logout", requireAuthenticated, handlers.Logout(sessionStore)) - - app.Get("/favourites", requireAuthenticated, handlers.GetFavourites(apiServices.FavouritesService)) - app.Post("/favourites", requireAuthenticated, handlers.CreateFavourite(apiServices.FavouritesService)) - app.Delete("/favourites", requireAuthenticated, handlers.DeleteFavourite(apiServices.FavouritesService)) - - 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 -} - -func generateSessionToken() string { - b := make([]byte, 100) - if _, err := rand.Read(b); err != nil { - return "" - } - return hex.EncodeToString(b) + return mux } |
