Enhance cursor rules and add user management functionality
- Updated cursor rules to emphasize the importance of dependency injection and logging practices. - Introduced a new user management domain, including entities, services, handlers, and validation. - Implemented user authentication features such as login, registration, and role-based access control. - Added Redis integration for token management and caching. - Enhanced API documentation with Swagger for user-related endpoints. - Updated configuration to support new JWT settings and Redis connection parameters.
This commit is contained in:
@@ -0,0 +1,687 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"tm/pkg/authorization"
|
||||
"tm/pkg/logger"
|
||||
"tm/pkg/response"
|
||||
|
||||
"github.com/asaskevich/govalidator"
|
||||
"github.com/google/uuid"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// Handler handles HTTP requests for user operations
|
||||
type Handler struct {
|
||||
service Service
|
||||
logger logger.Logger
|
||||
validator ValidationService
|
||||
authService authorization.AuthorizationService
|
||||
}
|
||||
|
||||
// NewUserHandler creates a new user handler
|
||||
func NewUserHandler(service Service, logger logger.Logger, validator ValidationService, authService authorization.AuthorizationService) *Handler {
|
||||
return &Handler{
|
||||
service: service,
|
||||
logger: logger,
|
||||
validator: validator,
|
||||
authService: authService,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterRoutes registers user routes
|
||||
func (h *Handler) RegisterRoutes(e *echo.Echo) {
|
||||
v1 := e.Group("/api/v1")
|
||||
|
||||
userGroup := v1.Group("/users")
|
||||
{
|
||||
// Public routes
|
||||
userGroup.POST("/login", h.Login)
|
||||
userGroup.POST("/refresh-token", h.RefreshToken)
|
||||
userGroup.POST("/reset-password", h.ResetPassword)
|
||||
|
||||
// Protected routes (require authentication)
|
||||
authGroup := userGroup.Group("")
|
||||
// authGroup.Use(h.AuthMiddleware())
|
||||
{
|
||||
authGroup.GET("/profile", h.GetProfile)
|
||||
authGroup.PUT("/profile", h.UpdateProfile)
|
||||
authGroup.PUT("/change-password", h.ChangePassword)
|
||||
authGroup.POST("/logout", h.Logout)
|
||||
|
||||
// Admin routes
|
||||
adminGroup := authGroup.Group("/admin")
|
||||
// adminGroup.Use(h.AdminMiddleware())
|
||||
{
|
||||
adminGroup.POST("", h.CreateUser)
|
||||
adminGroup.GET("", h.ListUsers)
|
||||
adminGroup.GET("/:id", h.GetUserByID)
|
||||
adminGroup.PUT("/:id", h.UpdateUser)
|
||||
adminGroup.DELETE("/:id", h.DeleteUser)
|
||||
adminGroup.PUT("/:id/status", h.UpdateUserStatus)
|
||||
adminGroup.PUT("/:id/role", h.UpdateUserRole)
|
||||
adminGroup.GET("/company/:company_id", h.GetUsersByCompanyID)
|
||||
adminGroup.GET("/role/:role", h.GetUsersByRole)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Login handles user login
|
||||
// @Summary Login user
|
||||
// @Description Authenticate user with email/username and password
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param login body LoginForm true "Login credentials"
|
||||
// @Success 200 {object} response.APIResponse{data=AuthResponse}
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/login [post]
|
||||
func (h *Handler) Login(c echo.Context) error {
|
||||
form, err := response.Parse[LoginForm](c)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, "Invalid request format", "")
|
||||
}
|
||||
|
||||
// Call service
|
||||
authResponse, err := h.service.Login(c.Request().Context(), form)
|
||||
if err != nil {
|
||||
return response.Unauthorized(c, err.Error())
|
||||
}
|
||||
|
||||
return response.Success(c, authResponse, "Login successful")
|
||||
}
|
||||
|
||||
// RefreshToken handles token refresh
|
||||
// @Summary Refresh access token
|
||||
// @Description Refresh access token using refresh token
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param refresh body RefreshTokenForm true "Refresh token"
|
||||
// @Success 200 {object} response.APIResponse{data=AuthResponse}
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/refresh-token [post]
|
||||
func (h *Handler) RefreshToken(c echo.Context) error {
|
||||
form, err := response.Parse[RefreshTokenForm](c)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, "Invalid request format", "")
|
||||
}
|
||||
|
||||
authResponse, err := h.service.RefreshToken(c.Request().Context(), form.RefreshToken)
|
||||
if err != nil {
|
||||
return response.Unauthorized(c, err.Error())
|
||||
}
|
||||
|
||||
return response.Success(c, authResponse, "Token refreshed successfully")
|
||||
}
|
||||
|
||||
// ResetPassword handles password reset request
|
||||
// @Summary Reset password
|
||||
// @Description Send password reset email to user
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param reset body ResetPasswordForm true "Password reset request"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/reset-password [post]
|
||||
func (h *Handler) ResetPassword(c echo.Context) error {
|
||||
form, err := response.Parse[ResetPasswordForm](c)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, "Invalid request format", "")
|
||||
}
|
||||
|
||||
err = h.service.ResetPassword(c.Request().Context(), form)
|
||||
if err != nil {
|
||||
return response.InternalServerError(c, "Failed to process password reset")
|
||||
}
|
||||
|
||||
return response.Success(c, map[string]interface{}{
|
||||
"message": "Password reset email sent successfully",
|
||||
}, "Password reset initiated")
|
||||
}
|
||||
|
||||
// GetProfile gets current user profile
|
||||
// @Summary Get user profile
|
||||
// @Description Get current user profile information
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Success 200 {object} response.APIResponse{data=UserResponse}
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 404 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/profile [get]
|
||||
func (h *Handler) GetProfile(c echo.Context) error {
|
||||
// Extract user ID from JWT token context
|
||||
userID, err := GetUserIDFromContext(c)
|
||||
if err != nil {
|
||||
return response.Unauthorized(c, "User not authenticated")
|
||||
}
|
||||
|
||||
user, err := h.service.GetProfile(c.Request().Context(), userID)
|
||||
if err != nil {
|
||||
return response.NotFound(c, "User not found")
|
||||
}
|
||||
|
||||
return response.Success(c, user.ToResponse(), "Profile retrieved successfully")
|
||||
}
|
||||
|
||||
// UpdateProfile updates current user profile
|
||||
// @Summary Update user profile
|
||||
// @Description Update current user profile information
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param profile body UpdateUserForm true "Profile update data"
|
||||
// @Success 200 {object} response.APIResponse{data=UserResponse}
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/profile [put]
|
||||
func (h *Handler) UpdateProfile(c echo.Context) error {
|
||||
// TODO: Extract user ID from JWT token
|
||||
userID := uuid.New() // Placeholder - should be extracted from JWT
|
||||
|
||||
form, err := response.Parse[UpdateUserForm](c)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, "Invalid request format", "")
|
||||
}
|
||||
|
||||
user, err := h.service.UpdateUser(c.Request().Context(), userID, form, &userID)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, err.Error(), "")
|
||||
}
|
||||
|
||||
return response.Success(c, user.ToResponse(), "Profile updated successfully")
|
||||
}
|
||||
|
||||
// ChangePassword changes current user password
|
||||
// @Summary Change password
|
||||
// @Description Change current user password
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param password body ChangePasswordForm true "Password change data"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/change-password [put]
|
||||
func (h *Handler) ChangePassword(c echo.Context) error {
|
||||
// TODO: Extract user ID from JWT token
|
||||
userID := uuid.New() // Placeholder - should be extracted from JWT
|
||||
|
||||
form, err := response.Parse[ChangePasswordForm](c)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, "Invalid request format", "")
|
||||
}
|
||||
|
||||
err = h.service.ChangePassword(c.Request().Context(), userID, form)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, err.Error(), "")
|
||||
}
|
||||
|
||||
return response.Success(c, map[string]interface{}{
|
||||
"message": "Password changed successfully",
|
||||
}, "Password changed successfully")
|
||||
}
|
||||
|
||||
// Logout handles user logout
|
||||
// @Summary Logout user
|
||||
// @Description Logout current user and invalidate tokens
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/logout [post]
|
||||
func (h *Handler) Logout(c echo.Context) error {
|
||||
// Extract user ID and access token from context
|
||||
userID, err := GetUserIDFromContext(c)
|
||||
if err != nil {
|
||||
return response.Unauthorized(c, "User not authenticated")
|
||||
}
|
||||
|
||||
accessToken, err := GetAccessTokenFromContext(c)
|
||||
if err != nil {
|
||||
return response.Unauthorized(c, "Access token not found")
|
||||
}
|
||||
|
||||
err = h.service.Logout(c.Request().Context(), userID, accessToken)
|
||||
if err != nil {
|
||||
return response.InternalServerError(c, "Failed to logout")
|
||||
}
|
||||
|
||||
return response.Success(c, map[string]interface{}{
|
||||
"message": "Logged out successfully",
|
||||
}, "Logged out successfully")
|
||||
}
|
||||
|
||||
// CreateUser creates a new user (admin only)
|
||||
// @Summary Create user
|
||||
// @Description Create a new user (admin only)
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param user body CreateUserForm true "User creation data"
|
||||
// @Success 201 {object} response.APIResponse{data=UserResponse}
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 403 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/admin [post]
|
||||
func (h *Handler) CreateUser(c echo.Context) error {
|
||||
// Get current user ID from JWT token
|
||||
currentUserID, err := GetUserIDFromContext(c)
|
||||
if err != nil {
|
||||
return response.Unauthorized(c, "User not authenticated")
|
||||
}
|
||||
|
||||
var form CreateUserForm
|
||||
if err := c.Bind(&form); err != nil {
|
||||
return response.BadRequest(c, "Invalid request format", "")
|
||||
}
|
||||
|
||||
// Validate form
|
||||
if _, err := govalidator.ValidateStruct(form); err != nil {
|
||||
return response.ValidationError(c, err.Error(), "")
|
||||
}
|
||||
|
||||
// Call service
|
||||
user, err := h.service.CreateUser(c.Request().Context(), &form, ¤tUserID)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, err.Error(), "")
|
||||
}
|
||||
|
||||
return response.Created(c, user.ToResponse(), "User created successfully")
|
||||
}
|
||||
|
||||
// ListUsers lists users with search and filters (admin only)
|
||||
// @Summary List users
|
||||
// @Description List users with search and filters (admin only)
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param search query string false "Search term"
|
||||
// @Param status query string false "User status filter"
|
||||
// @Param role query string false "User role filter"
|
||||
// @Param company_id query string false "Company ID filter"
|
||||
// @Param limit query int false "Limit results"
|
||||
// @Param offset query int false "Offset results"
|
||||
// @Param sort_by query string false "Sort field"
|
||||
// @Param sort_order query string false "Sort order"
|
||||
// @Success 200 {object} response.APIResponse{data=UserListResponse}
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 403 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/admin [get]
|
||||
func (h *Handler) ListUsers(c echo.Context) error {
|
||||
var form ListUsersForm
|
||||
if err := c.Bind(&form); err != nil {
|
||||
return response.BadRequest(c, "Invalid request format", "")
|
||||
}
|
||||
|
||||
// Validate form
|
||||
if _, err := govalidator.ValidateStruct(form); err != nil {
|
||||
return response.ValidationError(c, err.Error(), "")
|
||||
}
|
||||
|
||||
// Call service
|
||||
users, err := h.service.ListUsers(c.Request().Context(), &form)
|
||||
if err != nil {
|
||||
return response.InternalServerError(c, "Failed to list users")
|
||||
}
|
||||
|
||||
return response.Success(c, users, "Users retrieved successfully")
|
||||
}
|
||||
|
||||
// GetUserByID gets a user by ID (admin only)
|
||||
// @Summary Get user by ID
|
||||
// @Description Get user details by ID (admin only)
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "User ID"
|
||||
// @Success 200 {object} response.APIResponse{data=UserResponse}
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 403 {object} response.APIResponse
|
||||
// @Failure 404 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/admin/{id} [get]
|
||||
func (h *Handler) GetUserByID(c echo.Context) error {
|
||||
idStr := c.Param("id")
|
||||
userID, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, "Invalid user ID", "")
|
||||
}
|
||||
|
||||
user, err := h.service.GetUserByID(c.Request().Context(), userID)
|
||||
if err != nil {
|
||||
return response.NotFound(c, "User not found")
|
||||
}
|
||||
|
||||
return response.Success(c, user.ToResponse(), "User retrieved successfully")
|
||||
}
|
||||
|
||||
// UpdateUser updates a user (admin only)
|
||||
// @Summary Update user
|
||||
// @Description Update user information (admin only)
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "User ID"
|
||||
// @Param user body UpdateUserForm true "User update data"
|
||||
// @Success 200 {object} response.APIResponse{data=UserResponse}
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 403 {object} response.APIResponse
|
||||
// @Failure 404 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/admin/{id} [put]
|
||||
func (h *Handler) UpdateUser(c echo.Context) error {
|
||||
// TODO: Get current user ID from JWT token
|
||||
currentUserID := uuid.New() // Placeholder
|
||||
|
||||
idStr := c.Param("id")
|
||||
userID, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, "Invalid user ID", "")
|
||||
}
|
||||
|
||||
var form UpdateUserForm
|
||||
if err := c.Bind(&form); err != nil {
|
||||
return response.BadRequest(c, "Invalid request format", "")
|
||||
}
|
||||
|
||||
// Validate form
|
||||
if _, err := govalidator.ValidateStruct(form); err != nil {
|
||||
return response.ValidationError(c, err.Error(), "")
|
||||
}
|
||||
|
||||
// Call service
|
||||
user, err := h.service.UpdateUser(c.Request().Context(), userID, &form, ¤tUserID)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, err.Error(), "")
|
||||
}
|
||||
|
||||
return response.Success(c, user.ToResponse(), "User updated successfully")
|
||||
}
|
||||
|
||||
// DeleteUser deletes a user (admin only)
|
||||
// @Summary Delete user
|
||||
// @Description Delete a user (admin only)
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "User ID"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 403 {object} response.APIResponse
|
||||
// @Failure 404 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/admin/{id} [delete]
|
||||
func (h *Handler) DeleteUser(c echo.Context) error {
|
||||
// TODO: Get current user ID from JWT token
|
||||
currentUserID := uuid.New() // Placeholder
|
||||
|
||||
idStr := c.Param("id")
|
||||
userID, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, "Invalid user ID", "")
|
||||
}
|
||||
|
||||
err = h.service.DeleteUser(c.Request().Context(), userID, ¤tUserID)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, err.Error(), "")
|
||||
}
|
||||
|
||||
return response.Success(c, map[string]interface{}{
|
||||
"message": "User deleted successfully",
|
||||
}, "User deleted successfully")
|
||||
}
|
||||
|
||||
// UpdateUserStatus updates user status (admin only)
|
||||
// @Summary Update user status
|
||||
// @Description Update user account status (admin only)
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "User ID"
|
||||
// @Param status body UpdateUserStatusForm true "Status update data"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 403 {object} response.APIResponse
|
||||
// @Failure 404 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/admin/{id}/status [put]
|
||||
func (h *Handler) UpdateUserStatus(c echo.Context) error {
|
||||
// TODO: Get current user ID from JWT token
|
||||
currentUserID := uuid.New() // Placeholder
|
||||
|
||||
idStr := c.Param("id")
|
||||
userID, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, "Invalid user ID", "")
|
||||
}
|
||||
|
||||
var form UpdateUserStatusForm
|
||||
if err := c.Bind(&form); err != nil {
|
||||
return response.BadRequest(c, "Invalid request format", "")
|
||||
}
|
||||
|
||||
// Validate form
|
||||
if _, err := govalidator.ValidateStruct(form); err != nil {
|
||||
return response.ValidationError(c, err.Error(), "")
|
||||
}
|
||||
|
||||
// Call service
|
||||
err = h.service.UpdateUserStatus(c.Request().Context(), userID, &form, ¤tUserID)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, err.Error(), "")
|
||||
}
|
||||
|
||||
return response.Success(c, map[string]interface{}{
|
||||
"message": "User status updated successfully",
|
||||
}, "User status updated successfully")
|
||||
}
|
||||
|
||||
// UpdateUserRole updates user role (admin only)
|
||||
// @Summary Update user role
|
||||
// @Description Update user role (admin only)
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param id path string true "User ID"
|
||||
// @Param role body UpdateUserRoleForm true "Role update data"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 403 {object} response.APIResponse
|
||||
// @Failure 404 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/admin/{id}/role [put]
|
||||
func (h *Handler) UpdateUserRole(c echo.Context) error {
|
||||
// TODO: Get current user ID from JWT token
|
||||
currentUserID := uuid.New() // Placeholder
|
||||
|
||||
idStr := c.Param("id")
|
||||
userID, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, "Invalid user ID", "")
|
||||
}
|
||||
|
||||
var form UpdateUserRoleForm
|
||||
if err := c.Bind(&form); err != nil {
|
||||
return response.BadRequest(c, "Invalid request format", "")
|
||||
}
|
||||
|
||||
// Validate form
|
||||
if _, err := govalidator.ValidateStruct(form); err != nil {
|
||||
return response.ValidationError(c, err.Error(), "")
|
||||
}
|
||||
|
||||
// Call service
|
||||
err = h.service.UpdateUserRole(c.Request().Context(), userID, &form, ¤tUserID)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, err.Error(), "")
|
||||
}
|
||||
|
||||
return response.Success(c, map[string]interface{}{
|
||||
"message": "User role updated successfully",
|
||||
}, "User role updated successfully")
|
||||
}
|
||||
|
||||
// GetUsersByCompanyID gets users by company ID (admin only)
|
||||
// @Summary Get users by company ID
|
||||
// @Description Get users belonging to a specific company (admin only)
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param company_id path string true "Company ID"
|
||||
// @Param limit query int false "Limit results"
|
||||
// @Param offset query int false "Offset results"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 403 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/admin/company/{company_id} [get]
|
||||
func (h *Handler) GetUsersByCompanyID(c echo.Context) error {
|
||||
companyIDStr := c.Param("company_id")
|
||||
companyID, err := uuid.Parse(companyIDStr)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, "Invalid company ID", "")
|
||||
}
|
||||
|
||||
// Get query parameters
|
||||
limitStr := c.QueryParam("limit")
|
||||
if limitStr == "" {
|
||||
limitStr = "20"
|
||||
}
|
||||
offsetStr := c.QueryParam("offset")
|
||||
if offsetStr == "" {
|
||||
offsetStr = "0"
|
||||
}
|
||||
|
||||
limit, err := strconv.Atoi(limitStr)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, "Invalid limit parameter", "")
|
||||
}
|
||||
|
||||
offset, err := strconv.Atoi(offsetStr)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, "Invalid offset parameter", "")
|
||||
}
|
||||
|
||||
// Call service
|
||||
users, total, err := h.service.GetUsersByCompanyID(c.Request().Context(), companyID, limit, offset)
|
||||
if err != nil {
|
||||
return response.InternalServerError(c, "Failed to get users by company")
|
||||
}
|
||||
|
||||
// Convert to responses
|
||||
var userResponses []*UserResponse
|
||||
for _, user := range users {
|
||||
userResponses = append(userResponses, user.ToResponse())
|
||||
}
|
||||
|
||||
return response.SuccessWithMeta(c, map[string]interface{}{
|
||||
"users": userResponses,
|
||||
}, &response.Meta{
|
||||
Total: int(total),
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
}, "Users retrieved successfully")
|
||||
}
|
||||
|
||||
// GetUsersByRole gets users by role (admin only)
|
||||
// @Summary Get users by role
|
||||
// @Description Get users with a specific role (admin only)
|
||||
// @Tags users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security BearerAuth
|
||||
// @Param role path string true "User role"
|
||||
// @Param limit query int false "Limit results"
|
||||
// @Param offset query int false "Offset results"
|
||||
// @Success 200 {object} response.APIResponse
|
||||
// @Failure 400 {object} response.APIResponse
|
||||
// @Failure 401 {object} response.APIResponse
|
||||
// @Failure 403 {object} response.APIResponse
|
||||
// @Failure 500 {object} response.APIResponse
|
||||
// @Router /users/admin/role/{role} [get]
|
||||
func (h *Handler) GetUsersByRole(c echo.Context) error {
|
||||
roleStr := c.Param("role")
|
||||
role := UserRole(roleStr)
|
||||
|
||||
// Validate role
|
||||
if !h.validator.IsValidRole(role) {
|
||||
return response.BadRequest(c, "Invalid role", "")
|
||||
}
|
||||
|
||||
// Get query parameters
|
||||
limitStr := c.QueryParam("limit")
|
||||
if limitStr == "" {
|
||||
limitStr = "20"
|
||||
}
|
||||
offsetStr := c.QueryParam("offset")
|
||||
if offsetStr == "" {
|
||||
offsetStr = "0"
|
||||
}
|
||||
|
||||
limit, err := strconv.Atoi(limitStr)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, "Invalid limit parameter", "")
|
||||
}
|
||||
|
||||
offset, err := strconv.Atoi(offsetStr)
|
||||
if err != nil {
|
||||
return response.BadRequest(c, "Invalid offset parameter", "")
|
||||
}
|
||||
|
||||
// Call service
|
||||
users, err := h.service.GetUsersByRole(c.Request().Context(), role, limit, offset)
|
||||
if err != nil {
|
||||
return response.InternalServerError(c, "Failed to get users by role")
|
||||
}
|
||||
|
||||
// Convert to responses
|
||||
var userResponses []*UserResponse
|
||||
for _, user := range users {
|
||||
userResponses = append(userResponses, user.ToResponse())
|
||||
}
|
||||
|
||||
return response.SuccessWithMeta(c, map[string]interface{}{
|
||||
"users": userResponses,
|
||||
"role": role,
|
||||
}, &response.Meta{
|
||||
Limit: limit,
|
||||
Offset: offset,
|
||||
}, "Users retrieved successfully")
|
||||
}
|
||||
|
||||
// AuthMiddleware and AdminMiddleware are now implemented in middleware.go
|
||||
Reference in New Issue
Block a user