using Microsoft.AspNetCore.Mvc; using SchotzIadKmTracker.Api.Models.DTOs; using SchotzIadKmTracker.Api.Services; using SchotzIadKmTracker.Api.Services.Exceptions; namespace SchotzIadKmTracker.Api.Controllers; /// /// Endpoints réservés à un utilisateur AUTHENTIFIÉ. Ce controller ne porte PAS /// [AllowAnonymous] : il est donc soumis à l'autorisation globale /// (RequireAuthenticatedUser) — atteignable uniquement avec un jeton valide ET un /// compte existant (le middleware JWT rejette un jeton dont le compte est introuvable /// via OnTokenValidated). C'est pourquoi le changement de mot de passe est placé ICI /// et non dans AuthController (qui porte [AllowAnonymous] au niveau classe : un /// [Authorize] sur une action de ce dernier n'aurait pas suffi à exiger un jeton). /// [ApiController] [Route("api/auth")] public class SessionController : ControllerBase { private readonly IAuthService _authService; public SessionController(IAuthService authService) { _authService = authService; } /// /// Retourne 200 si la session est valide (jeton valide + compte existant), 401 sinon. /// [HttpGet("moi")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public IActionResult Moi() { return Ok(new { authentifie = true }); } /// /// Change le mot de passe d'un utilisateur authentifié (page « Compte utilisateur »). /// Contrairement à la réinitialisation par jeton email, exige l'ancien mot de passe. /// Un mot de passe actuel incorrect est rejeté en 400 ; les erreurs de validation du /// nouveau mot de passe (longueur) sont renvoyées automatiquement en 400 par FluentValidation. /// [HttpPost("change-password")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task ChangePassword( [FromBody] ChangePasswordDto dto, CancellationToken cancellationToken) { try { await _authService.ChangePasswordAsync(dto, cancellationToken); return Ok(); } catch (MotDePasseActuelInvalideException ex) { return Problem(detail: ex.Message, statusCode: StatusCodes.Status400BadRequest); } } }