selfprivacy.org.app/lib/logic/api_maps/rest_maps/backblaze.dart

184 lines
5.5 KiB
Dart
Raw Normal View History

2021-02-03 21:51:07 +02:00
import 'dart:io';
2022-02-16 09:28:29 +02:00
2021-02-03 21:51:07 +02:00
import 'package:dio/dio.dart';
2021-03-26 01:30:34 +02:00
import 'package:selfprivacy/config/get_it_config.dart';
import 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
2022-07-12 15:54:16 +03:00
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
import 'package:selfprivacy/logic/models/hive/backblaze_credential.dart';
2021-12-06 20:31:19 +02:00
export 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
2021-12-06 20:31:19 +02:00
class BackblazeApiAuth {
BackblazeApiAuth({required this.authorizationToken, required this.apiUrl});
final String authorizationToken;
final String apiUrl;
}
class BackblazeApplicationKey {
BackblazeApplicationKey({
required this.applicationKeyId,
required this.applicationKey,
});
2021-12-06 20:31:19 +02:00
final String applicationKeyId;
final String applicationKey;
}
2021-02-03 21:51:07 +02:00
2021-03-26 01:30:34 +02:00
class BackblazeApi extends ApiMap {
2022-02-16 09:28:29 +02:00
BackblazeApi({this.hasLogger = false, this.isWithToken = true});
2021-03-26 01:30:34 +02:00
2022-05-24 21:55:39 +03:00
@override
2021-03-26 01:30:34 +02:00
BaseOptions get options {
2022-06-05 22:36:32 +03:00
final BaseOptions options = BaseOptions(baseUrl: rootAddress);
2021-03-26 01:30:34 +02:00
if (isWithToken) {
final BackblazeCredential? backblazeCredential =
getIt<ApiConfigModel>().backblazeCredential;
2022-06-05 22:36:32 +03:00
final String token = backblazeCredential!.applicationKey;
2021-03-26 01:30:34 +02:00
options.headers = {'Authorization': 'Basic $token'};
}
if (validateStatus != null) {
options.validateStatus = validateStatus!;
2021-02-03 21:51:07 +02:00
}
2021-03-26 01:30:34 +02:00
return options;
2021-02-03 21:51:07 +02:00
}
@override
2021-03-26 01:30:34 +02:00
String rootAddress = 'https://api.backblazeb2.com/b2api/v2/';
2021-02-03 21:51:07 +02:00
2021-12-06 20:31:19 +02:00
String apiPrefix = '/b2api/v2';
Future<BackblazeApiAuth> getAuthorizationToken() async {
2022-06-05 22:36:32 +03:00
final Dio client = await getClient();
final BackblazeCredential? backblazeCredential =
getIt<ApiConfigModel>().backblazeCredential;
2021-12-06 20:31:19 +02:00
if (backblazeCredential == null) {
throw Exception('Backblaze credential is null');
}
final String encodedApiKey = encodedBackblazeKey(
backblazeCredential.keyId,
backblazeCredential.applicationKey,
);
2022-06-05 22:36:32 +03:00
final Response response = await client.get(
2021-12-06 20:31:19 +02:00
'b2_authorize_account',
options: Options(headers: {'Authorization': 'Basic $encodedApiKey'}),
);
if (response.statusCode != 200) {
throw Exception('code: ${response.statusCode}');
}
return BackblazeApiAuth(
authorizationToken: response.data['authorizationToken'],
apiUrl: response.data['apiUrl'],
);
}
Future<APIGenericResult<bool>> isApiTokenValid(
final String encodedApiKey,
) async {
2022-06-05 22:36:32 +03:00
final Dio client = await getClient();
bool isTokenValid = false;
try {
final Response response = await client.get(
'b2_authorize_account',
options: Options(
followRedirects: false,
validateStatus: (final status) =>
status != null && (status >= 200 || status == 401),
headers: {'Authorization': 'Basic $encodedApiKey'},
),
);
if (response.statusCode == HttpStatus.ok) {
isTokenValid =
response.data['allowed']['capabilities'].contains('listBuckets');
} else if (response.statusCode == HttpStatus.unauthorized) {
isTokenValid = false;
} else {
throw Exception('code: ${response.statusCode}');
2021-12-06 20:31:19 +02:00
}
} on DioError catch (e) {
print(e);
return APIGenericResult(
data: false,
success: false,
message: e.toString(),
);
} finally {
close(client);
2021-02-03 21:51:07 +02:00
}
return APIGenericResult(
data: isTokenValid,
success: true,
);
2021-02-03 21:51:07 +02:00
}
2021-03-26 01:30:34 +02:00
2021-12-06 20:31:19 +02:00
// Create bucket
2022-06-05 22:36:32 +03:00
Future<String> createBucket(final String bucketName) async {
final BackblazeApiAuth auth = await getAuthorizationToken();
final BackblazeCredential? backblazeCredential =
getIt<ApiConfigModel>().backblazeCredential;
2022-06-05 22:36:32 +03:00
final Dio client = await getClient();
2021-12-06 20:31:19 +02:00
client.options.baseUrl = auth.apiUrl;
2022-06-05 22:36:32 +03:00
final Response response = await client.post(
2021-12-06 20:31:19 +02:00
'$apiPrefix/b2_create_bucket',
data: {
'accountId': backblazeCredential!.keyId,
'bucketName': bucketName,
'bucketType': 'allPrivate',
'lifecycleRules': [
{
2022-05-24 21:55:39 +03:00
'daysFromHidingToDeleting': 30,
'daysFromUploadingToHiding': null,
'fileNamePrefix': ''
2021-12-06 20:31:19 +02:00
}
],
},
options: Options(
headers: {'Authorization': auth.authorizationToken},
),
);
close(client);
if (response.statusCode == HttpStatus.ok) {
return response.data['bucketId'];
} else {
throw Exception('code: ${response.statusCode}');
}
}
// Create a limited capability key with access to the given bucket
2022-06-05 22:36:32 +03:00
Future<BackblazeApplicationKey> createKey(final String bucketId) async {
final BackblazeApiAuth auth = await getAuthorizationToken();
final Dio client = await getClient();
2021-12-06 20:31:19 +02:00
client.options.baseUrl = auth.apiUrl;
2022-06-05 22:36:32 +03:00
final Response response = await client.post(
2021-12-06 20:31:19 +02:00
'$apiPrefix/b2_create_key',
data: {
'accountId': getIt<ApiConfigModel>().backblazeCredential!.keyId,
'bucketId': bucketId,
'capabilities': ['listBuckets', 'listFiles', 'readFiles', 'writeFiles'],
'keyName': 'selfprivacy-restricted-server-key',
},
options: Options(
headers: {'Authorization': auth.authorizationToken},
),
);
close(client);
if (response.statusCode == HttpStatus.ok) {
return BackblazeApplicationKey(
applicationKeyId: response.data['applicationKeyId'],
applicationKey: response.data['applicationKey'],
);
2021-12-06 20:31:19 +02:00
} else {
throw Exception('code: ${response.statusCode}');
}
}
2021-03-26 01:30:34 +02:00
@override
2022-02-16 09:28:29 +02:00
bool hasLogger;
2021-03-26 01:30:34 +02:00
@override
bool isWithToken;
}