package handler import ( "net/http" "time" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" "github.com/rs/zerolog/log" ) type RegisterRequest struct { Email string `json:"email" binding:"required,email"` Password string `json:"password" binding:"required,min=8"` Role string `json:"role" binding:"required,oneof=admin editor contributor"` } type LoginRequest struct { Email string `json:"email" binding:"required,email"` Password string `json:"password" binding:"required"` } type AuthResponse struct { Token string `json:"token"` } func (h *Handler) Register(c *gin.Context) { var req RegisterRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } user, err := h.service.CreateUser(c.Request.Context(), req.Email, req.Password, req.Role) if err != nil { log.Error().Err(err).Msg("Failed to create user") c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user"}) return } // Get user roles roles, err := h.service.GetUserRoles(c.Request.Context(), user.ID) if err != nil { log.Error().Err(err).Msg("Failed to get user roles") c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get user roles"}) return } // Extract role names for JWT roleNames := make([]string, len(roles)) for i, r := range roles { roleNames[i] = r.Name } // Generate JWT token token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "sub": user.ID, "roles": roleNames, "exp": time.Now().Add(24 * time.Hour).Unix(), }) tokenString, err := token.SignedString([]byte(h.cfg.JWT.Secret)) if err != nil { log.Error().Err(err).Msg("Failed to generate token") c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"}) return } c.JSON(http.StatusCreated, AuthResponse{Token: tokenString}) } func (h *Handler) Login(c *gin.Context) { var req LoginRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } user, err := h.service.GetUserByEmail(c.Request.Context(), req.Email) if err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid credentials"}) return } if !h.service.ValidatePassword(c.Request.Context(), user, req.Password) { c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid credentials"}) return } // Get user roles roles, err := h.service.GetUserRoles(c.Request.Context(), user.ID) if err != nil { log.Error().Err(err).Msg("Failed to get user roles") c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get user roles"}) return } // Extract role names for JWT roleNames := make([]string, len(roles)) for i, r := range roles { roleNames[i] = r.Name } // Generate JWT token token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "sub": user.ID, "roles": roleNames, "exp": time.Now().Add(24 * time.Hour).Unix(), }) tokenString, err := token.SignedString([]byte(h.cfg.JWT.Secret)) if err != nil { log.Error().Err(err).Msg("Failed to generate token") c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"}) return } c.JSON(http.StatusOK, AuthResponse{Token: tokenString}) }