Files
2025-09-12 12:38:11 +02:00

209 lines
5.2 KiB
Go

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)
}