package api import ( "net/http" "project-dashboard/api/utils" "project-dashboard/middleware" "project-dashboard/models" "github.com/gin-gonic/gin" ) type LoginRequest struct { Email string `json:"email" binding:"required,email"` Password string `json:"password" binding:"required"` } type RegisterRequest struct { Email string `json:"email" binding:"required,email"` Password string `json:"password" binding:"required,min=6"` FirstName string `json:"first_name" binding:"required"` LastName string `json:"last_name" binding:"required"` } type AuthResponse struct { Token string `json:"token"` User models.User `json:"user"` } // Register creates a new user account func Register(c *gin.Context) { var req RegisterRequest if err := c.ShouldBindJSON(&req); err != nil { utils.ValidationErrorResponse(c, gin.H{ "error": err.Error(), }) return } // Check if user already exists var existingUser models.User if err := models.GetDB().Where("email = ?", req.Email).First(&existingUser).Error; err == nil { utils.ErrorResponse(c, http.StatusConflict, "User with this email already exists") return } // Create new user user := models.User{ Email: req.Email, FirstName: req.FirstName, LastName: req.LastName, Role: "member", // Default role } // Hash password if err := user.HashPassword(req.Password); err != nil { utils.ErrorResponse(c, http.StatusInternalServerError, "Failed to hash password") return } // Save user to database if err := models.GetDB().Create(&user).Error; err != nil { utils.ErrorResponse(c, http.StatusInternalServerError, "Failed to create user") return } // Generate token token, err := middleware.GenerateToken(&user) if err != nil { utils.ErrorResponse(c, http.StatusInternalServerError, "Failed to generate token") return } utils.SuccessResponse(c, http.StatusCreated, "User created successfully", AuthResponse{ Token: token, User: user, }) } // Login authenticates a user func Login(c *gin.Context) { var req LoginRequest if err := c.ShouldBindJSON(&req); err != nil { utils.ValidationErrorResponse(c, gin.H{ "error": err.Error(), }) return } // Find user by email var user models.User if err := models.GetDB().Where("email = ?", req.Email).First(&user).Error; err != nil { utils.ErrorResponse(c, http.StatusUnauthorized, "Invalid email or password") return } // Check password if !user.CheckPassword(req.Password) { utils.ErrorResponse(c, http.StatusUnauthorized, "Invalid email or password") return } // Generate token token, err := middleware.GenerateToken(&user) if err != nil { utils.ErrorResponse(c, http.StatusInternalServerError, "Failed to generate token") return } utils.SuccessResponse(c, http.StatusOK, "Login successful", AuthResponse{ Token: token, User: user, }) } // GetProfile returns the current user's profile func GetProfile(c *gin.Context) { user, exists := c.Get("user") if !exists { utils.ErrorResponse(c, http.StatusUnauthorized, "User not authenticated") return } utils.SuccessResponse(c, http.StatusOK, "Profile retrieved successfully", user) } // UpdateProfile updates the current user's profile func UpdateProfile(c *gin.Context) { user, exists := c.Get("user") if !exists { utils.ErrorResponse(c, http.StatusUnauthorized, "User not authenticated") return } userObj := user.(*models.User) var updateData struct { FirstName string `json:"first_name"` LastName string `json:"last_name"` Avatar string `json:"avatar"` } if err := c.ShouldBindJSON(&updateData); err != nil { utils.ValidationErrorResponse(c, gin.H{ "error": err.Error(), }) return } // Update fields if updateData.FirstName != "" { userObj.FirstName = updateData.FirstName } if updateData.LastName != "" { userObj.LastName = updateData.LastName } if updateData.Avatar != "" { userObj.Avatar = updateData.Avatar } if err := models.GetDB().Save(userObj).Error; err != nil { utils.ErrorResponse(c, http.StatusInternalServerError, "Failed to update profile") return } utils.SuccessResponse(c, http.StatusOK, "Profile updated successfully", userObj) } // ChangePassword changes the user's password func ChangePassword(c *gin.Context) { user, exists := c.Get("user") if !exists { utils.ErrorResponse(c, http.StatusUnauthorized, "User not authenticated") return } userObj := user.(*models.User) var req struct { CurrentPassword string `json:"current_password" binding:"required"` NewPassword string `json:"new_password" binding:"required,min=6"` } if err := c.ShouldBindJSON(&req); err != nil { utils.ValidationErrorResponse(c, gin.H{ "error": err.Error(), }) return } // Verify current password if !userObj.CheckPassword(req.CurrentPassword) { utils.ErrorResponse(c, http.StatusBadRequest, "Current password is incorrect") return } // Hash new password if err := userObj.HashPassword(req.NewPassword); err != nil { utils.ErrorResponse(c, http.StatusInternalServerError, "Failed to hash new password") return } if err := models.GetDB().Save(userObj).Error; err != nil { utils.ErrorResponse(c, http.StatusInternalServerError, "Failed to update password") return } utils.SuccessResponse(c, http.StatusOK, "Password changed successfully", nil) }