fix: Implement Backblaze bucket restoration on server recovery (#324)
continuous-integration/drone/push Build is passing Details

Resolves issue [320](#320).

Co-authored-by: NaiJi <naijiworld@protonmail.com>
Reviewed-on: #324
Reviewed-by: Inex Code <inex.code@selfprivacy.org>
pull/270/head^2
NaiJi ✨ 2023-09-06 00:36:49 +03:00
parent 1642cb907d
commit 82dfdf04f9
3 changed files with 76 additions and 4 deletions

View File

@ -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<BackblazeBucket?> 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<ApiConfigModel>().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: '',
applicationKey: '',
);
}
}
return bucket;
} else {
throw Exception('code: ${response.statusCode}');
}
}
@override
bool hasLogger;

View File

@ -109,17 +109,34 @@ class BackupsCubit extends ServerInstallationDependendCubit<BackupsState> {
Future<void> reuploadKey() async {
emit(state.copyWith(preventActions: true));
final BackblazeBucket? bucket = getIt<ApiConfigModel>().backblazeBucket;
BackblazeBucket? bucket = getIt<ApiConfigModel>().backblazeBucket;
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;
bucket = BackblazeBucket(
bucketId: bucket.bucketId,
bucketName: bucket.bucketName,
encryptionKey: bucket.encryptionKey,
applicationKey: password,
applicationKeyId: login,
);
await getIt<ApiConfigModel>().storeBackblazeBucket(bucket);
emit(state.copyWith(backblazeBucket: bucket));
}
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) {
@ -129,7 +146,7 @@ class BackupsCubit extends ServerInstallationDependendCubit<BackupsState> {
return;
} else {
emit(state.copyWith(preventActions: false));
getIt<NavigationService>().showSnackBar('backup.reuploaded_key');
getIt<NavigationService>().showSnackBar('backup.reuploaded_key'.tr());
await updateBackups();
}
}

View File

@ -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<ServerInstallationState> {
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<ApiConfigModel>().storeBackblazeBucket(bucket!);
} catch (e) {
print(e);
}
}
finishRecoveryProcess(backblazeCredential);
return;
}