veza/veza-backend-api/internal/handlers/role_handler.go
senke dda16108e7 [BE-API-008] be-api: Implement user search endpoint
- Created SearchUsers method in UserService with pagination support
- SearchUsers searches by username, email, first_name, and last_name using ILIKE
- Added SearchUsers handler in ProfileHandler with query params (q, page, limit)
- Added GET /users/search route in setupUserRoutes
- Returns paginated results with total count
- Password hashes are excluded from results

Phase: PHASE-2
Priority: P1
Progress: 17/267 (6.4%)
2025-12-23 10:42:26 +01:00

209 lines
6.2 KiB
Go

package handlers
import (
"net/http"
"time"
apperrors "veza-backend-api/internal/errors"
"veza-backend-api/internal/models"
"veza-backend-api/internal/services"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"go.uber.org/zap"
)
// RoleHandler gère les endpoints de gestion des rôles
type RoleHandler struct {
roleService *services.RoleService
commonHandler *CommonHandler
}
// NewRoleHandler crée un nouveau RoleHandler
func NewRoleHandler(roleService *services.RoleService, logger *zap.Logger) *RoleHandler {
return &RoleHandler{
roleService: roleService,
commonHandler: NewCommonHandler(logger),
}
}
// GetRoles récupère tous les rôles
// BE-API-007: Implement roles management endpoints
func (h *RoleHandler) GetRoles(c *gin.Context) {
roles, err := h.roleService.GetRoles(c.Request.Context())
if err != nil {
RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to get roles", err))
return
}
RespondSuccess(c, http.StatusOK, roles)
}
// GetRole récupère un rôle par ID
// BE-API-007: Implement roles management endpoints
func (h *RoleHandler) GetRole(c *gin.Context) {
roleIDStr := c.Param("id")
roleID, err := uuid.Parse(roleIDStr)
if err != nil {
RespondWithAppError(c, apperrors.NewValidationError("invalid role id"))
return
}
role, err := h.roleService.GetRole(c.Request.Context(), roleID)
if err != nil {
if err.Error() == "role not found" {
RespondWithAppError(c, apperrors.NewNotFoundError("role"))
} else {
RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to get role", err))
}
return
}
RespondSuccess(c, http.StatusOK, role)
}
// CreateRole crée un nouveau rôle
func (h *RoleHandler) CreateRole(c *gin.Context) {
var role models.Role
if appErr := h.commonHandler.BindAndValidateJSON(c, &role); appErr != nil {
RespondWithAppError(c, appErr)
return
}
if err := h.roleService.CreateRole(c.Request.Context(), &role); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, gin.H{"role": role})
}
// UpdateRole met à jour un rôle
func (h *RoleHandler) UpdateRole(c *gin.Context) {
roleIDStr := c.Param("id")
roleID, err := uuid.Parse(roleIDStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid role id"})
return
}
var updates models.Role
if appErr := h.commonHandler.BindAndValidateJSON(c, &updates); appErr != nil {
RespondWithAppError(c, appErr)
return
}
if err := h.roleService.UpdateRole(c.Request.Context(), roleID, &updates); err != nil {
if err.Error() == "role not found or is system role" {
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
} else {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
}
return
}
c.JSON(http.StatusOK, gin.H{"message": "role updated"})
}
// DeleteRole supprime un rôle
func (h *RoleHandler) DeleteRole(c *gin.Context) {
roleIDStr := c.Param("id")
roleID, err := uuid.Parse(roleIDStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid role id"})
return
}
if err := h.roleService.DeleteRole(c.Request.Context(), roleID); err != nil {
if err.Error() == "role not found" || err.Error() == "cannot delete system role" {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
} else {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
}
return
}
c.JSON(http.StatusOK, gin.H{"message": "role deleted"})
}
// AssignRole assigne un rôle à un utilisateur
// BE-API-007: Implement roles management endpoints
// Supports both :id and :userId parameters for flexibility
func (h *RoleHandler) AssignRole(c *gin.Context) {
// Try :userId first (from /users/:userId/roles), fallback to :id
userIDStr := c.Param("userId")
if userIDStr == "" {
userIDStr = c.Param("id")
}
userID, err := uuid.Parse(userIDStr)
if err != nil {
RespondWithAppError(c, apperrors.NewValidationError("invalid user id"))
return
}
var req struct {
RoleID uuid.UUID `json:"role_id" binding:"required"`
ExpiresAt *time.Time `json:"expires_at"`
}
if appErr := h.commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
RespondWithAppError(c, appErr)
return
}
// Récupérer l'ID de l'utilisateur qui assigne depuis le contexte
assignedBy, ok := GetUserIDUUID(c)
if !ok {
return // Erreur déjà envoyée par GetUserIDUUID
}
if err := h.roleService.AssignRoleToUser(c.Request.Context(), userID, req.RoleID, assignedBy, req.ExpiresAt); err != nil {
RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to assign role", err))
return
}
RespondSuccess(c, http.StatusOK, gin.H{"message": "role assigned"})
}
// RevokeRole révoque un rôle d'un utilisateur
// BE-API-007: Implement roles management endpoints
// Supports both :id and :userId parameters for flexibility
func (h *RoleHandler) RevokeRole(c *gin.Context) {
// Try :userId first (from /users/:userId/roles/:roleId), fallback to :id
userIDStr := c.Param("userId")
if userIDStr == "" {
userIDStr = c.Param("id")
}
userID, err := uuid.Parse(userIDStr)
if err != nil {
RespondWithAppError(c, apperrors.NewValidationError("invalid user id"))
return
}
roleIDStr := c.Param("roleId")
roleID, err := uuid.Parse(roleIDStr)
if err != nil {
RespondWithAppError(c, apperrors.NewValidationError("invalid role id"))
return
}
if err := h.roleService.RevokeRoleFromUser(c.Request.Context(), userID, roleID); err != nil {
if err.Error() == "role assignment not found" {
RespondWithAppError(c, apperrors.NewNotFoundError("role assignment"))
} else {
RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to revoke role", err))
}
return
}
RespondSuccess(c, http.StatusOK, gin.H{"message": "role revoked"})
}
// GetUserRoles récupère tous les rôles d'un utilisateur
func (h *RoleHandler) GetUserRoles(c *gin.Context) {
userIDStr := c.Param("id")
userID, err := uuid.Parse(userIDStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid user id"})
return
}
roles, err := h.roleService.GetUserRoles(c.Request.Context(), userID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"roles": roles})
}