diff --git a/mobile/lib/models/account/two_factor.dart b/mobile/lib/models/account/two_factor.dart index b43f88a0c..6a18f4277 100644 --- a/mobile/lib/models/account/two_factor.dart +++ b/mobile/lib/models/account/two_factor.dart @@ -1 +1,13 @@ -enum TwoFactorType { totp, passKey } +enum TwoFactorType { totp, passkey } + +// ToString for TwoFactorType +String twoFactorTypeToString(TwoFactorType type) { + switch (type) { + case TwoFactorType.totp: + return "totp"; + case TwoFactorType.passkey: + return "passkey"; + default: + return type.name; + } +} diff --git a/mobile/lib/services/user_service.dart b/mobile/lib/services/user_service.dart index 0ca57992d..6d0408855 100644 --- a/mobile/lib/services/user_service.dart +++ b/mobile/lib/services/user_service.dart @@ -820,6 +820,7 @@ class UserService { _config.getHttpEndpoint() + "/users/two-factor/recover", queryParameters: { "sessionID": sessionID, + "twoFactorType": twoFactorTypeToString(type), }, ); if (response.statusCode == 200) { @@ -839,6 +840,7 @@ class UserService { ); } } on DioError catch (e) { + await dialog.hide(); _logger.severe(e); if (e.response != null && e.response!.statusCode == 404) { showToast(context, S.of(context).sessionExpired); @@ -860,6 +862,7 @@ class UserService { ); } } catch (e) { + await dialog.hide(); _logger.severe(e); // ignore: unawaited_futures showErrorDialog( @@ -913,7 +916,8 @@ class UserService { _config.getHttpEndpoint() + "/users/two-factor/remove", data: { "sessionID": sessionID, - "secret": secret, + "secret": utf8.decode(base64.decode(secret)), + "twoFactorType": twoFactorTypeToString(type), }, ); if (response.statusCode == 200) { @@ -933,7 +937,8 @@ class UserService { ); } } on DioError catch (e) { - _logger.severe(e); + await dialog.hide(); + _logger.severe("error during recovery", e); if (e.response != null && e.response!.statusCode == 404) { showToast(context, "Session expired"); // ignore: unawaited_futures @@ -954,7 +959,9 @@ class UserService { ); } } catch (e) { - _logger.severe(e); + await dialog.hide(); + _logger.severe('unexpcted error during recovery', e); + // ignore: unawaited_futures showErrorDialog( context, diff --git a/mobile/lib/ui/account/passkey_page.dart b/mobile/lib/ui/account/passkey_page.dart index ad838c868..d24ae8ba7 100644 --- a/mobile/lib/ui/account/passkey_page.dart +++ b/mobile/lib/ui/account/passkey_page.dart @@ -5,6 +5,7 @@ import 'package:logging/logging.dart'; import 'package:photos/core/configuration.dart'; import 'package:photos/ente_theme_data.dart'; import "package:photos/generated/l10n.dart"; +import "package:photos/models/account/two_factor.dart"; import 'package:photos/services/user_service.dart'; import "package:photos/utils/dialog_util.dart"; import 'package:uni_links/uni_links.dart'; @@ -119,6 +120,29 @@ class _PasskeyPageState extends State { child: Text(S.of(context).launchPasskeyUrlAgain), ), ), + const Padding(padding: EdgeInsets.all(30)), + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + UserService.instance.recoverTwoFactor( + context, + widget.sessionID, + TwoFactorType.passkey, + ); + }, + child: Container( + padding: const EdgeInsets.all(10), + child: Center( + child: Text( + S.of(context).lostDevice, + style: const TextStyle( + decoration: TextDecoration.underline, + fontSize: 12, + ), + ), + ), + ), + ), ], ), );