From 5c61bd50da6137fd10fef79f438ab978c6035a43 Mon Sep 17 00:00:00 2001 From: phuoc Date: Tue, 29 Oct 2024 15:07:57 +0700 Subject: [PATCH] store didRegisterPasskey android on blockStore Signed-off-by: phuoc --- .../autonomy_flutter/BackupDartPlugin.kt | 54 +++++++++++++++++++ lib/screen/onboarding_page.dart | 4 +- .../forget_exist/forget_exist_bloc.dart | 3 +- lib/service/configuration_service.dart | 14 ----- lib/service/passkey_service.dart | 46 ++-------------- lib/util/user_account_channel.dart | 12 +++++ 6 files changed, 76 insertions(+), 57 deletions(-) diff --git a/android/app/src/main/kotlin/com/bitmark/autonomy_flutter/BackupDartPlugin.kt b/android/app/src/main/kotlin/com/bitmark/autonomy_flutter/BackupDartPlugin.kt index a8a4cb059..3bcba670e 100644 --- a/android/app/src/main/kotlin/com/bitmark/autonomy_flutter/BackupDartPlugin.kt +++ b/android/app/src/main/kotlin/com/bitmark/autonomy_flutter/BackupDartPlugin.kt @@ -33,6 +33,7 @@ class BackupDartPlugin : MethodChannel.MethodCallHandler { private lateinit var disposables: CompositeDisposable private lateinit var client: BlockstoreClient private val primaryAddressStoreKey = "primary_address" + private val didRegisterPasskeys = "did_register_passkeys" fun createChannels(@NonNull flutterEngine: FlutterEngine, @NonNull context: Context) { this.context = context @@ -51,6 +52,8 @@ class BackupDartPlugin : MethodChannel.MethodCallHandler { "getPrimaryAddress" -> getPrimaryAddress(call, result) "clearPrimaryAddress" -> clearPrimaryAddress(call, result) "deleteKeys" -> deleteKeys(call, result) + "setDidRegisterPasskey" -> setDidRegisterPasskey(call, result) + "didRegisterPasskey" -> didRegisterPasskey(call, result) else -> { result.notImplemented() } @@ -246,6 +249,57 @@ class BackupDartPlugin : MethodChannel.MethodCallHandler { } } + private fun setDidRegisterPasskey(call: MethodCall, result: MethodChannel.Result) { + val data: Boolean = call.argument("data") ?: false + + val storeBytesBuilder = StoreBytesData.Builder() + .setKey(didRegisterPasskeys) + .setBytes(data.toString().toByteArray(Charsets.UTF_8)) + + client.storeBytes(storeBytesBuilder.build()) + .addOnSuccessListener { + + Log.e("setDidRegisterPasskey", data.toString()); + result.success(true) + } + .addOnFailureListener { e -> + Log.e("setDidRegisterPasskey", e.message ?: "") + result.success(false) + } + } + + private fun didRegisterPasskey(call: MethodCall, result: MethodChannel.Result) { + val request = RetrieveBytesRequest.Builder() + .setKeys(listOf(didRegisterPasskeys)) // Specify the key + .build() + client.retrieveBytes(request) + .addOnSuccessListener { + try { // Retrieve bytes using the key + val dataMap = it.blockstoreDataMap[didRegisterPasskeys] + if (dataMap != null) { + val bytes = dataMap.bytes + val resultString = bytes.toString(Charsets.UTF_8) + Log.d("didRegisterPasskey", resultString) + + + result.success(resultString.toBoolean()) + } else { + Log.e("didRegisterPasskey", "No data found for the key") + result.success(false) + } + } catch (e: Exception) { + Log.e("didRegisterPasskey", e.message ?: "Error decoding data") + //No primary address found + result.success(false) + } + } + .addOnFailureListener { + //Block store not available + result.error("didRegisterPasskey Block store error", it.message, it) + } + } + + private fun clearPrimaryAddress(call: MethodCall, result: MethodChannel.Result) { val retrieveRequest = DeleteBytesRequest.Builder() .setKeys(listOf(primaryAddressStoreKey)) diff --git a/lib/screen/onboarding_page.dart b/lib/screen/onboarding_page.dart index de71ff34b..e0b212781 100644 --- a/lib/screen/onboarding_page.dart +++ b/lib/screen/onboarding_page.dart @@ -27,6 +27,7 @@ import 'package:autonomy_flutter/util/metric_helper.dart'; import 'package:autonomy_flutter/util/notification_util.dart'; import 'package:autonomy_flutter/util/style.dart'; import 'package:autonomy_flutter/util/ui_helper.dart'; +import 'package:autonomy_flutter/util/user_account_channel.dart'; import 'package:autonomy_flutter/view/back_appbar.dart'; import 'package:autonomy_flutter/view/primary_button.dart'; import 'package:autonomy_flutter/view/responsive.dart'; @@ -55,6 +56,7 @@ class _OnboardingPageState extends State bool _loadingAnimation = true; final _passkeyService = injector.get(); + final _userAccountChannel = injector.get(); final _authService = injector.get(); final _onboardingLogo = Semantics( @@ -174,7 +176,7 @@ class _OnboardingPageState extends State }); } else { log.info('Passkey is supported. Authenticate with passkey'); - final didRegisterPasskey = await _passkeyService.didRegisterPasskey(); + final didRegisterPasskey = await _userAccountChannel.didRegisterPasskey(); if (mounted) { setState(() { _loadingAnimation = false; diff --git a/lib/screen/settings/forget_exist/forget_exist_bloc.dart b/lib/screen/settings/forget_exist/forget_exist_bloc.dart index 00f47a3f5..da1d06902 100644 --- a/lib/screen/settings/forget_exist/forget_exist_bloc.dart +++ b/lib/screen/settings/forget_exist/forget_exist_bloc.dart @@ -28,6 +28,7 @@ import 'package:autonomy_flutter/service/passkey_service.dart'; import 'package:autonomy_flutter/shared.dart'; import 'package:autonomy_flutter/util/log.dart'; import 'package:autonomy_flutter/util/notification_util.dart'; +import 'package:autonomy_flutter/util/user_account_channel.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:nft_collection/database/nft_collection_database.dart'; @@ -69,7 +70,7 @@ class ForgetExistBloc extends AuBloc { await _cloudDatabase.removeAll(); await _appDatabase.removeAll(); await _nftCollectionDatabase.removeAll(); - await injector().setDidRegisterPasskey(false); + await injector().setDidRegisterPasskey(false); await _configurationService.removeAll(); await injector().emptyCache(); await DefaultCacheManager().emptyCache(); diff --git a/lib/service/configuration_service.dart b/lib/service/configuration_service.dart index 1425c3e09..25ce3ba78 100644 --- a/lib/service/configuration_service.dart +++ b/lib/service/configuration_service.dart @@ -24,10 +24,6 @@ import 'package:uuid/uuid.dart'; //ignore_for_file: constant_identifier_names abstract class ConfigurationService { - bool didRegisterPasskeyAndroid(); - - Future setDidRegisterPasskeyAndroid(bool value); - bool didMigrateToAccountSetting(); Future setMigrateToAccountSetting(bool value); @@ -210,7 +206,6 @@ abstract class ConfigurationService { } class ConfigurationServiceImpl implements ConfigurationService { - static const String keyDidRegisterPasskey = 'did_register_passkey'; static const String keyDidMigrateToAccountSetting = 'did_migrate_to_account_setting'; static const String keyDidShowLiveWithArt = 'did_show_live_with_art'; @@ -934,15 +929,6 @@ class ConfigurationServiceImpl implements ConfigurationService { await _preferences.setString( KEY_ANNOUNCEMENT_TO_ISSUE_MAP, jsonEncode(mapJson)); } - - @override - bool didRegisterPasskeyAndroid() => - _preferences.getBool(keyDidRegisterPasskey) ?? false; - - @override - Future setDidRegisterPasskeyAndroid(bool value) async { - await _preferences.setBool(keyDidRegisterPasskey, value); - } } enum ConflictAction { diff --git a/lib/service/passkey_service.dart b/lib/service/passkey_service.dart index 9bbef375c..b964230e3 100644 --- a/lib/service/passkey_service.dart +++ b/lib/service/passkey_service.dart @@ -3,10 +3,9 @@ import 'dart:io'; import 'package:autonomy_flutter/gateway/user_api.dart'; import 'package:autonomy_flutter/service/address_service.dart'; import 'package:autonomy_flutter/service/auth_service.dart'; -import 'package:autonomy_flutter/service/configuration_service.dart'; import 'package:autonomy_flutter/util/passkey_utils.dart'; +import 'package:autonomy_flutter/util/user_account_channel.dart'; import 'package:device_info_plus/device_info_plus.dart'; -import 'package:flutter/services.dart'; import 'package:passkeys/authenticator.dart'; import 'package:passkeys/types.dart'; @@ -21,10 +20,6 @@ abstract class PasskeyService { Future registerFinalize(); - Future didRegisterPasskey(); - - Future setDidRegisterPasskey(bool value); - static String authenticationType = 'public-key'; } @@ -35,22 +30,16 @@ class PasskeyServiceImpl implements PasskeyService { String? _passkeyUserId; final UserApi _userApi; - final ConfigurationService _configurationService; + final UserAccountChannel _userAccountChannel; final AddressService _addressService; final AuthService _authService; - late final MethodChannel _iosMigrationChannel; - PasskeyServiceImpl( this._userApi, - this._configurationService, + this._userAccountChannel, this._addressService, this._authService, - ) { - if (Platform.isIOS) { - _iosMigrationChannel = const MethodChannel('migration_util'); - } - } + ); /* static final AuthenticatorSelectionType _defaultAuthenticatorSelection = @@ -163,34 +152,9 @@ class PasskeyServiceImpl implements PasskeyService { 'credentialCreationResponse': _registerResponse!.toCredentialCreationResponseJson(), }); - await setDidRegisterPasskey(true); + await _userAccountChannel.setDidRegisterPasskey(true); _authService.setAuthToken(response); } - - @override - Future didRegisterPasskey() async { - if (Platform.isAndroid) { - return _configurationService.didRegisterPasskeyAndroid(); - } - final didRegister = - await _iosMigrationChannel.invokeMethod('didRegisterPasskey', {}); - return didRegister; - } - - @override - Future setDidRegisterPasskey(bool value) async { - if (Platform.isAndroid) { - // for Android device, passkey is stored in Google Password Manager, - // so it is not synced - await _configurationService.setDidRegisterPasskeyAndroid(value); - return true; - } - final didRegister = - await _iosMigrationChannel.invokeMethod('setDidRegisterPasskey', { - 'data': value, - }); - return didRegister; - } } extension RegisterResponseTypeExt on RegisterResponseType { diff --git a/lib/util/user_account_channel.dart b/lib/util/user_account_channel.dart index ff53c36f0..e23d86b23 100644 --- a/lib/util/user_account_channel.dart +++ b/lib/util/user_account_channel.dart @@ -51,6 +51,18 @@ class UserAccountChannel { return false; } } + + Future didRegisterPasskey() async { + final didRegister = await _channel.invokeMethod('didRegisterPasskey', {}); + return didRegister; + } + + Future setDidRegisterPasskey(bool value) async { + final didRegister = await _channel.invokeMethod('setDidRegisterPasskey', { + 'data': value, + }); + return didRegister; + } } class AddressInfo {