Complete verification links and preserve verified login email (#60)
This commit is contained in:
1 parent
30f06c2f8f
commit
5f3b443e7b
25 files changed
+270
-32
No files matched your search
@@ -6,6 +6,8 @@ class BackendDTO {
|
||||
(jsonDecode(body) as Map<String, dynamic>)['data'] as Map<String, dynamic>,
|
||||
);
|
||||
final Map<String, dynamic> data;
|
||||
bool get verified => data['verified'] == true;
|
||||
String? get email => data['email'] as String?;
|
||||
String get error => data['error'] as String? ?? 'unavailable';
|
||||
String get userId =>
|
||||
data['userId'] as String? ??
|
||||
|
||||
@@ -6,6 +6,7 @@ class AuthDTO {
|
||||
}
|
||||
|
||||
class VerificationDTO {
|
||||
const VerificationDTO({required this.simulated});
|
||||
const VerificationDTO({required this.simulated, this.email});
|
||||
final bool simulated;
|
||||
final String? email;
|
||||
}
|
||||
@@ -5,6 +5,13 @@ import '../models/two_factor.dart';
|
||||
import '../models/verification.dart';
|
||||
|
||||
abstract final class BackendMapper {
|
||||
static VerificationResult activation(BackendDTO dto) {
|
||||
if (!dto.verified) {
|
||||
throw const VerificationException(VerificationError.internal);
|
||||
}
|
||||
return VerificationResult(isSimulated: false, verifiedEmail: dto.email);
|
||||
}
|
||||
|
||||
static AuthResult signup(BackendDTO dto) {
|
||||
if (dto.userId.isEmpty) throw const FormatException('Missing user');
|
||||
return AuthResult(userId: dto.userId, isSimulated: false);
|
||||
|
||||
@@ -9,5 +9,5 @@ abstract final class AuthMapper {
|
||||
|
||||
abstract final class VerificationMapper {
|
||||
static VerificationResult fromDTO(VerificationDTO dto) =>
|
||||
VerificationResult(isSimulated: dto.simulated);
|
||||
VerificationResult(isSimulated: dto.simulated, verifiedEmail: dto.email);
|
||||
}
|
||||
@@ -17,15 +17,22 @@ class VerificationException implements Exception {
|
||||
}
|
||||
|
||||
class VerificationResult {
|
||||
const VerificationResult({required this.isSimulated});
|
||||
const VerificationResult({required this.isSimulated, this.verifiedEmail});
|
||||
final bool isSimulated;
|
||||
final String? verifiedEmail;
|
||||
}
|
||||
|
||||
class VerificationState {
|
||||
const VerificationState(this.status, {this.isSimulated = false, this.error});
|
||||
const VerificationState(
|
||||
this.status, {
|
||||
this.isSimulated = false,
|
||||
this.error,
|
||||
this.result,
|
||||
});
|
||||
final VerificationStatus status;
|
||||
final VerificationError? error;
|
||||
final bool isSimulated;
|
||||
final VerificationResult? result;
|
||||
bool get isLoading =>
|
||||
status == VerificationStatus.sending ||
|
||||
status == VerificationStatus.checking;
|
||||
|
||||
@@ -35,7 +35,11 @@ class VerificationProvider extends ChangeNotifier {
|
||||
try {
|
||||
final result = await operation();
|
||||
if (_disposed || generation != _generation) return;
|
||||
_state = VerificationState(success, isSimulated: result.isSimulated);
|
||||
_state = VerificationState(
|
||||
success,
|
||||
isSimulated: result.isSimulated,
|
||||
result: success == VerificationStatus.verified ? result : null,
|
||||
);
|
||||
} catch (error) {
|
||||
if (_disposed || generation != _generation) return;
|
||||
final code = error is VerificationException
|
||||
|
||||
@@ -172,8 +172,10 @@ class BackendAuthServices
|
||||
|
||||
@override
|
||||
Future<VerificationResult> confirm({required String token}) async {
|
||||
await _post('verification/confirm', {'token': token}, verification: true);
|
||||
return VerificationMapper.fromDTO(const VerificationDTO(simulated: false));
|
||||
final dto = await _post('verification/confirm', {
|
||||
'token': token,
|
||||
}, verification: true);
|
||||
return BackendMapper.activation(dto);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -19,11 +19,13 @@ class DummyVerificationService implements VerificationService, SimulationInfo {
|
||||
const DummyVerificationService({
|
||||
this.delay = const Duration(milliseconds: 600),
|
||||
this.sendFailure,
|
||||
this.verifiedEmail = 'alex@example.com',
|
||||
});
|
||||
@override
|
||||
bool get isSimulated => true;
|
||||
final Duration delay;
|
||||
final VerificationError? sendFailure;
|
||||
final String verifiedEmail;
|
||||
|
||||
@override
|
||||
Future<VerificationResult> send({
|
||||
@@ -41,7 +43,7 @@ class DummyVerificationService implements VerificationService, SimulationInfo {
|
||||
switch (token) {
|
||||
case 'demo-valid':
|
||||
return VerificationMapper.fromDTO(
|
||||
const VerificationDTO(simulated: true),
|
||||
VerificationDTO(simulated: true, email: verifiedEmail),
|
||||
);
|
||||
case 'demo-expired':
|
||||
throw const VerificationException(VerificationError.expired);
|
||||
|
||||
Reference in new issue
Block a user