package user import ( "fmt" "time" "ResendIt/internal/api/middleware" "github.com/gin-gonic/gin" ) type Handler struct { service *Service } func NewHandler(service *Service) *Handler { return &Handler{service: service} } func (h *Handler) Register(c *gin.Context) { log := middleware.StructuredLog(c).With(). Str("event", "user_register"). Logger() var req struct { Username string `json:"username"` Password string `json:"password"` Role string `json:"role"` } if err := c.ShouldBindJSON(&req); err != nil { log.Warn(). Str("reason", "invalid_request"). Msg("Registration failed") c.JSON(400, gin.H{"error": "invalid request"}) return } user, err := h.service.CreateUser(req.Username, req.Password, req.Role) if err != nil { log.Error(). Err(err). Str("username", req.Username). Msg("Registration failed") c.JSON(500, gin.H{"error": err.Error()}) return } log.Info(). Str("user_id", fmt.Sprint(user.ID)). Str("username", user.Username). Str("role", user.Role). Msg("User registered successfully") c.JSON(201, gin.H{ "id": user.ID, "username": user.Username, "role": user.Role, }) } func (h *Handler) ChangePassword(c *gin.Context) { log := middleware.StructuredLog(c).With(). Str("event", "password_change"). Logger() var req struct { OldPassword string `json:"old_password"` NewPassword string `json:"new_password"` } userID, exists := c.Get("user_id") if !exists { c.JSON(401, gin.H{"error": "unauthorized"}) return } if err := c.ShouldBindJSON(&req); err != nil { log.Warn(). Str("reason", "invalid_request"). Msg("Password change failed") c.JSON(400, gin.H{"error": "invalid request"}) return } uid := fmt.Sprint(userID) start := time.Now() err := h.service.ChangePassword(uid, req.OldPassword, req.NewPassword) latency := time.Since(start) if err != nil { log.Warn(). Str("user_id", uid). Str("reason", err.Error()). Dur("latency_ms", latency). Msg("Password change failed") c.JSON(500, gin.H{"error": err.Error()}) return } log.Info(). Str("user_id", uid). Dur("latency_ms", latency). Msg("Password changed successfully") c.JSON(200, gin.H{"message": "password changed successfully"}) } func ForcePasswordChangeMiddleware(userService *Service) gin.HandlerFunc { return func(c *gin.Context) { log := middleware.StructuredLog(c).With(). Str("event", "force_password_check"). Logger() userID, exists := c.Get("user_id") if !exists { c.Next() return } uid := fmt.Sprint(userID) user, err := userService.FindByID(uid) if err != nil { log.Error(). Err(err). Str("user_id", uid). Msg("Failed to find user for password check") c.AbortWithStatus(500) return } if user.ForceChangePassword && c.Request.URL.Path != "/change-password" { log.Warn(). Str("user_id", uid). Str("path", c.Request.URL.Path). Msg("Access denied - force password change required") c.Redirect(302, "/change-password") c.Abort() return } c.Next() } }