142 lines
4.8 KiB
C#
142 lines
4.8 KiB
C#
using System;
|
|
using System.Security.Claims;
|
|
using System.Text.Json.Serialization;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using FinlyticBackend.Services;
|
|
using FinlyticCore.Models.Auth;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Cors;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
namespace FinlyticBackend.Controllers;
|
|
|
|
/// <summary>
|
|
/// DTO for admin password reset requests (AOT-compliant).
|
|
/// </summary>
|
|
public record ResetPasswordAdminDto(
|
|
[property: JsonPropertyName("newPassword")] string NewPassword
|
|
);
|
|
|
|
[ApiController]
|
|
[Route("api/v1/admin")]
|
|
[Authorize(Roles = "Admin")]
|
|
[EnableCors("AllowAll")]
|
|
public class AdminUserController : ControllerBase
|
|
{
|
|
private readonly IUserService _userService;
|
|
|
|
public AdminUserController(IUserService userService)
|
|
{
|
|
_userService = userService;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new user account by an administrator.
|
|
/// </summary>
|
|
[HttpPost("users")]
|
|
public async Task<IActionResult> CreateUser([FromBody] CreateUserRequestDto request, CancellationToken cancellationToken)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(request.Email) || string.IsNullOrWhiteSpace(request.Password))
|
|
{
|
|
return BadRequest(new { error = "Email and Password are required." });
|
|
}
|
|
|
|
var createdUser = await _userService.CreateUserByAdminAsync(request, cancellationToken);
|
|
if (createdUser == null)
|
|
{
|
|
return Conflict(new { error = $"User with email '{request.Email}' already exists." });
|
|
}
|
|
|
|
return StatusCode(201, createdUser);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves a list of all registered users.
|
|
/// </summary>
|
|
[HttpGet("users")]
|
|
public async Task<IActionResult> GetAllUsers(CancellationToken cancellationToken)
|
|
{
|
|
var users = await _userService.GetAllUsersAsync(cancellationToken);
|
|
return Ok(users);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates an existing user account.
|
|
/// </summary>
|
|
[HttpPut("users/{id:guid}")]
|
|
public async Task<IActionResult> UpdateUser(Guid id, [FromBody] UpdateUserRequestDto request, CancellationToken cancellationToken)
|
|
{
|
|
var currentAdminId = GetCurrentUserId();
|
|
|
|
// Schutz: Ein Admin sollte sich nicht selbst abwerten oder deaktivieren können
|
|
if (currentAdminId.HasValue && currentAdminId.Value == id)
|
|
{
|
|
if (request.IsActive == false)
|
|
{
|
|
return BadRequest(new { error = "You cannot deactivate your own admin account." });
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(request.Role) && !request.Role.Equals("Admin", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return BadRequest(new { error = "You cannot revoke your own Admin role." });
|
|
}
|
|
}
|
|
|
|
var updated = await _userService.UpdateUserAsync(id, request, cancellationToken);
|
|
if (updated == null)
|
|
{
|
|
return NotFound(new { error = $"User with ID '{id}' not found." });
|
|
}
|
|
|
|
return Ok(updated);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deactivates a user account.
|
|
/// </summary>
|
|
[HttpDelete("users/{id:guid}")]
|
|
public async Task<IActionResult> DeactivateUser(Guid id, CancellationToken cancellationToken)
|
|
{
|
|
var currentAdminId = GetCurrentUserId();
|
|
|
|
if (currentAdminId.HasValue && currentAdminId.Value == id)
|
|
{
|
|
return BadRequest(new { error = "You cannot deactivate your own admin account." });
|
|
}
|
|
|
|
bool deactivated = await _userService.DeactivateUserAsync(id, cancellationToken);
|
|
if (!deactivated)
|
|
{
|
|
return NotFound(new { error = $"User with ID '{id}' not found." });
|
|
}
|
|
|
|
return Ok(new { message = $"User '{id}' deactivated successfully." });
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resets a user's password and forces password change on next login.
|
|
/// </summary>
|
|
[HttpPost("users/{id:guid}/reset-password")]
|
|
public async Task<IActionResult> ResetPassword(Guid id, [FromBody] ResetPasswordAdminDto request, CancellationToken cancellationToken)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(request?.NewPassword))
|
|
{
|
|
return BadRequest(new { error = "NewPassword is required." });
|
|
}
|
|
|
|
bool reset = await _userService.ResetPasswordAsync(id, request.NewPassword, cancellationToken);
|
|
if (!reset)
|
|
{
|
|
return NotFound(new { error = $"User with ID '{id}' not found." });
|
|
}
|
|
|
|
return Ok(new { message = $"Password for user '{id}' has been reset successfully. They must change it upon next login." });
|
|
}
|
|
|
|
private Guid? GetCurrentUserId()
|
|
{
|
|
var claimVal = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue("sub");
|
|
return Guid.TryParse(claimVal, out var parsed) ? parsed : null;
|
|
}
|
|
} |