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 signInManager, UserManager userManager) : ControllerBase { [HttpPost("login")] [AllowAnonymous] public async Task 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 Logout() { await signInManager.SignOutAsync(); return Ok(new { message = "Logout erfolgreich." }); } [HttpGet("me")] [Authorize] public async Task> Me() { var user = await userManager.GetUserAsync(User); if (user is null) return Unauthorized(); var roles = await userManager.GetRolesAsync(user); return Ok(new CurrentUserResponse { Id = user.Id, UserName = user.UserName ?? string.Empty, Roles = roles.OrderBy(x => x).ToList(), IsActive = user.IsActive, MustChangePassword = user.MustChangePassword }); } [HttpPost("password")] [Authorize] public async Task ChangePassword([FromBody] ChangePasswordRequest pwChangeDto) { var user = await userManager.GetUserAsync(User); if (user is null) return Unauthorized(); if (string.IsNullOrWhiteSpace(pwChangeDto.NewPassword) || string.IsNullOrWhiteSpace(pwChangeDto.OldPassword) || string.IsNullOrWhiteSpace(pwChangeDto.NewPasswordConfirm)) { return BadRequest(new { message = "Alle Passwörter müssen einen Wert enthalten." }); } if (pwChangeDto.NewPassword != pwChangeDto.NewPasswordConfirm) { return BadRequest(new { message = "Die neuen Passwörter stimmen nicht überein." }); } var result = await userManager.ChangePasswordAsync( user, pwChangeDto.OldPassword, pwChangeDto.NewPassword ); if (!result.Succeeded) { return BadRequest(new { message = "Passwort konnte nicht geändert werden.", errors = result.Errors.Select(e => e.Description) }); } var stampResult = await userManager.UpdateSecurityStampAsync(user); if (!stampResult.Succeeded) { return StatusCode(500, new { message = "Passwort geändert, aber Sessions konnten nicht invalidiert werden." }); } await signInManager.SignOutAsync(); return Ok(new { message = "Passwort geändert. Du wurdest auf allen Geräten abgemeldet." }); } } }