Allow deletion of admins

This commit is contained in:
Robert van Diest
2026-03-25 19:14:02 +01:00
parent 83d2ad02d0
commit 3219b3a14d
5 changed files with 17 additions and 5 deletions

View File

@@ -19,8 +19,9 @@ public class AdminController(
DeleteUserHandler deleteUserHandler,
MakeAdminHandler makeAdminHandler) : ControllerBase
{
private bool IsAdmin =>
User.FindFirstValue("isAdmin") == "true";
private bool IsAdmin => User.FindFirstValue("isAdmin") == "true";
private Guid RequesterId => Guid.Parse(User.FindFirstValue(System.Security.Claims.ClaimTypes.NameIdentifier)
?? User.FindFirstValue("sub")!);
[HttpGet("users")]
public async Task<IActionResult> GetAllUsers(CancellationToken ct)
@@ -62,7 +63,7 @@ public class AdminController(
public async Task<IActionResult> DeleteUser(Guid id, CancellationToken ct)
{
if (!IsAdmin) return Forbid();
var result = await deleteUserHandler.HandleAsync(new DeleteUserCommand(id), ct);
var result = await deleteUserHandler.HandleAsync(new DeleteUserCommand(RequesterId, id), ct);
if (!result.IsSuccess)
return BadRequest(new ProblemDetails { Detail = result.Error });
return NoContent();

View File

@@ -1,3 +1,3 @@
namespace Randall.Application.Admin.DeleteUser;
public record DeleteUserCommand(Guid UserId);
public record DeleteUserCommand(Guid RequesterId, Guid UserId);

View File

@@ -11,8 +11,15 @@ public class DeleteUserHandler(IUserRepository userRepository)
if (user is null)
return Result.Failure("User not found.");
if (user.Id == command.RequesterId)
return Result.Failure("You cannot delete your own account.");
if (user.IsAdmin)
return Result.Failure("Admin users cannot be deleted.");
{
var adminCount = await userRepository.CountAdminsAsync(ct);
if (adminCount <= 1)
return Result.Failure("Cannot delete the last admin account.");
}
userRepository.Delete(user);
await userRepository.SaveChangesAsync(ct);

View File

@@ -7,6 +7,7 @@ public interface IUserRepository
Task<bool> ExistsByEmailAsync(string email, CancellationToken ct = default);
Task<List<User>> GetPendingAsync(CancellationToken ct = default);
Task<List<User>> GetAllAsync(CancellationToken ct = default);
Task<int> CountAdminsAsync(CancellationToken ct = default);
Task<List<User>> GetAllNonAdminAsync(CancellationToken ct = default);
Task AddAsync(User user, CancellationToken ct = default);
void Delete(User user);

View File

@@ -20,6 +20,9 @@ public class UserRepository(AppDbContext context) : IUserRepository
public Task<List<User>> GetAllAsync(CancellationToken ct = default) =>
context.Users.OrderBy(u => u.Name).ToListAsync(ct);
public Task<int> CountAdminsAsync(CancellationToken ct = default) =>
context.Users.CountAsync(u => u.IsAdmin);
public Task<List<User>> GetAllNonAdminAsync(CancellationToken ct = default) =>
context.Users.Where(u => !u.IsAdmin).OrderBy(u => u.Name).ToListAsync(ct);