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
103 lines
2.0 KiB
JavaScript
103 lines
2.0 KiB
JavaScript
import js from '@eslint/js';
|
|
import tseslint from 'typescript-eslint';
|
|
import sveltePlugin from 'eslint-plugin-svelte';
|
|
import svelteParser from 'svelte-eslint-parser';
|
|
import prettier from 'eslint-config-prettier';
|
|
|
|
export default tseslint.config(
|
|
// Base JavaScript recommended rules
|
|
js.configs.recommended,
|
|
|
|
// TypeScript recommended rules
|
|
...tseslint.configs.recommended,
|
|
|
|
// Global ignores
|
|
{
|
|
ignores: [
|
|
'.svelte-kit/**',
|
|
'build/**',
|
|
'dist/**',
|
|
'node_modules/**',
|
|
'*.config.js',
|
|
'*.config.ts'
|
|
]
|
|
},
|
|
|
|
// TypeScript files
|
|
{
|
|
files: ['**/*.ts'],
|
|
languageOptions: {
|
|
parserOptions: {
|
|
sourceType: 'module',
|
|
ecmaVersion: 2020
|
|
},
|
|
globals: {
|
|
window: 'readonly',
|
|
document: 'readonly',
|
|
console: 'readonly',
|
|
process: 'readonly',
|
|
__dirname: 'readonly',
|
|
__filename: 'readonly',
|
|
Promise: 'readonly',
|
|
Set: 'readonly',
|
|
Map: 'readonly'
|
|
}
|
|
},
|
|
rules: {
|
|
'@typescript-eslint/no-unused-vars': [
|
|
'error',
|
|
{
|
|
argsIgnorePattern: '^_',
|
|
varsIgnorePattern: '^_'
|
|
}
|
|
],
|
|
'no-console': ['warn', { allow: ['warn', 'error'] }]
|
|
}
|
|
},
|
|
|
|
// Svelte files
|
|
{
|
|
files: ['**/*.svelte'],
|
|
languageOptions: {
|
|
parser: svelteParser,
|
|
parserOptions: {
|
|
parser: tseslint.parser,
|
|
sourceType: 'module',
|
|
ecmaVersion: 2020,
|
|
extraFileExtensions: ['.svelte']
|
|
},
|
|
globals: {
|
|
window: 'readonly',
|
|
document: 'readonly',
|
|
console: 'readonly',
|
|
process: 'readonly',
|
|
Promise: 'readonly',
|
|
Set: 'readonly',
|
|
Map: 'readonly',
|
|
Event: 'readonly',
|
|
SubmitEvent: 'readonly',
|
|
fetch: 'readonly',
|
|
HTMLDivElement: 'readonly',
|
|
setInterval: 'readonly',
|
|
clearInterval: 'readonly'
|
|
}
|
|
},
|
|
plugins: {
|
|
svelte: sveltePlugin
|
|
},
|
|
rules: {
|
|
...sveltePlugin.configs.recommended.rules,
|
|
'@typescript-eslint/no-unused-vars': [
|
|
'error',
|
|
{
|
|
argsIgnorePattern: '^_',
|
|
varsIgnorePattern: '^_'
|
|
}
|
|
]
|
|
}
|
|
},
|
|
|
|
// Prettier (disable conflicting rules)
|
|
prettier
|
|
);
|