diff --git a/internal/controllers/user_controller.go b/internal/controllers/user_controller.go index b1d1d9c..6bf7f9f 100644 --- a/internal/controllers/user_controller.go +++ b/internal/controllers/user_controller.go @@ -95,6 +95,36 @@ func (uc *UserController) UpdateHandler(c *gin.Context) { c.JSON(http.StatusAccepted, gin.H{"message": "User updated successfully", "user": updatedUser.Safe()}) } +func (uc *UserController) DeleteUser(c *gin.Context) { + + requestUser, err := uc.extractUserFromContext(c) + if err != nil { + utils.RespondWithError(c, err, "Error extracting user from context in UpdateHandler", http.StatusBadRequest, "general", "server.validation.no_auth_tokenw") + return + } + + type deleteData = struct { + ID uint `json:"id"` + LastName string `json:"lastname"` + } + + var deletedUser deleteData + if err := c.ShouldBindJSON(&deletedUser); err != nil { + utils.HandleValidationError(c, err) + return + } + + if !utils.HasPrivilige(requestUser, constants.Priviliges.Update) && deletedUser.ID != requestUser.ID { + utils.RespondWithError(c, errors.ErrNotAuthorized, "Not allowed to delete user", http.StatusForbidden, "user", "server.error.unauthorized") + return + } + + if err := uc.Service.DeleteUser(deletedUser.LastName, deletedUser.ID); err != nil { + utils.RespondWithError(c, err, "Error during user deletion", http.StatusInternalServerError, "user", "server.error.internal_server_error") + return + } +} + func (uc *UserController) extractUserFromContext(c *gin.Context) (*models.User, error) { tokenString, err := c.Cookie("jwt") diff --git a/internal/models/bank_account.go b/internal/models/bank_account.go index a9bb8a8..24996e9 100644 --- a/internal/models/bank_account.go +++ b/internal/models/bank_account.go @@ -6,8 +6,8 @@ type BankAccount struct { CreatedAt time.Time UpdatedAt time.Time MandateDateSigned time.Time `gorm:"not null" json:"mandate_date_signed"` - Bank string `json:"bank_name" binding:"omitempty,alphanumunicode,safe_content"` - AccountHolderName string `json:"account_holder_name" binding:"omitempty,alphaunicode,safe_content"` + Bank string `json:"bank_name" binding:"safe_content"` + AccountHolderName string `json:"account_holder_name" binding:"safe_content"` IBAN string `json:"iban"` BIC string `json:"bic"` MandateReference string `gorm:"not null" json:"mandate_reference"` diff --git a/internal/repositories/user_repository.go b/internal/repositories/user_repository.go index 446d3cf..feb6582 100644 --- a/internal/repositories/user_repository.go +++ b/internal/repositories/user_repository.go @@ -21,10 +21,15 @@ type UserRepositoryInterface interface { SetVerificationToken(verification *models.Verification) (uint, error) IsVerified(userID *uint) (bool, error) GetVerificationOfToken(token *string) (*models.Verification, error) + DeleteUser(id uint) error } type UserRepository struct{} +func (ur *UserRepository) DeleteUser(id uint) error { + return database.DB.Delete(&models.User{}, "id = ?", id).Error +} + func PasswordExists(userID *uint) (bool, error) { var user models.User result := database.DB.Select("password").First(&user, userID) @@ -60,7 +65,7 @@ func (ur *UserRepository) UpdateUser(user *models.User) (*models.User, error) { return err } // Update the user's main fields - result := tx.Session(&gorm.Session{FullSaveAssociations: true}).Updates(user) + result := tx.Session(&gorm.Session{FullSaveAssociations: true}).Omit("Password").Updates(user) if result.Error != nil { return result.Error } @@ -68,6 +73,14 @@ func (ur *UserRepository) UpdateUser(user *models.User) (*models.User, error) { return errors.ErrNoRowsAffected } + if user.Password != "" { + if err := tx.Model(&models.User{}). + Where("id = ?", user.ID). + Update("Password", user.Password).Error; err != nil { + return err + } + } + // Update the Membership if provided if user.Membership.ID != 0 { if err := tx.Model(&existingUser.Membership).Updates(user.Membership).Error; err != nil { diff --git a/internal/routes/routes.go b/internal/routes/routes.go index cd6b0f8..31b5bfb 100644 --- a/internal/routes/routes.go +++ b/internal/routes/routes.go @@ -26,9 +26,10 @@ func RegisterRoutes(router *gin.Engine, userController *controllers.UserControll { userRouter.GET("/current", userController.CurrentUserHandler) userRouter.POST("/logout", userController.LogoutHandler) - userRouter.PATCH("/update", userController.UpdateHandler) - userRouter.POST("/update", userController.RegisterUser) + userRouter.PATCH("/upsert", userController.UpdateHandler) + userRouter.POST("/upsert", userController.RegisterUser) userRouter.GET("/all", userController.GetAllUsers) + userRouter.DELETE("/delete", userController.DeleteUser) } membershipRouter := router.Group("/backend/membership") diff --git a/internal/services/user_service.go b/internal/services/user_service.go index cf78454..af1f802 100644 --- a/internal/services/user_service.go +++ b/internal/services/user_service.go @@ -24,6 +24,7 @@ type UserServiceInterface interface { GetUsers(where map[string]interface{}) (*[]models.User, error) VerifyUser(token *string) (*models.User, error) UpdateUser(user *models.User) (*models.User, error) + DeleteUser(lastname string, id uint) error } type UserService struct { @@ -31,6 +32,22 @@ type UserService struct { Licences repositories.LicenceInterface } +func (service *UserService) DeleteUser(lastname string, id uint) error { + if id == 0 || lastname == "" { + return errors.ErrNoData + } + + user, err := service.GetUserByID(id) + if err != nil { + return err + } + if user == nil { + return errors.ErrUserNotFound + } + + return service.Repo.DeleteUser(id) +} + func (service *UserService) UpdateUser(user *models.User) (*models.User, error) { if user.ID == 0 { diff --git a/internal/validation/DriversLicence_validation.go b/internal/validation/DriversLicence_validation.go index f2c564c..5987ae2 100644 --- a/internal/validation/DriversLicence_validation.go +++ b/internal/validation/DriversLicence_validation.go @@ -2,7 +2,6 @@ package validation import ( "GoMembership/internal/models" - "strconv" "time" "github.com/go-playground/validator/v10" @@ -10,7 +9,8 @@ import ( func validateDriverslicence(sl validator.StructLevel) { dl := sl.Current().Interface().(models.User).Licence - if !validateLicence(dl.Number) { + // if !vValidateLicence(dl.Number) { + if dl.Number == "" { sl.ReportError(dl.Number, "licence_number", "", "invalid", "") } if dl.IssuedDate.After(time.Now()) { @@ -21,32 +21,33 @@ func validateDriverslicence(sl validator.StructLevel) { } } -func validateLicence(fieldValue string) bool { - if len(fieldValue) != 11 { - return false - } +// seems like not every country has to have an licence id and it seems that germany changed their id generation type.. +// func validateLicence(fieldValue string) bool { +// if len(fieldValue) != 11 { +// return false +// } - id, tenthChar := string(fieldValue[:9]), string(fieldValue[9]) +// id, tenthChar := string(fieldValue[:9]), string(fieldValue[9]) - if tenthChar == "X" { - tenthChar = "10" - } - tenthValue, _ := strconv.ParseInt(tenthChar, 10, 8) +// if tenthChar == "X" { +// tenthChar = "10" +// } +// tenthValue, _ := strconv.ParseInt(tenthChar, 10, 8) - // for readability - weights := []int{9, 8, 7, 6, 5, 4, 3, 2, 1} - sum := 0 +// // for readability +// weights := []int{9, 8, 7, 6, 5, 4, 3, 2, 1} +// sum := 0 - for i := 0; i < 9; i++ { - char := string(id[i]) - value, _ := strconv.ParseInt(char, 36, 64) - sum += int(value) * weights[i] - } +// for i := 0; i < 9; i++ { +// char := string(id[i]) +// value, _ := strconv.ParseInt(char, 36, 64) +// sum += int(value) * weights[i] +// } - calcCheckDigit := sum % 11 - if calcCheckDigit != int(tenthValue) { - return false - } +// calcCheckDigit := sum % 11 +// if calcCheckDigit != int(tenthValue) { +// return false +// } - return true -} +// return true +// } diff --git a/internal/validation/user_validation.go b/internal/validation/user_validation.go index c965c10..a05f18a 100644 --- a/internal/validation/user_validation.go +++ b/internal/validation/user_validation.go @@ -27,7 +27,6 @@ func validateUser(sl validator.StructLevel) { sl.ReportError(user.DateOfBirth, "DateOfBirth", "dateofbirth", "age", "") } // validate subscriptionModel - logger.Error.Printf("User SubscriptionModel.Name: %#v", user.Membership.SubscriptionModel.Name) if user.Membership.SubscriptionModel.Name == "" { sl.ReportError(user.Membership.SubscriptionModel.Name, "SubscriptionModel.Name", "name", "required", "") } else {