Skip to content

Commit

Permalink
feat: add error handling for user and event
Browse files Browse the repository at this point in the history
  • Loading branch information
peterxcli committed Feb 4, 2024
1 parent ffceb1a commit 89de7d7
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 8 deletions.
40 changes: 35 additions & 5 deletions pkg/controller/user_controller.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package controller

import (
"errors"
"fmt"
"net/http"
"strconv"
Expand All @@ -9,6 +10,7 @@ import (

"bikefest/pkg/bootstrap"
"bikefest/pkg/model"
"bikefest/pkg/service"

"github.com/gin-gonic/gin"
)
Expand Down Expand Up @@ -37,13 +39,21 @@ func NewUserController(userSvc model.UserService, eventSvc model.EventService, a
// @Produce json
// @Security ApiKeyAuth
// @Success 200 {object} model.UserResponse "Profile successfully retrieved"
// @Failure 401 {object} model.Response "Unauthorized: Invalid or expired token"
// @Failure 404 {object} model.Response "User not found"
// @Failure 500 {object} model.Response "Internal Server Error"
// @Router /users/profile [get]
func (ctrl *UserController) Profile(c *gin.Context) {
identity, _ := RetrieveIdentity(c, true)
userID := identity.UserID
profile, err := ctrl.userSvc.GetUserByID(c, userID)
if err != nil {
switch {
case errors.Is(err, service.ErrUserNotFound):
c.AbortWithStatusJSON(http.StatusNotFound, model.Response{
Msg: "User not found",
})
return
case err != nil:
c.AbortWithStatusJSON(http.StatusInternalServerError, model.Response{
Msg: err.Error(),
})
Expand All @@ -62,12 +72,19 @@ func (ctrl *UserController) Profile(c *gin.Context) {
// @Produce json
// @Param user_id path string true "User ID"
// @Success 200 {object} model.UserResponse "User successfully retrieved"
// @Failure 404 {object} model.Response "User not found"
// @Failure 500 {object} model.Response "Internal Server Error"
// @Router /users/{user_id} [get]
func (ctrl *UserController) GetUserByID(c *gin.Context) {
userID := c.Param("user_id")
user, err := ctrl.userSvc.GetUserByID(c, userID)
if err != nil {
switch {
case errors.Is(err, service.ErrUserNotFound):
c.AbortWithStatusJSON(http.StatusNotFound, model.Response{
Msg: "User not found",
})
return
case err != nil:
c.AbortWithStatusJSON(http.StatusInternalServerError, model.Response{
Msg: err.Error(),
})
Expand Down Expand Up @@ -287,8 +304,10 @@ func (ctrl *UserController) FakeRegister(c *gin.Context) {
// @Security ApiKeyAuth
// @Param request body model.CreateEventRequest true "Event Subscription Request"
// @Success 200 {object} model.EventResponse "Successfully subscribed to the event"
// @Failure 400 {object} model.Response "Bad Request - Invalid input"
// @Failure 500 {object} model.Response "Internal Server Error"
// @Failure 400 {object} model.Response "Bad Request - Invalid input, such as invalid time format or missing required fields"
// @Failure 409 {object} model.Response "Conflict - User already subscribed to the event"
// @Failure 422 {object} model.Response "Unprocessable Entity - User has exceeded the maximum number of subscriptions"
// @Failure 500 {object} model.Response "Internal Server Error - Error storing the event, subscribing the user, or enqueuing the event notification"
// @Router /users/events [post]
func (ctrl *UserController) SubscribeEvent(c *gin.Context) {
identity, _ := RetrieveIdentity(c, true)
Expand Down Expand Up @@ -331,7 +350,18 @@ func (ctrl *UserController) SubscribeEvent(c *gin.Context) {
}
_ = ctrl.eventSvc.Store(c, newEvent)
err = ctrl.userSvc.SubscribeEvent(c, userID, *newEvent.ID)
if err != nil {
switch {
case errors.Is(err, service.ErrEventExceedsMaxSubscriptions):
c.AbortWithStatusJSON(http.StatusUnprocessableEntity, model.Response{
Msg: "User has exceeded the maximum number of subscriptions",
})
return
case errors.Is(err, service.ErrEventAlreadySubscribed):
c.AbortWithStatusJSON(http.StatusConflict, model.Response{
Msg: "User already subscribed to the event",
})
return
case err != nil:
c.AbortWithStatusJSON(http.StatusInternalServerError, model.Response{
Msg: err.Error(),
})
Expand Down
11 changes: 8 additions & 3 deletions pkg/service/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (

var (
ErrEventExceedsMaxSubscriptions = errors.New("exceeds the maximum number of subscriptions")
ErrEventAlreadySubscribed = errors.New("already subscribed to this event")
ErrUserNotFound = errors.New("user not found")
)

func NewUserService(db *gorm.DB, cache *redis.Client) model.UserService {
Expand All @@ -35,12 +37,12 @@ func (us *UserServiceImpl) SubscribeEvent(ctx context.Context, userID string, ev
return err
}
if event.ID != nil {
return errors.New("already subscribed this event")
return ErrEventAlreadySubscribed
}
// Check if events exceed 10
// TODO: meow
if count := us.db.WithContext(ctx).Model(&model.User{ID: userID}).Association("Events").Count(); count >= 10 {
return errors.New("exceeds the maximum number of subscriptions")
return ErrEventExceedsMaxSubscriptions
}
return us.db.WithContext(ctx).Model(&model.User{ID: userID}).Association("Events").Append(&model.Event{ID: &eventID})
}
Expand Down Expand Up @@ -75,7 +77,10 @@ func (us *UserServiceImpl) CreateFakeUser(ctx context.Context, user *model.User)
func (us *UserServiceImpl) GetUserByID(ctx context.Context, id string) (*model.User, error) {
user := &model.User{}
err := us.db.WithContext(ctx).Where(&model.User{ID: id}).First(user).Error
if err != nil {
switch {
case errors.Is(err, gorm.ErrRecordNotFound):
return nil, ErrUserNotFound
case err != nil:
return nil, err
}
return user, nil
Expand Down

0 comments on commit 89de7d7

Please sign in to comment.