14176a3ee2
Introduce full admin user listing/detail endpoints and a forced password-change flow. Backend: make CurrentUserResponse.UserName nullable and add ToCurrentUserResponseAsync extension; AppUserController now exposes GET /auth/user (list) and GET /auth/user/{id} (detail) using UserManager and Admin-only policy; AuthController uses the new mapper and after successful password change clears MustChangePassword, updates UpdatedAt and persists changes (with error handling) before updating security stamp. Frontend: add admin users pages (list + detail), ChangePassword page and route, adminUsers and enhanced authSession services (typed responses, changePassword API, error mapping), router guard to redirect users with mustChangePassword=true to the change-password flow, and show success banner on login after password change. UI tweaks: separate admin section in sidebar, add password-change entries in account menu, footer sizing fixes, and various layout/UX improvements. These changes enable admin account management and enforce secure password updates across the app.
40 lines
1.3 KiB
C#
40 lines
1.3 KiB
C#
using API.Contracts.Auth;
|
|
using API.Models;
|
|
using API.Security;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
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 tasks = users.Select(user => user.ToCurrentUserResponseAsync(userManager));
|
|
return Ok(await Task.WhenAll(tasks));
|
|
}
|
|
|
|
[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));
|
|
}
|
|
}
|
|
}
|