Files
Hoard/API/Controllers/Auth/AppUserController.cs
T
2026-05-03 15:59:20 +02:00

169 lines
6.1 KiB
C#

using API.Contracts.Auth;
using API.Models;
using API.Security;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace API.Controllers.Auth
{
[ApiController]
[Authorize(Policy = PolicyNames.AdminOnly)]
[Route("auth/user")]
public class AppUserController(UserManager<AppUser> userManager) : ControllerBase
{
[HttpGet]
public async Task<ActionResult<IReadOnlyList<CurrentUserResponse>>> GetAppUsers()
{
var users = await userManager.Users
.OrderBy(x => x.UserName)
.ToListAsync();
var responses = new List<CurrentUserResponse>(users.Count);
foreach (var user in users)
{
responses.Add(await user.ToCurrentUserResponseAsync(userManager));
}
return Ok(responses);
}
[HttpGet("{id:guid}")]
public async Task<ActionResult<CurrentUserResponse>> GetAppUserById([FromRoute] Guid id)
{
var user = await userManager.Users.FirstOrDefaultAsync(x => x.Id == id);
if (user is null)
{
return NotFound(new { message = "Benutzer wurde nicht gefunden." });
}
return Ok(await user.ToCurrentUserResponseAsync(userManager));
}
[HttpPatch("{id:guid}")]
public async Task<IActionResult> UpdateAppUser([FromRoute] Guid id, [FromBody] ChangeUserRequest changeDto)
{
var user = await userManager.Users.FirstOrDefaultAsync(x => x.Id == id);
if (user is null)
{
return NotFound(new { message = "Benutzer wurde nicht gefunden." });
}
if (changeDto.IsActive != null)
{
if (!changeDto.IsActive.Value && await userManager.IsInRoleAsync(user, RoleNames.Admin))
{
return StatusCode(StatusCodes.Status403Forbidden,
new { message = "Adminkonten können nicht deaktiviert werden." });
}
user.IsActive = changeDto.IsActive.Value;
if (!changeDto.IsActive.Value)
{
var stampResult = await userManager.UpdateSecurityStampAsync(user);
if (!stampResult.Succeeded)
{
return StatusCode(500, new { message = "Benutzer wurde deaktiviert, aber Sessions konnten nicht invalidiert werden. " +
"Er könnte also immer noch Angemeldet sein!" });
}
}
}
if (changeDto.UserName != null)
{
var newUserName = changeDto.UserName.Trim();
if (string.IsNullOrEmpty(newUserName))
{
return BadRequest(new { message = "Benutzername darf nicht leer sein." });
}
if (!string.Equals(newUserName, user.UserName, StringComparison.OrdinalIgnoreCase))
{
var setNameResult = await userManager.SetUserNameAsync(user, newUserName);
if (!setNameResult.Succeeded)
{
if (setNameResult.Errors.Any(e => e.Code == nameof(IdentityErrorDescriber.DuplicateUserName)))
{
return Conflict(new { message = "Benutzername ist bereits vergeben." });
}
return BadRequest(new { message = "Benutzername konnte nicht geändert werden.", errors = setNameResult.Errors.Select(e => e.Description) });
}
}
}
if (changeDto.MustChangePassword != null)
{
user.MustChangePassword = changeDto.MustChangePassword.Value;
await userManager.UpdateAsync(user);
}
return Ok(await user.ToCurrentUserResponseAsync(userManager));
}
[HttpPost]
public async Task<IActionResult> CreateNewAppUser([FromBody] CreateUserRequest createDto)
{
var newUser = new AppUser
{
UserName = createDto.UserName.Trim(),
MustChangePassword = true,
IsActive = createDto.IsActive,
};
var result = await userManager.CreateAsync(newUser, createDto.StartPassword);
if (!result.Succeeded)
{
if (result.Errors.Any(e => e.Code == nameof(IdentityErrorDescriber.DuplicateUserName)))
{
return Conflict(new { message = "Benutzername ist bereits vergeben." });
}
var passwordErrors = result.Errors
.Where(e => e.Code.StartsWith("Password"))
.Select(e => e.Description)
.ToList();
if (passwordErrors.Any())
{
return UnprocessableEntity(new
{
message = "Passwort erfüllt nicht die Sicherheitsanforderungen.",
errors = passwordErrors
});
}
return BadRequest(new
{
message = "Benutzer konnte nicht erstellt werden.",
errors = result.Errors.Select(e => e.Description)
});
}
if (createDto.IsAdmin)
{
var roleResult = await userManager.AddToRoleAsync(newUser, RoleNames.Admin);
if (!roleResult.Succeeded)
{
return BadRequest(new
{
message = "Benutzer wurde erstellt, aber Rolle konnte nicht zugewiesen werden.",
errors = roleResult.Errors.Select(e => e.Description)
});
}
}
return CreatedAtAction(nameof(GetAppUserById), new { id = newUser.Id },
await newUser.ToCurrentUserResponseAsync(userManager));
}
}
}