8c1e593686
- Introduced a new customer management domain, including entities, services, handlers, and forms for customer operations. - Added JWT-based user authorization settings in the configuration file for both user and customer management. - Updated API endpoints to reflect the new structure, including changes to health check and user management routes. - Enhanced Swagger documentation to include new customer-related endpoints and authorization details. - Refactored the Makefile to include a target for generating API documentation. - Removed obsolete documentation files to streamline the project structure.
698 lines
22 KiB
Go
698 lines
22 KiB
Go
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("/admin/v1")
|
|
|
|
// Public routes (no authentication required)
|
|
authorizationGP := v1.Group("")
|
|
authorizationGP.POST("/login", h.Login)
|
|
authorizationGP.POST("/refresh-token", h.RefreshToken)
|
|
authorizationGP.POST("/reset-password", h.ResetPassword)
|
|
|
|
// Protected routes (require authentication)
|
|
profileGP := v1.Group("")
|
|
profileGP.Use(h.AuthMiddleware())
|
|
profileGP.GET("/profile", h.GetProfile)
|
|
profileGP.PUT("/profile", h.UpdateProfile)
|
|
profileGP.PUT("/change-password", h.ChangePassword)
|
|
profileGP.DELETE("/logout", h.Logout)
|
|
|
|
// Admin routes (require admin role)
|
|
adminGroup := v1.Group("/users")
|
|
adminGroup.Use(h.AuthMiddleware(), 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 username and password
|
|
// @Tags Authorization
|
|
// @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 /admin/v1/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 Authorization
|
|
// @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 /admin/v1/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 Authorization
|
|
// @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 /admin/v1/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 /admin/v1/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 /admin/v1/profile [put]
|
|
func (h *Handler) UpdateProfile(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")
|
|
}
|
|
|
|
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 /admin/v1/change-password [put]
|
|
func (h *Handler) ChangePassword(c echo.Context) error {
|
|
userID, err := GetUserIDFromContext(c)
|
|
if err != nil {
|
|
return response.Unauthorized(c, "User not authenticated")
|
|
}
|
|
|
|
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 /admin/v1/logout [delete]
|
|
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 /admin/v1/users [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 /admin/v1/users [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 /admin/v1/users/{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 /admin/v1/users/{id} [put]
|
|
func (h *Handler) UpdateUser(c echo.Context) error {
|
|
// Extract user ID from JWT token context
|
|
currentUserID, err := GetUserIDFromContext(c)
|
|
if err != nil {
|
|
return response.Unauthorized(c, "User not authenticated")
|
|
}
|
|
|
|
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 /admin/v1/users/{id} [delete]
|
|
func (h *Handler) DeleteUser(c echo.Context) error {
|
|
// Extract user ID from JWT token context
|
|
currentUserID, err := GetUserIDFromContext(c)
|
|
if err != nil {
|
|
return response.Unauthorized(c, "User not authenticated")
|
|
}
|
|
|
|
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 /admin/v1/users/{id}/status [put]
|
|
func (h *Handler) UpdateUserStatus(c echo.Context) error {
|
|
currentUserID, err := GetUserIDFromContext(c)
|
|
if err != nil {
|
|
return response.Unauthorized(c, "User not authenticated")
|
|
}
|
|
|
|
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 /admin/v1/users/{id}/role [put]
|
|
func (h *Handler) UpdateUserRole(c echo.Context) error {
|
|
// Extract user ID from JWT token context
|
|
currentUserID, err := GetUserIDFromContext(c)
|
|
if err != nil {
|
|
return response.Unauthorized(c, "User not authenticated")
|
|
}
|
|
|
|
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{data=map[string]interface{}} "Users with pagination metadata"
|
|
// @Failure 400 {object} response.APIResponse
|
|
// @Failure 401 {object} response.APIResponse
|
|
// @Failure 403 {object} response.APIResponse
|
|
// @Failure 500 {object} response.APIResponse
|
|
// @Router /admin/v1/users/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{data=map[string]interface{}} "Users with pagination metadata"
|
|
// @Failure 400 {object} response.APIResponse
|
|
// @Failure 401 {object} response.APIResponse
|
|
// @Failure 403 {object} response.APIResponse
|
|
// @Failure 500 {object} response.APIResponse
|
|
// @Router /admin/v1/users/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
|