// internal/controllers/user_controller.go package controllers import ( "lost-and-found/internal/models" "lost-and-found/internal/services" "lost-and-found/internal/utils" "net/http" "strconv" "github.com/gin-gonic/gin" "gorm.io/gorm" ) type UserController struct { userService *services.UserService } func NewUserController(db *gorm.DB) *UserController { return &UserController{ userService: services.NewUserService(db), } } // GetProfile gets user profile // GET /api/user/profile func (c *UserController) GetProfile(ctx *gin.Context) { userObj, _ := ctx.Get("user") user := userObj.(*models.User) profile, err := c.userService.GetProfile(user.ID) if err != nil { utils.ErrorResponse(ctx, http.StatusNotFound, "Profile not found", err.Error()) return } utils.SuccessResponse(ctx, http.StatusOK, "Profile retrieved", profile.ToResponse()) } // UpdateProfile updates user profile // PUT /api/user/profile func (c *UserController) UpdateProfile(ctx *gin.Context) { userObj, _ := ctx.Get("user") user := userObj.(*models.User) var req services.UpdateProfileRequest if err := ctx.ShouldBindJSON(&req); err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid request data", err.Error()) return } ipAddress := ctx.ClientIP() userAgent := ctx.Request.UserAgent() updatedUser, err := c.userService.UpdateProfile(user.ID, req, ipAddress, userAgent) if err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Update failed", err.Error()) return } utils.SuccessResponse(ctx, http.StatusOK, "Profile updated", updatedUser.ToResponse()) } // ChangePassword changes user password // POST /api/user/change-password func (c *UserController) ChangePassword(ctx *gin.Context) { userObj, _ := ctx.Get("user") user := userObj.(*models.User) var req services.ChangePasswordRequest if err := ctx.ShouldBindJSON(&req); err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid request data", err.Error()) return } ipAddress := ctx.ClientIP() userAgent := ctx.Request.UserAgent() if err := c.userService.ChangePassword(user.ID, req, ipAddress, userAgent); err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Password change failed", err.Error()) return } utils.SuccessResponse(ctx, http.StatusOK, "Password changed successfully", nil) } // GetStats gets user statistics // GET /api/user/stats func (c *UserController) GetStats(ctx *gin.Context) { userObj, _ := ctx.Get("user") user := userObj.(*models.User) stats, err := c.userService.GetUserStats(user.ID) if err != nil { utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to get stats", err.Error()) return } utils.SuccessResponse(ctx, http.StatusOK, "Stats retrieved", stats) } // GetAllUsers gets all users (admin only) // GET /api/admin/users func (c *UserController) GetAllUsers(ctx *gin.Context) { page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1")) limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10")) users, total, err := c.userService.GetAllUsers(page, limit) if err != nil { utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to get users", err.Error()) return } var responses []models.UserResponse for _, user := range users { responses = append(responses, user.ToResponse()) } utils.SendPaginatedResponse(ctx, http.StatusOK, "Users retrieved", responses, total, page, limit) } // GetUserByID gets user by ID (admin only) // GET /api/admin/users/:id func (c *UserController) GetUserByID(ctx *gin.Context) { id, err := strconv.ParseUint(ctx.Param("id"), 10, 32) if err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid user ID", err.Error()) return } user, err := c.userService.GetUserByID(uint(id)) if err != nil { utils.ErrorResponse(ctx, http.StatusNotFound, "User not found", err.Error()) return } utils.SuccessResponse(ctx, http.StatusOK, "User retrieved", user.ToResponse()) } // UpdateUserRole updates user role (admin only) // PATCH /api/admin/users/:id/role func (c *UserController) UpdateUserRole(ctx *gin.Context) { adminObj, _ := ctx.Get("user") admin := adminObj.(*models.User) userID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) if err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid user ID", err.Error()) return } var req struct { RoleID uint `json:"role_id" binding:"required"` } if err := ctx.ShouldBindJSON(&req); err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid request data", err.Error()) return } ipAddress := ctx.ClientIP() userAgent := ctx.Request.UserAgent() if err := c.userService.UpdateUserRole(admin.ID, uint(userID), req.RoleID, ipAddress, userAgent); err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to update role", err.Error()) return } utils.SuccessResponse(ctx, http.StatusOK, "User role updated", nil) } // BlockUser blocks a user (admin only) // POST /api/admin/users/:id/block func (c *UserController) BlockUser(ctx *gin.Context) { adminObj, _ := ctx.Get("user") admin := adminObj.(*models.User) userID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) if err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid user ID", err.Error()) return } ipAddress := ctx.ClientIP() userAgent := ctx.Request.UserAgent() if err := c.userService.BlockUser(admin.ID, uint(userID), ipAddress, userAgent); err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to block user", err.Error()) return } utils.SuccessResponse(ctx, http.StatusOK, "User blocked", nil) } // UnblockUser unblocks a user (admin only) // POST /api/admin/users/:id/unblock func (c *UserController) UnblockUser(ctx *gin.Context) { adminObj, _ := ctx.Get("user") admin := adminObj.(*models.User) userID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) if err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid user ID", err.Error()) return } ipAddress := ctx.ClientIP() userAgent := ctx.Request.UserAgent() if err := c.userService.UnblockUser(admin.ID, uint(userID), ipAddress, userAgent); err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to unblock user", err.Error()) return } utils.SuccessResponse(ctx, http.StatusOK, "User unblocked", nil) } // DeleteUser deletes a user (admin only) // DELETE /api/admin/users/:id func (c *UserController) DeleteUser(ctx *gin.Context) { adminObj, _ := ctx.Get("user") admin := adminObj.(*models.User) userID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) if err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid user ID", err.Error()) return } ipAddress := ctx.ClientIP() userAgent := ctx.Request.UserAgent() if err := c.userService.DeleteUser(admin.ID, uint(userID), ipAddress, userAgent); err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to delete user", err.Error()) return } utils.SuccessResponse(ctx, http.StatusOK, "User deleted", nil) }