Class UsersController
- Namespace
- KadicAuth.Api.Controllers
- Assembly
- KadicAuth.Api.dll
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class UsersController : ControllerBase
- Inheritance
-
objectControllerBaseUsersController
Constructors
UsersController(IMediator, ILogger<UsersController>, ICurrentUser, IPermissionService, IPermissionRepository, ITenantIdContext, IStringLocalizer<AuthMessages>)
public UsersController(IMediator mediator, ILogger<UsersController> logger, ICurrentUser currentUser, IPermissionService permissionService, IPermissionRepository permissionRepository, ITenantIdContext tenantIdContext, IStringLocalizer<AuthMessages> localizer)
Parameters
mediatorIMediatorloggerILogger<UsersController>currentUserICurrentUserpermissionServiceIPermissionServicepermissionRepositoryIPermissionRepositorytenantIdContextITenantIdContextlocalizerIStringLocalizer<AuthMessages>
Methods
ActivateUser(Guid, CancellationToken)
Activate a user
[HttpPatch("{userId:guid}/activate")]
[EnableRateLimiting("sensitive-write")]
[Authorize(Policy = "AUTH_USERS_ACTIVATE")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(Error), 400)]
[ProducesResponseType(typeof(Error), 404)]
[ProducesResponseType(typeof(Error), 409)]
public Task<ActionResult> ActivateUser(Guid userId, CancellationToken cancellationToken)
Parameters
userIdGuidcancellationTokenCancellationToken
Returns
- Task<ActionResult>
AdminChangePassword(Guid, AdminChangePasswordDto, CancellationToken)
Admin-level password change for a user (bypasses current password requirement)
[HttpPatch("{userId:guid}/admin-change-password")]
[EnableRateLimiting("sensitive-write")]
[Authorize(Policy = "AUTH_USERS_UPDATE")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(Error), 404)]
[ProducesResponseType(typeof(Error), 400)]
public Task<ActionResult> AdminChangePassword(Guid userId, AdminChangePasswordDto request, CancellationToken cancellationToken)
Parameters
userIdGuidrequestAdminChangePasswordDtocancellationTokenCancellationToken
Returns
- Task<ActionResult>
AssignBranches(Guid, AssignBranchesRequest, CancellationToken)
Vincula el usuario como ADMIN a las sucursales indicadas. Si branchIds es null o vacío, se asigna a TODAS las sucursales activas del tenant. El rol ADMIN se resuelve por Code="ADMIN"; si no existe en el tenant, se crea automáticamente y se le asignan TODOS los permisos del sistema.
[HttpPut("{userId:guid}/branches")]
[EnableRateLimiting("sensitive-write")]
[Authorize(Policy = "AUTH_USERS_ASSIGN_BRANCHES")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(Error), 400)]
[ProducesResponseType(typeof(Error), 404)]
public Task<ActionResult> AssignBranches(Guid userId, AssignBranchesRequest request, CancellationToken cancellationToken)
Parameters
userIdGuidrequestAssignBranchesRequestcancellationTokenCancellationToken
Returns
- Task<ActionResult>
ChangePassword(Guid, ChangePasswordDto, CancellationToken)
Change user password
[HttpPost("{userId:guid}/change-password")]
[Authorize(Policy = "AUTH_USERS_CHANGE_PASSWORD")]
[EnableRateLimiting("sensitive-write")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(Error), 400)]
public Task<ActionResult> ChangePassword(Guid userId, ChangePasswordDto request, CancellationToken cancellationToken)
Parameters
userIdGuidrequestChangePasswordDtocancellationTokenCancellationToken
Returns
- Task<ActionResult>
ClearLoginHistory(Guid, CancellationToken)
Delete all login attempt history for a user
[HttpDelete("{userId:guid}/login-attempts")]
[Authorize(Policy = "AUTH_USERS_CLEAR_LOGIN_HISTORY")]
[ProducesResponseType(204)]
[ProducesResponseType(typeof(Error), 404)]
public Task<ActionResult> ClearLoginHistory(Guid userId, CancellationToken cancellationToken = default)
Parameters
userIdGuidcancellationTokenCancellationToken
Returns
- Task<ActionResult>
CreateUser(CreateUserDto, CancellationToken)
Create a new user (with tenant and roles)
[HttpPost]
[EnableRateLimiting("sensitive-write")]
[Authorize(Policy = "AUTH_USERS_CREATE")]
[ProducesResponseType(typeof(Result<Guid>), 201)]
[ProducesResponseType(typeof(Result), 400)]
[ProducesResponseType(typeof(Result), 409)]
public Task<ActionResult> CreateUser(CreateUserDto request, CancellationToken cancellationToken)
Parameters
requestCreateUserDtocancellationTokenCancellationToken
Returns
- Task<ActionResult>
CreateUserWithRoles(CreateUserWithRolesRequest, CancellationToken)
Create user and optionally assign roles in one request.
[HttpPost("with-roles")]
[EnableRateLimiting("sensitive-write")]
[Authorize(Policy = "AUTH_USERS_CREATE")]
[ProducesResponseType(typeof(Result<Guid>), 201)]
[ProducesResponseType(typeof(Result), 400)]
[ProducesResponseType(typeof(Result), 409)]
public Task<ActionResult> CreateUserWithRoles(CreateUserWithRolesRequest request, CancellationToken cancellationToken)
Parameters
requestCreateUserWithRolesRequestcancellationTokenCancellationToken
Returns
- Task<ActionResult>
DeactivateUser(Guid, CancellationToken)
Deactivate a user
[HttpPatch("{userId:guid}/deactivate")]
[EnableRateLimiting("sensitive-write")]
[Authorize(Policy = "AUTH_USERS_DEACTIVATE")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(Error), 400)]
[ProducesResponseType(typeof(Error), 404)]
[ProducesResponseType(typeof(Error), 409)]
public Task<ActionResult> DeactivateUser(Guid userId, CancellationToken cancellationToken)
Parameters
userIdGuidcancellationTokenCancellationToken
Returns
- Task<ActionResult>
ForcePasswordReset(Guid, CancellationToken)
Force a user to change their password on next login
[HttpPost("{userId:guid}/force-password-reset")]
[EnableRateLimiting("sensitive-write")]
[Authorize(Policy = "AUTH_USERS_UPDATE")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(Error), 404)]
[ProducesResponseType(typeof(Error), 400)]
public Task<ActionResult> ForcePasswordReset(Guid userId, CancellationToken cancellationToken)
Parameters
userIdGuidcancellationTokenCancellationToken
Returns
- Task<ActionResult>
GetLoginAttempts(Guid, int, int, bool, CancellationToken)
Get paginated login attempt history for a user
[HttpGet("{userId:guid}/login-attempts")]
[Authorize(Policy = "AUTH_USERS_VIEW")]
[ProducesResponseType(typeof(PaginatorResponseDto<LoginAttemptDto>), 200)]
[ProducesResponseType(typeof(Error), 404)]
[ProducesResponseType(typeof(Error), 400)]
public Task<ActionResult> GetLoginAttempts(Guid userId, int page = 1, int pageSize = 10, bool onlyFailed = false, CancellationToken cancellationToken = default)
Parameters
userIdGuidpageintpageSizeintonlyFailedboolcancellationTokenCancellationToken
Returns
- Task<ActionResult>
GetMyAccessibleModules(CancellationToken)
Returns the distinct Auth.Modules.ModuleKey values (uppercase) the current user has ANY effective permission in, resolved from the real Permission -> SubModule -> Module relationship (not a code-prefix guess). Used by the frontend to decide whether a whole section (menu item + parent route) should be reachable, independent of which specific granular permission (View/Create/etc.) the user actually holds.
[HttpGet("me/accessible-modules")]
[Authorize]
[ProducesResponseType(typeof(IReadOnlyCollection<string>), 200)]
public Task<ActionResult<IReadOnlyCollection<string>>> GetMyAccessibleModules(CancellationToken cancellationToken)
Parameters
cancellationTokenCancellationToken
Returns
- Task<ActionResult<IReadOnlyCollection<string>>>
GetMyPermissions(CancellationToken)
Returns the effective permission codes of the current authenticated
user. For normal users this is the deduplicated union of the permissions
of every role attached to their primary branch. For users with an
ACTIVE grant in Auth.PlatformAdmins, this returns the complete
catalog of permission codes so the frontend (which hides buttons and
routes based on hasPermission()) treats them as fully privileged.
The UI should call this once right after login and whenever the token is refreshed.
[HttpGet("me/permissions")]
[Authorize]
[ProducesResponseType(typeof(IReadOnlyCollection<string>), 200)]
public Task<ActionResult<IReadOnlyCollection<string>>> GetMyPermissions(CancellationToken cancellationToken)
Parameters
cancellationTokenCancellationToken
Returns
- Task<ActionResult<IReadOnlyCollection<string>>>
GetUserBasicInfo(Guid, CancellationToken)
Resolves a user's display name (first + last name) for the current tenant. Deliberately gated by plain [Authorize] instead of Users.View — any authenticated user needs to be able to show "created by / approved by" audit labels for records they can already see, without being granted the admin-level "view all users" permission.
[HttpGet("{id:guid}/basic-info")]
[Authorize]
[ProducesResponseType(typeof(UserBasicInfoDto), 200)]
[ProducesResponseType(typeof(Error), 404)]
public Task<ActionResult<UserBasicInfoDto>> GetUserBasicInfo(Guid id, CancellationToken cancellationToken)
Parameters
idGuidcancellationTokenCancellationToken
Returns
- Task<ActionResult<UserBasicInfoDto>>
GetUserById(Guid, CancellationToken)
Get user by ID
[HttpGet("{id:guid}")]
[Authorize(Policy = "AUTH_USERS_VIEW")]
[ProducesResponseType(typeof(UserDto), 200)]
[ProducesResponseType(typeof(Error), 404)]
[ProducesResponseType(typeof(Error), 400)]
public Task<ActionResult> GetUserById(Guid id, CancellationToken cancellationToken)
Parameters
idGuidcancellationTokenCancellationToken
Returns
- Task<ActionResult>
GetUsers(PaginatorRequestDto, Guid?, CancellationToken)
Get all users with pagination, optionally filtered by tenant branch
[HttpGet]
[Authorize(Policy = "AUTH_USERS_VIEW")]
[ProducesResponseType(typeof(PaginatorResponseDto<UserDto>), 200)]
[ProducesResponseType(typeof(Error), 400)]
public Task<ActionResult> GetUsers(PaginatorRequestDto paginatorRequest, Guid? tenantBranchId = null, CancellationToken cancellationToken = default)
Parameters
paginatorRequestPaginatorRequestDtotenantBranchIdGuid?cancellationTokenCancellationToken
Returns
- Task<ActionResult>
UnlockUser(Guid, CancellationToken)
Unlock a locked-out user account
[HttpPatch("{userId:guid}/unlock")]
[EnableRateLimiting("sensitive-write")]
[Authorize(Policy = "AUTH_USERS_UPDATE")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(Error), 404)]
[ProducesResponseType(typeof(Error), 400)]
public Task<ActionResult> UnlockUser(Guid userId, CancellationToken cancellationToken)
Parameters
userIdGuidcancellationTokenCancellationToken
Returns
- Task<ActionResult>
UpdateUser(Guid, UpdateUserDto, CancellationToken)
Update an existing user (profile, tenant branch, and roles)
[HttpPut("{id:guid}")]
[EnableRateLimiting("sensitive-write")]
[Authorize(Policy = "AUTH_USERS_UPDATE")]
[ProducesResponseType(200)]
[ProducesResponseType(typeof(Error), 400)]
[ProducesResponseType(typeof(Error), 404)]
[ProducesResponseType(typeof(Error), 409)]
public Task<ActionResult> UpdateUser(Guid id, UpdateUserDto request, CancellationToken cancellationToken)
Parameters
idGuidrequestUpdateUserDtocancellationTokenCancellationToken
Returns
- Task<ActionResult>