Application mono-utilisateur : inscription unique, connexion par JWT (12 h), protection de toutes les routes de données, réinitialisation de mot de passe par email avec repli de journalisation, onboarding réorganisé en deux étapes (inscription → connexion → profil + véhicule). Backend (SchotzIadKmTracker.Api) : - Entités Compte (singleton) et ResetPasswordToken + migration AjoutAuthentification. - Hachage PasswordHasher, JwtService (HS256, durée configurable), IEmailService (MailKit + repli LoggingEmailService selon Smtp:Host). - AuthService (register 409 si compte existant, login 401 générique, forgot-password non-divulgation, reset à usage unique + expiration), AuthController (5 endpoints publics), DTOs + validateurs FluentValidation. - Sécurité pipeline : JwtBearer + filtre d'autorisation global, UseAuthentication avant UseAuthorization ; /health et /api/auth/* publics. Frontend (schotziad-km-tracker, zoneless + signals) : - AuthService (localStorage), authInterceptor (Bearer + purge/redirection 401), authGuard, écrans Login/Register/ForgotPassword/ResetPassword, routes publiques et protection [authGuard, profilConfigureGuard]. Configuration : .env.example et docker-compose.yml (JWT__SecretKey, durées, Smtp__*). Tests : 54 tests backend (propriétés FsCheck P1–P14, exemples, intégration WebApplicationFactory) + tests frontend (AuthService, authGuard, authInterceptor, ResetPasswordComponent). Suite complète au vert. Spec : .kiro/specs/authentification (requirements, design, tasks).
61 lines
2.3 KiB
C#
61 lines
2.3 KiB
C#
using FluentAssertions;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using SchotzIadKmTracker.Api.Configuration;
|
|
using SchotzIadKmTracker.Api.Services;
|
|
using Xunit;
|
|
|
|
namespace SchotzIadKmTracker.Tests.Auth;
|
|
|
|
/// <summary>
|
|
/// Vérifie la logique de sélection en DI de l'implémentation d'<see cref="IEmailService"/>,
|
|
/// telle que décrite dans <c>Program.cs</c> :
|
|
/// Smtp:Host vide => LoggingEmailService (repli journalisation, Exigence 6.5)
|
|
/// Smtp:Host renseigné => SmtpEmailService (MailKit, Exigence 6.4)
|
|
///
|
|
/// On reconstruit un <see cref="ServiceCollection"/> minimal appliquant la même condition
|
|
/// (<c>string.IsNullOrWhiteSpace(smtpOptions.Host)</c>) puis on résout le service pour
|
|
/// confirmer le type concret retenu, sans démarrer l'hôte complet (évite l'accès à la base réelle).
|
|
/// </summary>
|
|
public class AuthServiceEmailSelectionTests
|
|
{
|
|
private static IEmailService ResoudreEmailService(string host)
|
|
{
|
|
var smtpOptions = new SmtpOptions { Host = host };
|
|
|
|
var services = new ServiceCollection();
|
|
services.AddLogging();
|
|
services.Configure<SmtpOptions>(o => o.Host = host);
|
|
|
|
// Réplique exacte de la condition de Program.cs (section « Sélection de l'implémentation Email »).
|
|
if (string.IsNullOrWhiteSpace(smtpOptions.Host))
|
|
services.AddScoped<IEmailService, LoggingEmailService>();
|
|
else
|
|
services.AddScoped<IEmailService, SmtpEmailService>();
|
|
|
|
var provider = services.BuildServiceProvider();
|
|
return provider.GetRequiredService<IEmailService>();
|
|
}
|
|
|
|
// Feature: authentification, sélection DI email (5.3) : Host vide => LoggingEmailService.
|
|
// Validates: Requirements 6.5
|
|
[Theory]
|
|
[InlineData("")]
|
|
[InlineData(" ")]
|
|
public void Host_vide_selectionne_LoggingEmailService(string host)
|
|
{
|
|
var service = ResoudreEmailService(host);
|
|
service.Should().BeOfType<LoggingEmailService>();
|
|
}
|
|
|
|
// Feature: authentification, sélection DI email (5.3) : Host renseigné => SmtpEmailService.
|
|
// Validates: Requirements 6.4
|
|
[Fact]
|
|
public void Host_renseigne_selectionne_SmtpEmailService()
|
|
{
|
|
var service = ResoudreEmailService("smtp.example.com");
|
|
service.Should().BeOfType<SmtpEmailService>();
|
|
}
|
|
}
|