Add auth controller/DTOs and update seed password

Introduce authentication API: add AuthController with login, logout and me endpoints using SignInManager/UserManager; add LoginRequest and CurrentUserResponse DTOs. Login enforces active users, updates UpdatedAt on success, and returns localized messages. Also change default seed admin password from "Hoard" to "HoardPassword".
This commit is contained in:
Jonas
2026-04-18 22:04:51 +02:00
parent ffaf5d24c1
commit fc99c91bd8
4 changed files with 91 additions and 1 deletions
+11
View File
@@ -0,0 +1,11 @@
namespace API.Contracts.Auth
{
public class CurrentUserResponse
{
public Guid Id { get; set; }
public string UserName { get; set; } = string.Empty;
public bool IsAdmin { get; set; }
public bool IsActive { get; set; }
public bool MustChangePassword { get; set; }
}
}
+8
View File
@@ -0,0 +1,8 @@
namespace API.Contracts.Auth
{
public class LoginRequest
{
public string UserName { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
}
}
+71
View File
@@ -0,0 +1,71 @@
using API.Contracts.Auth;
using API.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace API.Controllers.Auth
{
[ApiController]
[Route("auth")]
public class AuthController(
SignInManager<AppUser> signInManager,
UserManager<AppUser> userManager)
: ControllerBase
{
[HttpPost("login")]
[AllowAnonymous]
public async Task<IActionResult> Login([FromBody] LoginRequest request)
{
if (string.IsNullOrWhiteSpace(request.UserName) || string.IsNullOrWhiteSpace(request.Password))
return BadRequest(new { message = "Benutzername und Passwort sind erforderlich." });
var user = await userManager.FindByNameAsync(request.UserName);
if (user is null)
return Unauthorized(new { message = "Ungültige Anmeldedaten." });
if (!user.IsActive)
return Forbid();
var result = await signInManager.PasswordSignInAsync(
user,
request.Password,
isPersistent: true,
lockoutOnFailure: false);
if (!result.Succeeded)
return Unauthorized(new { message = "Ungültige Anmeldedaten." });
user.UpdatedAt = DateTimeOffset.UtcNow;
await userManager.UpdateAsync(user);
return Ok(new { message = "Login erfolgreich." });
}
[HttpPost("logout")]
[Authorize]
public async Task<IActionResult> Logout()
{
await signInManager.SignOutAsync();
return Ok(new { message = "Logout erfolgreich." });
}
[HttpGet("me")]
[Authorize]
public async Task<ActionResult<CurrentUserResponse>> Me()
{
var user = await userManager.GetUserAsync(User);
if (user is null)
return Unauthorized();
return Ok(new CurrentUserResponse
{
Id = user.Id,
UserName = user.UserName ?? string.Empty,
IsAdmin = user.IsAdmin,
IsActive = user.IsActive,
MustChangePassword = user.MustChangePassword
});
}
}
}
+1 -1
View File
@@ -20,7 +20,7 @@ namespace API.Services
} }
var adminUserName = configuration["SeedAdmin:UserName"] ?? "admin"; var adminUserName = configuration["SeedAdmin:UserName"] ?? "admin";
var adminPassword = configuration["SeedAdmin:Password"] ?? "Hoard"; var adminPassword = configuration["SeedAdmin:Password"] ?? "HoardPassword";
var adminEmail = configuration["SeedAdmin:Email"]; var adminEmail = configuration["SeedAdmin:Email"];
var admin = new AppUser var admin = new AppUser