From 2e2a34a5cf28c4d80bce3187a87cfbb302e7f4e4 Mon Sep 17 00:00:00 2001 From: NaiJi Date: Tue, 5 Sep 2023 14:42:22 -0300 Subject: [PATCH 1/5] fix: Implement Backblaze bucket restoration on server recovery --- lib/logic/api_maps/rest_maps/backblaze.dart | 38 +++++++++++++++++++ .../server_installation_cubit.dart | 17 +++++++++ 2 files changed, 55 insertions(+) diff --git a/lib/logic/api_maps/rest_maps/backblaze.dart b/lib/logic/api_maps/rest_maps/backblaze.dart index b9df76c2..867b4e8a 100644 --- a/lib/logic/api_maps/rest_maps/backblaze.dart +++ b/lib/logic/api_maps/rest_maps/backblaze.dart @@ -2,6 +2,8 @@ import 'dart:io'; import 'package:dio/dio.dart'; import 'package:selfprivacy/config/get_it_config.dart'; +import 'package:selfprivacy/logic/models/backup.dart'; +import 'package:selfprivacy/logic/models/hive/backblaze_bucket.dart'; import 'package:selfprivacy/logic/models/hive/backups_credential.dart'; import 'package:selfprivacy/logic/api_maps/generic_result.dart'; import 'package:selfprivacy/logic/api_maps/rest_maps/rest_api_map.dart'; @@ -179,6 +181,42 @@ class BackblazeApi extends RestApiMap { } } + Future fetchBucket( + final BackupsCredential credentials, + final BackupConfiguration configuration, + ) async { + BackblazeBucket? bucket; + final BackblazeApiAuth auth = await getAuthorizationToken(); + final Dio client = await getClient(); + client.options.baseUrl = auth.apiUrl; + final Response response = await client.get( + '$apiPrefix/b2_list_buckets', + queryParameters: { + 'accountId': getIt().backblazeCredential!.keyId, + }, + options: Options( + headers: {'Authorization': auth.authorizationToken}, + ), + ); + close(client); + if (response.statusCode == HttpStatus.ok) { + for (final rawBucket in response.data['buckets']) { + if (rawBucket['bucketId'] == configuration.locationId) { + bucket = BackblazeBucket( + bucketId: rawBucket['bucketId'], + bucketName: rawBucket['bucketName'], + encryptionKey: configuration.encryptionKey, + applicationKeyId: credentials.keyId, + applicationKey: '', + ); + } + } + return bucket; + } else { + throw Exception('code: ${response.statusCode}'); + } + } + @override bool hasLogger; diff --git a/lib/logic/cubit/server_installation/server_installation_cubit.dart b/lib/logic/cubit/server_installation/server_installation_cubit.dart index a10532ef..195c5ded 100644 --- a/lib/logic/cubit/server_installation/server_installation_cubit.dart +++ b/lib/logic/cubit/server_installation/server_installation_cubit.dart @@ -5,7 +5,9 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:equatable/equatable.dart'; import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server_api.dart'; +import 'package:selfprivacy/logic/api_maps/rest_maps/backblaze.dart'; import 'package:selfprivacy/logic/api_maps/tls_options.dart'; +import 'package:selfprivacy/logic/models/hive/backblaze_bucket.dart'; import 'package:selfprivacy/logic/models/hive/backups_credential.dart'; import 'package:selfprivacy/logic/models/callback_dialogue_branching.dart'; import 'package:selfprivacy/logic/models/hive/server_details.dart'; @@ -199,8 +201,23 @@ class ServerInstallationCubit extends Cubit { applicationKey: applicationKey, provider: BackupsProviderType.backblaze, ); + final BackblazeBucket? bucket; await repository.saveBackblazeKey(backblazeCredential); if (state is ServerInstallationRecovery) { + final configuration = await ServerApi( + customToken: + (state as ServerInstallationRecovery).serverDetails!.apiToken, + isWithToken: true, + ).getBackupsConfiguration(); + if (configuration != null) { + try { + bucket = await BackblazeApi() + .fetchBucket(backblazeCredential, configuration); + await getIt().storeBackblazeBucket(bucket!); + } catch (e) { + print(e); + } + } finishRecoveryProcess(backblazeCredential); return; } -- 2.42.0 From d7d84692c3755b1ff5f49ef1a0f85f746c807ccc Mon Sep 17 00:00:00 2001 From: NaiJi Date: Tue, 5 Sep 2023 15:02:48 -0300 Subject: [PATCH 2/5] fix: Force applicationKeyId to empty string on restoration --- lib/logic/api_maps/rest_maps/backblaze.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/logic/api_maps/rest_maps/backblaze.dart b/lib/logic/api_maps/rest_maps/backblaze.dart index 867b4e8a..d908cd26 100644 --- a/lib/logic/api_maps/rest_maps/backblaze.dart +++ b/lib/logic/api_maps/rest_maps/backblaze.dart @@ -206,7 +206,7 @@ class BackblazeApi extends RestApiMap { bucketId: rawBucket['bucketId'], bucketName: rawBucket['bucketName'], encryptionKey: configuration.encryptionKey, - applicationKeyId: credentials.keyId, + applicationKeyId: '', applicationKey: '', ); } -- 2.42.0 From 45259135437af46eb6b57bcdb515b924c982ccf4 Mon Sep 17 00:00:00 2001 From: NaiJi Date: Tue, 5 Sep 2023 15:03:40 -0300 Subject: [PATCH 3/5] fix: Implement applicationKey regeneretion on reupload key after restoration --- lib/logic/cubit/backups/backups_cubit.dart | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/logic/cubit/backups/backups_cubit.dart b/lib/logic/cubit/backups/backups_cubit.dart index 938b606a..69cea9a5 100644 --- a/lib/logic/cubit/backups/backups_cubit.dart +++ b/lib/logic/cubit/backups/backups_cubit.dart @@ -113,13 +113,21 @@ class BackupsCubit extends ServerInstallationDependendCubit { if (bucket == null) { emit(state.copyWith(isInitialized: false)); } else { + String login = bucket.applicationKeyId; + String password = bucket.applicationKey; + if (login.isEmpty || password.isEmpty) { + final BackblazeApplicationKey key = + await backblaze.createKey(bucket.bucketId); + login = key.applicationKeyId; + password = key.applicationKey; + } final GenericResult result = await api.initializeRepository( InitializeRepositoryInput( provider: BackupsProviderType.backblaze, locationId: bucket.bucketId, locationName: bucket.bucketName, - login: bucket.applicationKeyId, - password: bucket.applicationKey, + login: login, + password: password, ), ); if (result.success == false) { -- 2.42.0 From 7aebab4881111d44337388cae8ebc3fb25a12e81 Mon Sep 17 00:00:00 2001 From: NaiJi Date: Tue, 5 Sep 2023 15:20:25 -0300 Subject: [PATCH 4/5] fix: Implement backblaze bucket saving after regenerating application key --- lib/logic/cubit/backups/backups_cubit.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/logic/cubit/backups/backups_cubit.dart b/lib/logic/cubit/backups/backups_cubit.dart index 69cea9a5..5eb9678e 100644 --- a/lib/logic/cubit/backups/backups_cubit.dart +++ b/lib/logic/cubit/backups/backups_cubit.dart @@ -120,6 +120,15 @@ class BackupsCubit extends ServerInstallationDependendCubit { await backblaze.createKey(bucket.bucketId); login = key.applicationKeyId; password = key.applicationKey; + await getIt().storeBackblazeBucket( + BackblazeBucket( + bucketId: bucket.bucketId, + bucketName: bucket.bucketName, + encryptionKey: bucket.encryptionKey, + applicationKey: password, + applicationKeyId: login, + ), + ); } final GenericResult result = await api.initializeRepository( InitializeRepositoryInput( -- 2.42.0 From 39e264bb42eca0f2edf15ea238c86176f09daf36 Mon Sep 17 00:00:00 2001 From: NaiJi Date: Tue, 5 Sep 2023 16:14:16 -0300 Subject: [PATCH 5/5] fix: Emit new bucket to backups state after force reuploading key --- lib/logic/cubit/backups/backups_cubit.dart | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/logic/cubit/backups/backups_cubit.dart b/lib/logic/cubit/backups/backups_cubit.dart index 5eb9678e..89470656 100644 --- a/lib/logic/cubit/backups/backups_cubit.dart +++ b/lib/logic/cubit/backups/backups_cubit.dart @@ -109,7 +109,7 @@ class BackupsCubit extends ServerInstallationDependendCubit { Future reuploadKey() async { emit(state.copyWith(preventActions: true)); - final BackblazeBucket? bucket = getIt().backblazeBucket; + BackblazeBucket? bucket = getIt().backblazeBucket; if (bucket == null) { emit(state.copyWith(isInitialized: false)); } else { @@ -120,15 +120,15 @@ class BackupsCubit extends ServerInstallationDependendCubit { await backblaze.createKey(bucket.bucketId); login = key.applicationKeyId; password = key.applicationKey; - await getIt().storeBackblazeBucket( - BackblazeBucket( - bucketId: bucket.bucketId, - bucketName: bucket.bucketName, - encryptionKey: bucket.encryptionKey, - applicationKey: password, - applicationKeyId: login, - ), + bucket = BackblazeBucket( + bucketId: bucket.bucketId, + bucketName: bucket.bucketName, + encryptionKey: bucket.encryptionKey, + applicationKey: password, + applicationKeyId: login, ); + await getIt().storeBackblazeBucket(bucket); + emit(state.copyWith(backblazeBucket: bucket)); } final GenericResult result = await api.initializeRepository( InitializeRepositoryInput( @@ -146,7 +146,7 @@ class BackupsCubit extends ServerInstallationDependendCubit { return; } else { emit(state.copyWith(preventActions: false)); - getIt().showSnackBar('backup.reuploaded_key'); + getIt().showSnackBar('backup.reuploaded_key'.tr()); await updateBackups(); } } -- 2.42.0