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

165 lines
4.9 KiB
Dart
Raw Normal View History

2021-02-03 19:51:07 +00:00
import 'dart:io';
2022-02-16 07:28:29 +00:00
2021-02-03 19:51:07 +00:00
import 'package:dio/dio.dart';
2021-03-25 23:30:34 +00:00
import 'package:selfprivacy/config/get_it_config.dart';
2021-02-03 19:51:07 +00:00
import 'package:selfprivacy/logic/api_maps/api_map.dart';
import 'package:selfprivacy/logic/models/hive/backblaze_credential.dart';
2021-12-06 18:31:19 +00: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 18:31:19 +00:00
final String applicationKeyId;
final String applicationKey;
}
2021-02-03 19:51:07 +00:00
2021-03-25 23:30:34 +00:00
class BackblazeApi extends ApiMap {
2022-02-16 07:28:29 +00:00
BackblazeApi({this.hasLogger = false, this.isWithToken = true});
2021-03-25 23:30:34 +00:00
2022-05-24 18:55:39 +00:00
@override
2021-03-25 23:30:34 +00:00
BaseOptions get options {
2022-06-05 19:36:32 +00:00
final BaseOptions options = BaseOptions(baseUrl: rootAddress);
2021-03-25 23:30:34 +00:00
if (isWithToken) {
final BackblazeCredential? backblazeCredential =
getIt<ApiConfigModel>().backblazeCredential;
2022-06-05 19:36:32 +00:00
final String token = backblazeCredential!.applicationKey;
2021-03-25 23:30:34 +00:00
options.headers = {'Authorization': 'Basic $token'};
}
if (validateStatus != null) {
options.validateStatus = validateStatus!;
2021-02-03 19:51:07 +00:00
}
2021-03-25 23:30:34 +00:00
return options;
2021-02-03 19:51:07 +00:00
}
@override
2021-03-25 23:30:34 +00:00
String rootAddress = 'https://api.backblazeb2.com/b2api/v2/';
2021-02-03 19:51:07 +00:00
2021-12-06 18:31:19 +00:00
String apiPrefix = '/b2api/v2';
Future<BackblazeApiAuth> getAuthorizationToken() async {
2022-06-05 19:36:32 +00:00
final Dio client = await getClient();
final BackblazeCredential? backblazeCredential =
getIt<ApiConfigModel>().backblazeCredential;
2021-12-06 18:31:19 +00:00
if (backblazeCredential == null) {
throw Exception('Backblaze credential is null');
}
final String encodedApiKey = encodedBackblazeKey(
backblazeCredential.keyId,
backblazeCredential.applicationKey,
);
2022-06-05 19:36:32 +00:00
final Response response = await client.get(
2021-12-06 18:31:19 +00: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'],
);
}
2022-06-05 19:36:32 +00:00
Future<bool> isValid(final String encodedApiKey) async {
final Dio client = await getClient();
try {
final Response response = await client.get(
'b2_authorize_account',
options: Options(headers: {'Authorization': 'Basic $encodedApiKey'}),
);
if (response.statusCode == HttpStatus.ok) {
if (response.data['allowed']['capabilities'].contains('listBuckets')) {
return true;
}
return false;
} else if (response.statusCode == HttpStatus.unauthorized) {
return false;
} else {
throw Exception('code: ${response.statusCode}');
2021-12-06 18:31:19 +00:00
}
} on DioError {
2021-12-06 18:31:19 +00:00
return false;
} finally {
close(client);
2021-02-03 19:51:07 +00:00
}
}
2021-03-25 23:30:34 +00:00
2021-12-06 18:31:19 +00:00
// Create bucket
2022-06-05 19:36:32 +00:00
Future<String> createBucket(final String bucketName) async {
final BackblazeApiAuth auth = await getAuthorizationToken();
final BackblazeCredential? backblazeCredential =
getIt<ApiConfigModel>().backblazeCredential;
2022-06-05 19:36:32 +00:00
final Dio client = await getClient();
2021-12-06 18:31:19 +00:00
client.options.baseUrl = auth.apiUrl;
2022-06-05 19:36:32 +00:00
final Response response = await client.post(
2021-12-06 18:31:19 +00:00
'$apiPrefix/b2_create_bucket',
data: {
'accountId': backblazeCredential!.keyId,
'bucketName': bucketName,
'bucketType': 'allPrivate',
'lifecycleRules': [
{
2022-05-24 18:55:39 +00:00
'daysFromHidingToDeleting': 30,
'daysFromUploadingToHiding': null,
'fileNamePrefix': ''
2021-12-06 18:31:19 +00: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 19:36:32 +00:00
Future<BackblazeApplicationKey> createKey(final String bucketId) async {
final BackblazeApiAuth auth = await getAuthorizationToken();
final Dio client = await getClient();
2021-12-06 18:31:19 +00:00
client.options.baseUrl = auth.apiUrl;
2022-06-05 19:36:32 +00:00
final Response response = await client.post(
2021-12-06 18:31:19 +00: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 18:31:19 +00:00
} else {
throw Exception('code: ${response.statusCode}');
}
}
2021-03-25 23:30:34 +00:00
@override
2022-02-16 07:28:29 +00:00
bool hasLogger;
2021-03-25 23:30:34 +00:00
@override
bool isWithToken;
}