feat(front): implémenter la page create-password du ticket #118
Ajoute le flux frontend de création initiale du mot de passe via token email (route /create-password, vérification de token et soumission /auth/create-password), avec redirection login en succès et gestion neutre des liens invalides/expirés. Made-with: Cursor
This commit is contained in:
@@ -44,6 +44,8 @@ class ApiConfig {
|
||||
static const String refreshToken = '/auth/refresh';
|
||||
static const String authMe = '/auth/me';
|
||||
static const String changePasswordRequired = '/auth/change-password-required';
|
||||
static const String verifyCreatePasswordToken = '/auth/verify-token';
|
||||
static const String createPassword = '/auth/create-password';
|
||||
|
||||
// Users endpoints
|
||||
static const String users = '/users';
|
||||
|
||||
@@ -131,6 +131,61 @@ class AuthService {
|
||||
}
|
||||
}
|
||||
|
||||
/// Vérifie qu'un token de création de mot de passe est encore valide.
|
||||
/// Retourne `true` si l'API renvoie 200 ; `false` si 404.
|
||||
static Future<bool> verifyCreatePasswordToken(String token) async {
|
||||
final cleaned = token.trim();
|
||||
if (cleaned.isEmpty) return false;
|
||||
try {
|
||||
final uri = Uri.parse(
|
||||
'${ApiConfig.baseUrl}${ApiConfig.verifyCreatePasswordToken}?token=${Uri.encodeQueryComponent(cleaned)}',
|
||||
);
|
||||
final response = await http.get(uri, headers: ApiConfig.headers);
|
||||
if (response.statusCode == 200) return true;
|
||||
if (response.statusCode == 404) return false;
|
||||
final decoded = _tryDecodeJsonMap(response.body);
|
||||
throw Exception(_extractErrorMessage(decoded, response.statusCode));
|
||||
} on http.ClientException {
|
||||
throw Exception(
|
||||
'Connexion à ${ApiConfig.baseUrl} impossible. Vérifiez votre réseau puis réessayez.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Crée le mot de passe initial via token email.
|
||||
static Future<void> createPasswordWithToken({
|
||||
required String token,
|
||||
required String password,
|
||||
required String passwordConfirmation,
|
||||
}) async {
|
||||
final cleaned = token.trim();
|
||||
if (cleaned.isEmpty) {
|
||||
throw Exception('Lien invalide ou expiré.');
|
||||
}
|
||||
late final http.Response response;
|
||||
try {
|
||||
response = await http.post(
|
||||
Uri.parse('${ApiConfig.baseUrl}${ApiConfig.createPassword}'),
|
||||
headers: ApiConfig.headers,
|
||||
body: jsonEncode({
|
||||
'token': cleaned,
|
||||
'password': password,
|
||||
'password_confirmation': passwordConfirmation,
|
||||
}),
|
||||
);
|
||||
} on http.ClientException {
|
||||
throw Exception(
|
||||
'Connexion à ${ApiConfig.baseUrl} impossible. Vérifiez votre réseau puis réessayez.',
|
||||
);
|
||||
}
|
||||
|
||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
return;
|
||||
}
|
||||
final decoded = _tryDecodeJsonMap(response.body);
|
||||
throw Exception(_extractErrorMessage(decoded, response.statusCode));
|
||||
}
|
||||
|
||||
/// Déconnexion de l'utilisateur
|
||||
static Future<void> logout() async {
|
||||
await TokenService.clearAll();
|
||||
|
||||
Reference in New Issue
Block a user