**Motivations:** - Migrer api-relay vers base de données SQLite (production) - Ajouter authentification API key pour endpoints POST (protection abus) - PersistentNonceCache pour service-login-verify (IndexedDB/localStorage) - Écran paramètres crypto avancés UserWallet - Documenter options non implémentées (Merkle, évolutions api-relay) **Root causes:** - N/A (évolutions + correctifs) **Correctifs:** - N/A **Evolutions:** - api-relay: DatabaseStorageService (SQLite), StorageAdapter (compatibilité), ApiKeyService (génération/validation), auth middleware (Bearer/X-API-Key), endpoints admin (/admin/api-keys), migration script (migrate-to-db.ts), suppression saveToDisk périodique - service-login-verify: PersistentNonceCache (IndexedDB avec fallback localStorage, TTL, cleanup), export dans index - userwallet: CryptoSettingsScreen (hashAlgorithm, jsonCanonizationStrict, ecdhCurve, nonceTtlMs, timestampWindowMs), modifications LoginScreen, LoginForm, CreateIdentityScreen, ImportIdentityScreen, DataExportImportScreen, PairingDisplayScreen, RelaySettingsScreen, ServiceListScreen, MemberSelectionScreen, GlobalActionBar - features: OPTIONS_NON_IMPLENTEES.md (analyse Merkle trees, évolutions api-relay) **Pages affectées:** - api-relay: package.json, index.ts, middleware/auth.ts, services/database.ts, services/storageAdapter.ts, services/apiKeyService.ts, scripts/migrate-to-db.ts - service-login-verify: persistentNonceCache.ts, index.ts, tsconfig.json, dist/ - userwallet: App, CryptoSettingsScreen, LoginScreen, LoginForm, CreateIdentityScreen, ImportIdentityScreen, DataExportImportScreen, PairingDisplayScreen, RelaySettingsScreen, ServiceListScreen, MemberSelectionScreen, GlobalActionBar - features: OPTIONS_NON_IMPLENTEES.md - data: sync-utxos.log
52 lines
1.4 KiB
TypeScript
52 lines
1.4 KiB
TypeScript
import { useState, FormEvent } from 'react';
|
|
import { useAuth } from '../hooks/useAuth';
|
|
import { sendAuthResponse } from '../utils/iframe';
|
|
|
|
export function LoginForm(): JSX.Element {
|
|
const { keyPair, isLoading, createAuthResponse } = useAuth();
|
|
const [isAuthenticating, setIsAuthenticating] = useState(false);
|
|
|
|
const handleSubmit = (e: FormEvent<HTMLFormElement>): void => {
|
|
e.preventDefault();
|
|
void (async (): Promise<void> => {
|
|
if (keyPair === null || isLoading) {
|
|
return;
|
|
}
|
|
|
|
setIsAuthenticating(true);
|
|
try {
|
|
const response = createAuthResponse();
|
|
if (response !== null) {
|
|
sendAuthResponse(response);
|
|
} else {
|
|
console.error('Failed to create auth response');
|
|
}
|
|
} catch (error) {
|
|
console.error('Authentication error:', error);
|
|
} finally {
|
|
setIsAuthenticating(false);
|
|
}
|
|
})();
|
|
};
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div role="status" aria-live="polite" aria-busy="true">
|
|
Chargement...
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit} aria-label="Formulaire de connexion">
|
|
<button
|
|
type="submit"
|
|
disabled={isAuthenticating || keyPair === null}
|
|
aria-busy={isAuthenticating}
|
|
>
|
|
{isAuthenticating ? 'Authentification...' : 'Se connecter'}
|
|
</button>
|
|
</form>
|
|
);
|
|
}
|