117 lines
3.4 KiB
Dart
117 lines
3.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import 'package:go_router/go_router.dart';
|
|
|
|
import 'package:sxchnge_analytics/sxchnge_analytics.dart';
|
|
|
|
import 'package:sxchnge_auth/sxchnge_auth.dart';
|
|
|
|
import '../generated/i18n/app_localizations.dart';
|
|
|
|
class FactorRouteRequest {
|
|
const FactorRouteRequest(this.provider, this.summary);
|
|
final TwoFactorProvider provider;
|
|
final Widget? summary;
|
|
}
|
|
|
|
Future<FactorGrant?> verifyFactor(
|
|
BuildContext context, {
|
|
required FactorChallenge challenge,
|
|
required TwoFactorService service,
|
|
required JourneyRecorder recorder,
|
|
required JourneyKind journey,
|
|
Widget? summary,
|
|
}) async {
|
|
final provider = TwoFactorProvider(
|
|
service,
|
|
challenge,
|
|
recorder: recorder,
|
|
journey: journey,
|
|
);
|
|
FactorGrant? result;
|
|
try {
|
|
result = await context.push<FactorGrant>(
|
|
'/two-factor',
|
|
extra: FactorRouteRequest(provider, summary),
|
|
);
|
|
return result;
|
|
} finally {
|
|
if (result == null) {
|
|
final step = recorder.begin(
|
|
journey,
|
|
JourneyStep.factorVerification,
|
|
simulated: service.isSimulated,
|
|
);
|
|
recorder.finish(step, cancelled: true, simulated: service.isSimulated);
|
|
}
|
|
provider.dispose();
|
|
}
|
|
}
|
|
|
|
String factorErrorText(AppLocalizations l, FactorError error) =>
|
|
switch (error) {
|
|
FactorError.invalid => l.factorInvalid,
|
|
FactorError.expired => l.factorExpired,
|
|
FactorError.locked => l.factorLocked,
|
|
FactorError.cooldown => l.factorWait,
|
|
FactorError.required => l.factorRequired,
|
|
FactorError.unavailable => l.factorUnavailable,
|
|
};
|
|
|
|
class FactorRoute extends StatefulWidget {
|
|
const FactorRoute({super.key, required this.request});
|
|
final FactorRouteRequest request;
|
|
@override
|
|
State<FactorRoute> createState() => _FactorRouteState();
|
|
}
|
|
|
|
class _FactorRouteState extends State<FactorRoute> {
|
|
FactorRouteRequest get request => widget.request;
|
|
@override
|
|
void dispose() {
|
|
request.provider.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final l = AppLocalizations.of(context)!;
|
|
final purpose = request.provider.challenge.purpose;
|
|
final purposeText = switch (purpose) {
|
|
FactorPurpose.login => l.factorLogin,
|
|
FactorPurpose.enable => l.factorEnableHelp,
|
|
FactorPurpose.disable => l.factorDisableHelp,
|
|
_ => l.factorMoney,
|
|
};
|
|
final methodText = request.provider.challenge.method == FactorMethod.email
|
|
? l.factorEmail
|
|
: l.factorAuthenticator;
|
|
return TwoFactorPage(
|
|
provider: request.provider,
|
|
summary: request.summary,
|
|
labels: TwoFactorLabels(
|
|
title: l.factorTitle,
|
|
description: '$purposeText $methodText',
|
|
code: l.factorCode,
|
|
confirm: l.factorConfirm,
|
|
cancel: l.wClose,
|
|
resend: l.factorResend,
|
|
expired: request.provider.challenge.method == FactorMethod.email
|
|
? l.factorExpired
|
|
: l.factorAppExpired,
|
|
help: request.provider.challenge.method == FactorMethod.email
|
|
? l.factorHelp
|
|
: l.factorAppHelp,
|
|
errorText: (error) =>
|
|
error == FactorError.expired &&
|
|
request.provider.challenge.method == FactorMethod.authenticator
|
|
? l.factorAppExpired
|
|
: factorErrorText(l, error),
|
|
cooldownText: (seconds) => l.factorCooldown(seconds),
|
|
),
|
|
onVerified: (grant) => context.pop(grant),
|
|
onCancel: () => context.pop(),
|
|
);
|
|
}
|
|
}
|