package handlers import ( "encoding/json" "fmt" "hamster-tycoon/storage/dao" "hamster-tycoon/storage/model" "hamster-tycoon/storage/validators" "hamster-tycoon/utils" "net/http" "strings" "github.com/gin-gonic/gin" "google.golang.org/api/oauth2/v2" ) var httpClient = &http.Client{} func (hc *handlersContext) getAllUsers(c *gin.Context) { users, err := hc.db.GetAllUsers() if err != nil { utils.GetLoggerFromCtx(c).WithError(err).Error("error while getting users") utils.JSONErrorWithMessage(c.Writer, model.ErrInternalServer, "Error while getting users") return } utils.JSON(c.Writer, http.StatusOK, users) } func (hc *handlersContext) connectUser(c *gin.Context) { authorizationHeader := c.GetHeader("Authorization") authorizationHeaderSplitted := strings.Split(authorizationHeader, " ") if len(authorizationHeaderSplitted) != 2 { utils.JSONError(c.Writer, model.ErrBadRequestFormat) return } oauth2Service, err := oauth2.New(httpClient) tokenInfoCall := oauth2Service.Tokeninfo() tokenInfoCall.IdToken(authorizationHeaderSplitted[1]) tokenInfo, err := tokenInfoCall.Do() if err != nil { utils.GetLogger().WithError(err).Error(err) utils.JSONError(c.Writer, model.ErrBadRequestFormat) return } user, err := hc.userService.GetUserFromGoogleID(tokenInfo.UserId) if err != nil { utils.GetLogger().WithError(err).Error(err) if castedError, ok := err.(*model.APIError); ok { if castedError.Type == model.ErrNotFound.Type { user, err := hc.userService.CreateUserFromGoogleToken(tokenInfo.UserId, tokenInfo.Email) if err != nil { fmt.Println(err) utils.JSONError(c.Writer, model.ErrInternalServer) return } utils.JSON(c.Writer, 200, user) return } utils.JSONError(c.Writer, *castedError) return } utils.JSONError(c.Writer, model.ErrInternalServer) return } utils.JSON(c.Writer, 200, user) } func (hc *handlersContext) createUser(c *gin.Context) { b, err := c.GetRawData() if err != nil { utils.GetLoggerFromCtx(c).WithError(err).Error("error while creating user, read data fail") utils.JSONError(c.Writer, model.ErrInternalServer) return } userToCreate := model.UserEditable{} err = json.Unmarshal(b, &userToCreate) if err != nil { utils.JSONError(c.Writer, model.ErrBadRequestFormat) return } err = hc.validator.StructCtx(c, userToCreate) if err != nil { utils.JSONError(c.Writer, validators.NewDataValidationAPIError(err)) return } user := model.User{ UserEditable: userToCreate, } err = hc.db.CreateUser(&user) if e, ok := err.(*dao.Error); ok { switch { case e.Type == dao.ErrTypeDuplicate: utils.JSONErrorWithMessage(c.Writer, model.ErrAlreadyExists, "User already exists") return default: utils.GetLoggerFromCtx(c).WithError(err).WithField("type", e.Type).Error("error CreateUser: Error type not handled") utils.JSONError(c.Writer, model.ErrInternalServer) return } } else if err != nil { utils.GetLoggerFromCtx(c).WithError(err).Error("error while creating user") utils.JSONError(c.Writer, model.ErrInternalServer) return } utils.JSON(c.Writer, http.StatusCreated, user) } func (hc *handlersContext) getUser(c *gin.Context) { userID := c.Param("id") err := hc.validator.VarCtx(c, userID, "uuid4") if err != nil { utils.JSONError(c.Writer, validators.NewDataValidationAPIError(err)) return } user, err := hc.db.GetUsersByID(userID) if e, ok := err.(*dao.Error); ok { switch { case e.Type == dao.ErrTypeNotFound: utils.JSONErrorWithMessage(c.Writer, model.ErrNotFound, "User not found") return default: utils.GetLoggerFromCtx(c).WithError(err).WithField("type", e.Type).Error("error GetUser: get user error type not handled") utils.JSONError(c.Writer, model.ErrInternalServer) return } } else if err != nil { utils.GetLoggerFromCtx(c).WithError(err).Error("error while get user") utils.JSONError(c.Writer, model.ErrInternalServer) return } if user == nil { utils.JSONErrorWithMessage(c.Writer, model.ErrNotFound, "User not found") return } utils.JSON(c.Writer, http.StatusOK, user) } func (hc *handlersContext) deleteUser(c *gin.Context) { userID := c.Param("id") err := hc.validator.VarCtx(c, userID, "uuid4") if err != nil { utils.JSONError(c.Writer, validators.NewDataValidationAPIError(err)) return } // check user id given in URL exists _, err = hc.db.GetUsersByID(userID) if e, ok := err.(*dao.Error); ok { switch { case e.Type == dao.ErrTypeNotFound: utils.JSONErrorWithMessage(c.Writer, model.ErrNotFound, "User to delete not found") return default: utils.GetLoggerFromCtx(c).WithError(err).WithField("type", e.Type).Error("error DeleteUser: get user error type not handled") utils.JSONError(c.Writer, model.ErrInternalServer) return } } else if err != nil { utils.GetLoggerFromCtx(c).WithError(err).Error("error while get user to delete") utils.JSONError(c.Writer, model.ErrInternalServer) return } err = hc.db.DeleteUser(userID) if e, ok := err.(*dao.Error); ok { switch { case e.Type == dao.ErrTypeNotFound: utils.JSONErrorWithMessage(c.Writer, model.ErrNotFound, "User to delete not found") return default: utils.GetLoggerFromCtx(c).WithError(err).WithField("type", e.Type).Error("error DeleteUser: Error type not handled") utils.JSONError(c.Writer, model.ErrInternalServer) return } } else if err != nil { utils.GetLoggerFromCtx(c).WithError(err).Error("error while deleting user") utils.JSONError(c.Writer, model.ErrInternalServer) return } utils.JSON(c.Writer, http.StatusNoContent, nil) } func (hc *handlersContext) updateUser(c *gin.Context) { userID := c.Param("id") err := hc.validator.VarCtx(c, userID, "uuid4") if err != nil { utils.JSONError(c.Writer, validators.NewDataValidationAPIError(err)) return } // check user id given in URL exists user, err := hc.db.GetUsersByID(userID) if e, ok := err.(*dao.Error); ok { switch { case e.Type == dao.ErrTypeNotFound: utils.JSONErrorWithMessage(c.Writer, model.ErrNotFound, "User to update not found") return default: utils.GetLoggerFromCtx(c).WithError(err).WithField("type", e.Type).Error("deleteUser: get user error type not handled") utils.JSONError(c.Writer, model.ErrInternalServer) return } } else if err != nil { utils.GetLoggerFromCtx(c).WithError(err).Error("error while get user to update") utils.JSONError(c.Writer, model.ErrInternalServer) return } // get body and verify data b, err := c.GetRawData() if err != nil { utils.GetLoggerFromCtx(c).WithError(err).Error("error while updating user, read data fail") utils.JSONError(c.Writer, model.ErrInternalServer) return } userToUpdate := model.UserEditable{} err = json.Unmarshal(b, &userToUpdate) if err != nil { utils.JSONError(c.Writer, model.ErrBadRequestFormat) return } err = hc.validator.StructCtx(c, userToUpdate) if err != nil { utils.JSONError(c.Writer, validators.NewDataValidationAPIError(err)) return } user.UserEditable = userToUpdate // make the update err = hc.db.UpdateUser(user) if e, ok := err.(*dao.Error); ok { switch { case e.Type == dao.ErrTypeNotFound: utils.JSONErrorWithMessage(c.Writer, model.ErrNotFound, "User to update not found") return default: utils.GetLoggerFromCtx(c).WithError(err).WithField("type", e.Type).Error("error UpdateUser: Error type not handled") utils.JSONError(c.Writer, model.ErrInternalServer) return } } else if err != nil { utils.GetLoggerFromCtx(c).WithError(err).Error("error while deleting user") utils.JSONError(c.Writer, model.ErrInternalServer) return } utils.JSON(c.Writer, http.StatusOK, user) }