Files
Classeo/backend/.php-cs-fixer.dist.php
Mathias STRASSER b9d9f48305 feat: Connexion utilisateur avec sécurité renforcée
Implémente la Story 1.4 du système d'authentification avec plusieurs
couches de protection contre les attaques par force brute.

Sécurité backend :
- Authentification JWT avec access token (15min) + refresh token (7j)
- Rotation automatique des refresh tokens avec détection de replay
- Rate limiting progressif par IP (délai Fibonacci après échecs)
- Intégration Cloudflare Turnstile CAPTCHA après 5 tentatives
- Alerte email à l'utilisateur après blocage temporaire
- Isolation multi-tenant (un utilisateur ne peut se connecter que sur
  son établissement)

Frontend :
- Page de connexion avec feedback visuel des délais et erreurs
- Composant TurnstileCaptcha réutilisable
- Gestion d'état auth avec stockage sécurisé des tokens
- Tests E2E Playwright pour login, tenant isolation, et activation

Infrastructure :
- Configuration Symfony Security avec json_login + jwt
- Cache pools séparés (filesystem en test, Redis en prod)
- NullLoginRateLimiter pour environnement de test (évite blocage CI)
- Génération des clés JWT en CI après démarrage du backend
2026-02-01 14:43:12 +01:00

65 lines
2.1 KiB
PHP

<?php
declare(strict_types=1);
$finder = (new PhpCsFixer\Finder())
->in(__DIR__)
->exclude('var')
->exclude('vendor')
// Fichiers auto-générés par Symfony/Doctrine
->notPath('config/bundles.php')
->notPath('config/preload.php')
->notPath('config/reference.php')
->notPath('src/DataFixtures/AppFixtures.php')
// Exclusions spécifiques
->notPath('src/Shared/Domain/AggregateRoot.php')
->notPath('src/Shared/Domain/EntityId.php')
// Classes that need to be mocked in tests (cannot be final)
->notPath('src/Shared/Infrastructure/Tenant/TenantResolver.php')
// Domain TenantId needs to be extended by Infrastructure alias during migration
->notPath('src/Shared/Domain/Tenant/TenantId.php')
;
return (new PhpCsFixer\Config())
->setRules([
'@Symfony' => true,
'@Symfony:risky' => true,
'declare_strict_types' => true,
'strict_param' => true,
'array_syntax' => ['syntax' => 'short'],
'ordered_imports' => ['sort_algorithm' => 'alpha'],
'no_unused_imports' => true,
'not_operator_with_successor_space' => false,
'trailing_comma_in_multiline' => true,
'phpdoc_order' => true,
'phpdoc_separation' => true,
'phpdoc_no_empty_return' => true,
'native_function_invocation' => [
'include' => ['@compiler_optimized'],
'scope' => 'namespaced',
'strict' => true,
],
'native_constant_invocation' => true,
'global_namespace_import' => [
'import_classes' => true,
'import_constants' => true,
'import_functions' => true,
],
'final_class' => true,
'class_definition' => [
'single_line' => true,
],
'concat_space' => [
'spacing' => 'one',
],
'single_line_throw' => false,
// NO Yoda conditions
'yoda_style' => false,
'blank_line_before_statement' => [
'statements' => ['return', 'throw', 'try'],
],
])
->setRiskyAllowed(true)
->setFinder($finder)
;