emloyee and user fixings
This commit is contained in:
@@ -27,13 +27,15 @@ public sealed class AuthController : ControllerBase
|
||||
private readonly IAuthRecoveryService _recovery;
|
||||
private readonly IAuthAltService _alt;
|
||||
private readonly IRoleService _roles;
|
||||
private readonly IAuditService _audit;
|
||||
|
||||
public AuthController(IAuthUserService users, IAuthRecoveryService recovery, IAuthAltService alt, IRoleService roles)
|
||||
public AuthController(IAuthUserService users, IAuthRecoveryService recovery, IAuthAltService alt, IRoleService roles, IAuditService audit)
|
||||
{
|
||||
_users = users;
|
||||
_recovery = recovery;
|
||||
_alt = alt;
|
||||
_roles = roles;
|
||||
_audit = audit;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -68,6 +70,7 @@ public sealed class AuthController : ControllerBase
|
||||
{
|
||||
var result = await _users.LoginAsync(request, ct);
|
||||
AuthCookieWriter.WriteSession(Response, result.AccessToken, result.RefreshToken, result.Body.ExpiresIn);
|
||||
if (result.Body.User?.UserId is Guid authUserId) await _audit.RecordLoginAsync(authUserId, ClientIp(), ClientUserAgent(), ct);
|
||||
return Ok(result.Body);
|
||||
}
|
||||
|
||||
@@ -78,9 +81,13 @@ public sealed class AuthController : ControllerBase
|
||||
{
|
||||
var result = await _users.VerifyOtpForLoginAsync(request, ct);
|
||||
AuthCookieWriter.WriteSession(Response, result.AccessToken, result.RefreshToken, result.Body.ExpiresIn);
|
||||
if (result.Body.User?.UserId is Guid authUserId) await _audit.RecordLoginAsync(authUserId, ClientIp(), ClientUserAgent(), ct);
|
||||
return Ok(result.Body);
|
||||
}
|
||||
|
||||
private string? ClientIp() => HttpContext.Connection.RemoteIpAddress?.ToString();
|
||||
private string? ClientUserAgent() => Request.Headers.UserAgent.ToString() is { Length: > 0 } ua ? ua : null;
|
||||
|
||||
[HttpPost("refresh-token")]
|
||||
[AllowAnonymous]
|
||||
[ProducesResponseType(typeof(AuthSessionResponse), StatusCodes.Status200OK)]
|
||||
|
||||
@@ -61,4 +61,14 @@ public sealed class BranchesController : ApiControllerBase
|
||||
await _branches.SetStatusAsync(branchId, request.Status, ct);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpDelete("{branchId:int}")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesResponseType(StatusCodes.Status409Conflict)]
|
||||
public async Task<IActionResult> Delete(int branchId, CancellationToken ct)
|
||||
{
|
||||
await _branches.DeleteAsync(branchId, ct);
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,6 @@ public sealed class EmployeesController : ApiControllerBase
|
||||
return Ok(result.Value);
|
||||
}
|
||||
|
||||
/// <summary>Never a hard delete — Employee is retained forever (docs/12-BACKEND-HRM.md C.2).</summary>
|
||||
[HttpPatch("{employeeId:int}/status")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
@@ -93,6 +92,17 @@ public sealed class EmployeesController : ApiControllerBase
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
/// <summary>Permanently deletes the employee and all dependent HR records. Blocked (409) if payroll history exists.</summary>
|
||||
[HttpDelete("{employeeId:int}")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[ProducesResponseType(StatusCodes.Status409Conflict)]
|
||||
public async Task<IActionResult> Delete(int employeeId, CancellationToken ct)
|
||||
{
|
||||
await _employees.DeleteAsync(employeeId, ct);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPost("{employeeId:int}/link-user")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using ERPCore.Domain.Enums;
|
||||
using ERPCore.Dtos.Audit;
|
||||
using ERPCore.Dtos.Common;
|
||||
using ERPCore.Dtos.Hrm;
|
||||
using ERPCore.Dtos.Users;
|
||||
@@ -16,12 +18,14 @@ public sealed class UsersController : ApiControllerBase
|
||||
{
|
||||
private readonly IUserManagementService _users;
|
||||
private readonly IEmployeeUserLinkService _links;
|
||||
private readonly IAuditService _audit;
|
||||
private readonly ICurrentUser _currentUser;
|
||||
|
||||
public UsersController(IUserManagementService users, IEmployeeUserLinkService links, ICurrentUser currentUser)
|
||||
public UsersController(IUserManagementService users, IEmployeeUserLinkService links, IAuditService audit, ICurrentUser currentUser)
|
||||
{
|
||||
_users = users;
|
||||
_links = links;
|
||||
_audit = audit;
|
||||
_currentUser = currentUser;
|
||||
}
|
||||
|
||||
@@ -33,8 +37,8 @@ public sealed class UsersController : ApiControllerBase
|
||||
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(PagedResponse<ManagedUserDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PagedResponse<ManagedUserDto>>> List([FromQuery] PageQuery query, CancellationToken ct)
|
||||
=> Ok(await _users.ListAsync(query, ct));
|
||||
public async Task<ActionResult<PagedResponse<ManagedUserDto>>> List([FromQuery] PageQuery query, [FromQuery] EntityStatus? status, [FromQuery] string? roleCode, CancellationToken ct)
|
||||
=> Ok(await _users.ListAsync(query, status, roleCode, ct));
|
||||
|
||||
/// <summary>AuthHex UserType options for the create-user form's select.</summary>
|
||||
[HttpGet("user-types")]
|
||||
@@ -65,4 +69,18 @@ public sealed class UsersController : ApiControllerBase
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult<ManagedUserDto>> UpdateRole(int userId, [FromBody] UpdateUserRoleRequest request, CancellationToken ct)
|
||||
=> Ok(await _users.UpdateRoleAsync(userId, request, ct));
|
||||
|
||||
/// <summary>Revokes/restores standing inside ERPCore only — see <see cref="IUserManagementService.SetStatusAsync"/>.</summary>
|
||||
[HttpPatch("{userId:int}/status")]
|
||||
[ProducesResponseType(typeof(ManagedUserDto), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult<ManagedUserDto>> UpdateStatus(int userId, [FromBody] UpdateUserStatusRequest request, CancellationToken ct)
|
||||
=> Ok(await _users.SetStatusAsync(userId, request.Status, ct));
|
||||
|
||||
/// <summary>Device/login history ERPCore captures itself — not AuthHex's "currently active sessions"
|
||||
/// (which only ever reports the caller's own). See <see cref="IAuditService.ListLoginDevicesAsync"/>.</summary>
|
||||
[HttpGet("{userId:int}/login-devices")]
|
||||
[ProducesResponseType(typeof(PagedResponse<LoginActivityDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PagedResponse<LoginActivityDto>>> ListLoginDevices(int userId, [FromQuery] PageQuery query, CancellationToken ct)
|
||||
=> Ok(await _audit.ListLoginDevicesAsync(userId, query, ct));
|
||||
}
|
||||
|
||||
@@ -15,8 +15,9 @@ public sealed class WarehousesController : ApiControllerBase
|
||||
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(PagedResponse<WarehouseDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<PagedResponse<WarehouseDto>>> List([FromQuery] PageQuery query, CancellationToken ct)
|
||||
=> Ok(await _warehouses.ListAsync(query, ct));
|
||||
public async Task<ActionResult<PagedResponse<WarehouseDto>>> List(
|
||||
[FromQuery] PageQuery query, [FromQuery] int? branchId, CancellationToken ct)
|
||||
=> Ok(await _warehouses.ListAsync(query, branchId, ct));
|
||||
|
||||
[HttpGet("{warehouseId:int}")]
|
||||
[ProducesResponseType(typeof(WarehouseDto), StatusCodes.Status200OK)]
|
||||
|
||||
Reference in New Issue
Block a user