mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-09 17:39:42 +00:00
chore: Merge endpoint-errors into master
Reviewed-on: https://git.selfprivacy.org/kherel/selfprivacy.org.app/pulls/149 Reviewed-by: Inex Code <inex.code@selfprivacy.org>
This commit is contained in:
commit
51ca8bce27
|
@ -273,6 +273,7 @@
|
||||||
"place_where_data": "A place where your data and SelfPrivacy services will reside:",
|
"place_where_data": "A place where your data and SelfPrivacy services will reside:",
|
||||||
"how": "How to obtain API token",
|
"how": "How to obtain API token",
|
||||||
"provider_bad_key_error": "Provider API key is invalid",
|
"provider_bad_key_error": "Provider API key is invalid",
|
||||||
|
"could_not_connect": "Counldn't connect to the provider.",
|
||||||
"choose_location_type": "Choose your server location and type:",
|
"choose_location_type": "Choose your server location and type:",
|
||||||
"back_to_locations": "Go back to available locations!",
|
"back_to_locations": "Go back to available locations!",
|
||||||
"no_locations_found": "No available locations found. Make sure your account is accessible.",
|
"no_locations_found": "No available locations found. Make sure your account is accessible.",
|
||||||
|
|
|
@ -272,6 +272,7 @@
|
||||||
"place_where_data": "Здесь будут жить ваши данные и SelfPrivacy-сервисы:",
|
"place_where_data": "Здесь будут жить ваши данные и SelfPrivacy-сервисы:",
|
||||||
"how": "Как получить API Token",
|
"how": "Как получить API Token",
|
||||||
"provider_bad_key_error": "API ключ провайдера неверен",
|
"provider_bad_key_error": "API ключ провайдера неверен",
|
||||||
|
"could_not_connect": "Не удалось соединиться с провайдером.",
|
||||||
"choose_location_type": "Выберите локацию и тип вашего сервера:",
|
"choose_location_type": "Выберите локацию и тип вашего сервера:",
|
||||||
"back_to_locations": "Назад к доступным локациям!",
|
"back_to_locations": "Назад к доступным локациям!",
|
||||||
"no_locations_found": "Не найдено локаций. Убедитесь, что ваш аккаунт доступен.",
|
"no_locations_found": "Не найдено локаций. Убедитесь, что ваш аккаунт доступен.",
|
||||||
|
|
15
lib/logic/api_maps/api_generic_result.dart
Normal file
15
lib/logic/api_maps/api_generic_result.dart
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
class APIGenericResult<T> {
|
||||||
|
APIGenericResult({
|
||||||
|
required this.success,
|
||||||
|
required this.data,
|
||||||
|
this.message,
|
||||||
|
this.code,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Whether was a response successfully received,
|
||||||
|
/// doesn't represent success of the request if `data<T>` is `bool`
|
||||||
|
final bool success;
|
||||||
|
final String? message;
|
||||||
|
final T data;
|
||||||
|
final int? code;
|
||||||
|
}
|
|
@ -22,13 +22,13 @@ mixin JobsApi on ApiMap {
|
||||||
return jobsList;
|
return jobsList;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericMutationResult<bool>> removeApiJob(final String uid) async {
|
Future<APIGenericResult<bool>> removeApiJob(final String uid) async {
|
||||||
try {
|
try {
|
||||||
final GraphQLClient client = await getClient();
|
final GraphQLClient client = await getClient();
|
||||||
final variables = Variables$Mutation$RemoveJob(jobId: uid);
|
final variables = Variables$Mutation$RemoveJob(jobId: uid);
|
||||||
final mutation = Options$Mutation$RemoveJob(variables: variables);
|
final mutation = Options$Mutation$RemoveJob(variables: variables);
|
||||||
final response = await client.mutate$RemoveJob(mutation);
|
final response = await client.mutate$RemoveJob(mutation);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: response.parsedData?.removeJob.success ?? false,
|
data: response.parsedData?.removeJob.success ?? false,
|
||||||
success: true,
|
success: true,
|
||||||
code: response.parsedData?.removeJob.code ?? 0,
|
code: response.parsedData?.removeJob.code ?? 0,
|
||||||
|
@ -36,7 +36,7 @@ mixin JobsApi on ApiMap {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: false,
|
data: false,
|
||||||
success: false,
|
success: false,
|
||||||
code: 0,
|
code: 0,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:graphql/client.dart';
|
import 'package:graphql/client.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
|
import 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/api_map.dart';
|
import 'package:selfprivacy/logic/api_maps/graphql_maps/api_map.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/disk_volumes.graphql.dart';
|
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/disk_volumes.graphql.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/schema.graphql.dart';
|
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/schema.graphql.dart';
|
||||||
|
@ -22,36 +23,14 @@ import 'package:selfprivacy/logic/models/service.dart';
|
||||||
import 'package:selfprivacy/logic/models/ssh_settings.dart';
|
import 'package:selfprivacy/logic/models/ssh_settings.dart';
|
||||||
import 'package:selfprivacy/logic/models/system_settings.dart';
|
import 'package:selfprivacy/logic/models/system_settings.dart';
|
||||||
|
|
||||||
|
export 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
|
||||||
|
|
||||||
part 'jobs_api.dart';
|
part 'jobs_api.dart';
|
||||||
part 'server_actions_api.dart';
|
part 'server_actions_api.dart';
|
||||||
part 'services_api.dart';
|
part 'services_api.dart';
|
||||||
part 'users_api.dart';
|
part 'users_api.dart';
|
||||||
part 'volume_api.dart';
|
part 'volume_api.dart';
|
||||||
|
|
||||||
class GenericResult<T> {
|
|
||||||
GenericResult({
|
|
||||||
required this.success,
|
|
||||||
required this.data,
|
|
||||||
this.message,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// Whether was a response successfully received,
|
|
||||||
/// doesn't represent success of the request if `data<T>` is `bool`
|
|
||||||
final bool success;
|
|
||||||
final String? message;
|
|
||||||
final T data;
|
|
||||||
}
|
|
||||||
|
|
||||||
class GenericMutationResult<T> extends GenericResult<T> {
|
|
||||||
GenericMutationResult({
|
|
||||||
required super.success,
|
|
||||||
required this.code,
|
|
||||||
required super.data,
|
|
||||||
super.message,
|
|
||||||
});
|
|
||||||
final int code;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ServerApi extends ApiMap
|
class ServerApi extends ApiMap
|
||||||
with VolumeApi, JobsApi, ServerActionsApi, ServicesApi, UsersApi {
|
with VolumeApi, JobsApi, ServerActionsApi, ServicesApi, UsersApi {
|
||||||
ServerApi({
|
ServerApi({
|
||||||
|
@ -206,7 +185,7 @@ class ServerApi extends ApiMap
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<RecoveryKeyStatus?>> getRecoveryTokenStatus() async {
|
Future<APIGenericResult<RecoveryKeyStatus?>> getRecoveryTokenStatus() async {
|
||||||
RecoveryKeyStatus? key;
|
RecoveryKeyStatus? key;
|
||||||
QueryResult<Query$RecoveryKey> response;
|
QueryResult<Query$RecoveryKey> response;
|
||||||
String? error;
|
String? error;
|
||||||
|
@ -223,18 +202,18 @@ class ServerApi extends ApiMap
|
||||||
print(e);
|
print(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GenericResult<RecoveryKeyStatus?>(
|
return APIGenericResult<RecoveryKeyStatus?>(
|
||||||
success: error == null,
|
success: error == null,
|
||||||
data: key,
|
data: key,
|
||||||
message: error,
|
message: error,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<String>> generateRecoveryToken(
|
Future<APIGenericResult<String>> generateRecoveryToken(
|
||||||
final DateTime? expirationDate,
|
final DateTime? expirationDate,
|
||||||
final int? numberOfUses,
|
final int? numberOfUses,
|
||||||
) async {
|
) async {
|
||||||
GenericResult<String> key;
|
APIGenericResult<String> key;
|
||||||
QueryResult<Mutation$GetNewRecoveryApiKey> response;
|
QueryResult<Mutation$GetNewRecoveryApiKey> response;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -255,19 +234,19 @@ class ServerApi extends ApiMap
|
||||||
);
|
);
|
||||||
if (response.hasException) {
|
if (response.hasException) {
|
||||||
print(response.exception.toString());
|
print(response.exception.toString());
|
||||||
key = GenericResult<String>(
|
key = APIGenericResult<String>(
|
||||||
success: false,
|
success: false,
|
||||||
data: '',
|
data: '',
|
||||||
message: response.exception.toString(),
|
message: response.exception.toString(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
key = GenericResult<String>(
|
key = APIGenericResult<String>(
|
||||||
success: true,
|
success: true,
|
||||||
data: response.parsedData!.getNewRecoveryApiKey.key!,
|
data: response.parsedData!.getNewRecoveryApiKey.key!,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
key = GenericResult<String>(
|
key = APIGenericResult<String>(
|
||||||
success: false,
|
success: false,
|
||||||
data: '',
|
data: '',
|
||||||
message: e.toString(),
|
message: e.toString(),
|
||||||
|
@ -300,8 +279,8 @@ class ServerApi extends ApiMap
|
||||||
return records;
|
return records;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<List<ApiToken>>> getApiTokens() async {
|
Future<APIGenericResult<List<ApiToken>>> getApiTokens() async {
|
||||||
GenericResult<List<ApiToken>> tokens;
|
APIGenericResult<List<ApiToken>> tokens;
|
||||||
QueryResult<Query$GetApiTokens> response;
|
QueryResult<Query$GetApiTokens> response;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -310,7 +289,7 @@ class ServerApi extends ApiMap
|
||||||
if (response.hasException) {
|
if (response.hasException) {
|
||||||
final message = response.exception.toString();
|
final message = response.exception.toString();
|
||||||
print(message);
|
print(message);
|
||||||
tokens = GenericResult<List<ApiToken>>(
|
tokens = APIGenericResult<List<ApiToken>>(
|
||||||
success: false,
|
success: false,
|
||||||
data: [],
|
data: [],
|
||||||
message: message,
|
message: message,
|
||||||
|
@ -324,13 +303,13 @@ class ServerApi extends ApiMap
|
||||||
ApiToken.fromGraphQL(device),
|
ApiToken.fromGraphQL(device),
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
tokens = GenericResult<List<ApiToken>>(
|
tokens = APIGenericResult<List<ApiToken>>(
|
||||||
success: true,
|
success: true,
|
||||||
data: parsed,
|
data: parsed,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
tokens = GenericResult<List<ApiToken>>(
|
tokens = APIGenericResult<List<ApiToken>>(
|
||||||
success: false,
|
success: false,
|
||||||
data: [],
|
data: [],
|
||||||
message: e.toString(),
|
message: e.toString(),
|
||||||
|
@ -340,8 +319,8 @@ class ServerApi extends ApiMap
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<void>> deleteApiToken(final String name) async {
|
Future<APIGenericResult<void>> deleteApiToken(final String name) async {
|
||||||
GenericResult<void> returnable;
|
APIGenericResult<void> returnable;
|
||||||
QueryResult<Mutation$DeleteDeviceApiToken> response;
|
QueryResult<Mutation$DeleteDeviceApiToken> response;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -358,19 +337,19 @@ class ServerApi extends ApiMap
|
||||||
);
|
);
|
||||||
if (response.hasException) {
|
if (response.hasException) {
|
||||||
print(response.exception.toString());
|
print(response.exception.toString());
|
||||||
returnable = GenericResult<void>(
|
returnable = APIGenericResult<void>(
|
||||||
success: false,
|
success: false,
|
||||||
data: null,
|
data: null,
|
||||||
message: response.exception.toString(),
|
message: response.exception.toString(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
returnable = GenericResult<void>(
|
returnable = APIGenericResult<void>(
|
||||||
success: true,
|
success: true,
|
||||||
data: null,
|
data: null,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
returnable = GenericResult<void>(
|
returnable = APIGenericResult<void>(
|
||||||
success: false,
|
success: false,
|
||||||
data: null,
|
data: null,
|
||||||
message: e.toString(),
|
message: e.toString(),
|
||||||
|
@ -380,8 +359,8 @@ class ServerApi extends ApiMap
|
||||||
return returnable;
|
return returnable;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<String>> createDeviceToken() async {
|
Future<APIGenericResult<String>> createDeviceToken() async {
|
||||||
GenericResult<String> token;
|
APIGenericResult<String> token;
|
||||||
QueryResult<Mutation$GetNewDeviceApiKey> response;
|
QueryResult<Mutation$GetNewDeviceApiKey> response;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -393,19 +372,19 @@ class ServerApi extends ApiMap
|
||||||
);
|
);
|
||||||
if (response.hasException) {
|
if (response.hasException) {
|
||||||
print(response.exception.toString());
|
print(response.exception.toString());
|
||||||
token = GenericResult<String>(
|
token = APIGenericResult<String>(
|
||||||
success: false,
|
success: false,
|
||||||
data: '',
|
data: '',
|
||||||
message: response.exception.toString(),
|
message: response.exception.toString(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
token = GenericResult<String>(
|
token = APIGenericResult<String>(
|
||||||
success: true,
|
success: true,
|
||||||
data: response.parsedData!.getNewDeviceApiKey.key!,
|
data: response.parsedData!.getNewDeviceApiKey.key!,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
token = GenericResult<String>(
|
token = APIGenericResult<String>(
|
||||||
success: false,
|
success: false,
|
||||||
data: '',
|
data: '',
|
||||||
message: e.toString(),
|
message: e.toString(),
|
||||||
|
@ -417,10 +396,10 @@ class ServerApi extends ApiMap
|
||||||
|
|
||||||
Future<bool> isHttpServerWorking() async => (await getApiVersion()) != null;
|
Future<bool> isHttpServerWorking() async => (await getApiVersion()) != null;
|
||||||
|
|
||||||
Future<GenericResult<String>> authorizeDevice(
|
Future<APIGenericResult<String>> authorizeDevice(
|
||||||
final DeviceToken deviceToken,
|
final DeviceToken deviceToken,
|
||||||
) async {
|
) async {
|
||||||
GenericResult<String> token;
|
APIGenericResult<String> token;
|
||||||
QueryResult<Mutation$AuthorizeWithNewDeviceApiKey> response;
|
QueryResult<Mutation$AuthorizeWithNewDeviceApiKey> response;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -442,19 +421,19 @@ class ServerApi extends ApiMap
|
||||||
);
|
);
|
||||||
if (response.hasException) {
|
if (response.hasException) {
|
||||||
print(response.exception.toString());
|
print(response.exception.toString());
|
||||||
token = GenericResult<String>(
|
token = APIGenericResult<String>(
|
||||||
success: false,
|
success: false,
|
||||||
data: '',
|
data: '',
|
||||||
message: response.exception.toString(),
|
message: response.exception.toString(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
token = GenericResult<String>(
|
token = APIGenericResult<String>(
|
||||||
success: true,
|
success: true,
|
||||||
data: response.parsedData!.authorizeWithNewDeviceApiKey.token!,
|
data: response.parsedData!.authorizeWithNewDeviceApiKey.token!,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
token = GenericResult<String>(
|
token = APIGenericResult<String>(
|
||||||
success: false,
|
success: false,
|
||||||
data: '',
|
data: '',
|
||||||
message: e.toString(),
|
message: e.toString(),
|
||||||
|
@ -464,10 +443,10 @@ class ServerApi extends ApiMap
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<String>> useRecoveryToken(
|
Future<APIGenericResult<String>> useRecoveryToken(
|
||||||
final DeviceToken deviceToken,
|
final DeviceToken deviceToken,
|
||||||
) async {
|
) async {
|
||||||
GenericResult<String> token;
|
APIGenericResult<String> token;
|
||||||
QueryResult<Mutation$UseRecoveryApiKey> response;
|
QueryResult<Mutation$UseRecoveryApiKey> response;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -489,19 +468,19 @@ class ServerApi extends ApiMap
|
||||||
);
|
);
|
||||||
if (response.hasException) {
|
if (response.hasException) {
|
||||||
print(response.exception.toString());
|
print(response.exception.toString());
|
||||||
token = GenericResult<String>(
|
token = APIGenericResult<String>(
|
||||||
success: false,
|
success: false,
|
||||||
data: '',
|
data: '',
|
||||||
message: response.exception.toString(),
|
message: response.exception.toString(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
token = GenericResult<String>(
|
token = APIGenericResult<String>(
|
||||||
success: true,
|
success: true,
|
||||||
data: response.parsedData!.useRecoveryApiKey.token!,
|
data: response.parsedData!.useRecoveryApiKey.token!,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
token = GenericResult<String>(
|
token = APIGenericResult<String>(
|
||||||
success: false,
|
success: false,
|
||||||
data: '',
|
data: '',
|
||||||
message: e.toString(),
|
message: e.toString(),
|
||||||
|
|
|
@ -20,7 +20,7 @@ mixin ServicesApi on ApiMap {
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericMutationResult<bool>> enableService(
|
Future<APIGenericResult<bool>> enableService(
|
||||||
final String serviceId,
|
final String serviceId,
|
||||||
) async {
|
) async {
|
||||||
try {
|
try {
|
||||||
|
@ -28,7 +28,7 @@ mixin ServicesApi on ApiMap {
|
||||||
final variables = Variables$Mutation$EnableService(serviceId: serviceId);
|
final variables = Variables$Mutation$EnableService(serviceId: serviceId);
|
||||||
final mutation = Options$Mutation$EnableService(variables: variables);
|
final mutation = Options$Mutation$EnableService(variables: variables);
|
||||||
final response = await client.mutate$EnableService(mutation);
|
final response = await client.mutate$EnableService(mutation);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: response.parsedData?.enableService.success ?? false,
|
data: response.parsedData?.enableService.success ?? false,
|
||||||
success: true,
|
success: true,
|
||||||
code: response.parsedData?.enableService.code ?? 0,
|
code: response.parsedData?.enableService.code ?? 0,
|
||||||
|
@ -36,7 +36,7 @@ mixin ServicesApi on ApiMap {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: false,
|
data: false,
|
||||||
success: false,
|
success: false,
|
||||||
code: 0,
|
code: 0,
|
||||||
|
@ -45,7 +45,7 @@ mixin ServicesApi on ApiMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericMutationResult<void>> disableService(
|
Future<APIGenericResult<void>> disableService(
|
||||||
final String serviceId,
|
final String serviceId,
|
||||||
) async {
|
) async {
|
||||||
try {
|
try {
|
||||||
|
@ -53,7 +53,7 @@ mixin ServicesApi on ApiMap {
|
||||||
final variables = Variables$Mutation$DisableService(serviceId: serviceId);
|
final variables = Variables$Mutation$DisableService(serviceId: serviceId);
|
||||||
final mutation = Options$Mutation$DisableService(variables: variables);
|
final mutation = Options$Mutation$DisableService(variables: variables);
|
||||||
final response = await client.mutate$DisableService(mutation);
|
final response = await client.mutate$DisableService(mutation);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: null,
|
data: null,
|
||||||
success: response.parsedData?.disableService.success ?? false,
|
success: response.parsedData?.disableService.success ?? false,
|
||||||
code: response.parsedData?.disableService.code ?? 0,
|
code: response.parsedData?.disableService.code ?? 0,
|
||||||
|
@ -61,7 +61,7 @@ mixin ServicesApi on ApiMap {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: null,
|
data: null,
|
||||||
success: false,
|
success: false,
|
||||||
code: 0,
|
code: 0,
|
||||||
|
@ -70,7 +70,7 @@ mixin ServicesApi on ApiMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericMutationResult<bool>> stopService(
|
Future<APIGenericResult<bool>> stopService(
|
||||||
final String serviceId,
|
final String serviceId,
|
||||||
) async {
|
) async {
|
||||||
try {
|
try {
|
||||||
|
@ -78,7 +78,7 @@ mixin ServicesApi on ApiMap {
|
||||||
final variables = Variables$Mutation$StopService(serviceId: serviceId);
|
final variables = Variables$Mutation$StopService(serviceId: serviceId);
|
||||||
final mutation = Options$Mutation$StopService(variables: variables);
|
final mutation = Options$Mutation$StopService(variables: variables);
|
||||||
final response = await client.mutate$StopService(mutation);
|
final response = await client.mutate$StopService(mutation);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: response.parsedData?.stopService.success ?? false,
|
data: response.parsedData?.stopService.success ?? false,
|
||||||
success: true,
|
success: true,
|
||||||
code: response.parsedData?.stopService.code ?? 0,
|
code: response.parsedData?.stopService.code ?? 0,
|
||||||
|
@ -86,7 +86,7 @@ mixin ServicesApi on ApiMap {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: false,
|
data: false,
|
||||||
success: false,
|
success: false,
|
||||||
code: 0,
|
code: 0,
|
||||||
|
@ -95,13 +95,13 @@ mixin ServicesApi on ApiMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericMutationResult> startService(final String serviceId) async {
|
Future<APIGenericResult> startService(final String serviceId) async {
|
||||||
try {
|
try {
|
||||||
final GraphQLClient client = await getClient();
|
final GraphQLClient client = await getClient();
|
||||||
final variables = Variables$Mutation$StartService(serviceId: serviceId);
|
final variables = Variables$Mutation$StartService(serviceId: serviceId);
|
||||||
final mutation = Options$Mutation$StartService(variables: variables);
|
final mutation = Options$Mutation$StartService(variables: variables);
|
||||||
final response = await client.mutate$StartService(mutation);
|
final response = await client.mutate$StartService(mutation);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: null,
|
data: null,
|
||||||
success: response.parsedData?.startService.success ?? false,
|
success: response.parsedData?.startService.success ?? false,
|
||||||
code: response.parsedData?.startService.code ?? 0,
|
code: response.parsedData?.startService.code ?? 0,
|
||||||
|
@ -109,7 +109,7 @@ mixin ServicesApi on ApiMap {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: null,
|
data: null,
|
||||||
success: false,
|
success: false,
|
||||||
code: 0,
|
code: 0,
|
||||||
|
@ -118,7 +118,7 @@ mixin ServicesApi on ApiMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericMutationResult<bool>> restartService(
|
Future<APIGenericResult<bool>> restartService(
|
||||||
final String serviceId,
|
final String serviceId,
|
||||||
) async {
|
) async {
|
||||||
try {
|
try {
|
||||||
|
@ -126,7 +126,7 @@ mixin ServicesApi on ApiMap {
|
||||||
final variables = Variables$Mutation$RestartService(serviceId: serviceId);
|
final variables = Variables$Mutation$RestartService(serviceId: serviceId);
|
||||||
final mutation = Options$Mutation$RestartService(variables: variables);
|
final mutation = Options$Mutation$RestartService(variables: variables);
|
||||||
final response = await client.mutate$RestartService(mutation);
|
final response = await client.mutate$RestartService(mutation);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: response.parsedData?.restartService.success ?? false,
|
data: response.parsedData?.restartService.success ?? false,
|
||||||
success: true,
|
success: true,
|
||||||
code: response.parsedData?.restartService.code ?? 0,
|
code: response.parsedData?.restartService.code ?? 0,
|
||||||
|
@ -134,7 +134,7 @@ mixin ServicesApi on ApiMap {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: false,
|
data: false,
|
||||||
success: false,
|
success: false,
|
||||||
code: 0,
|
code: 0,
|
||||||
|
@ -143,7 +143,7 @@ mixin ServicesApi on ApiMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericMutationResult<ServerJob?>> moveService(
|
Future<APIGenericResult<ServerJob?>> moveService(
|
||||||
final String serviceId,
|
final String serviceId,
|
||||||
final String destination,
|
final String destination,
|
||||||
) async {
|
) async {
|
||||||
|
@ -158,7 +158,7 @@ mixin ServicesApi on ApiMap {
|
||||||
final mutation = Options$Mutation$MoveService(variables: variables);
|
final mutation = Options$Mutation$MoveService(variables: variables);
|
||||||
final response = await client.mutate$MoveService(mutation);
|
final response = await client.mutate$MoveService(mutation);
|
||||||
final jobJson = response.parsedData?.moveService.job?.toJson();
|
final jobJson = response.parsedData?.moveService.job?.toJson();
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
success: true,
|
success: true,
|
||||||
code: response.parsedData?.moveService.code ?? 0,
|
code: response.parsedData?.moveService.code ?? 0,
|
||||||
message: response.parsedData?.moveService.message,
|
message: response.parsedData?.moveService.message,
|
||||||
|
@ -166,7 +166,7 @@ mixin ServicesApi on ApiMap {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
success: false,
|
success: false,
|
||||||
code: 0,
|
code: 0,
|
||||||
message: e.toString(),
|
message: e.toString(),
|
||||||
|
|
|
@ -45,7 +45,7 @@ mixin UsersApi on ApiMap {
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericMutationResult<User?>> createUser(
|
Future<APIGenericResult<User?>> createUser(
|
||||||
final String username,
|
final String username,
|
||||||
final String password,
|
final String password,
|
||||||
) async {
|
) async {
|
||||||
|
@ -56,7 +56,7 @@ mixin UsersApi on ApiMap {
|
||||||
);
|
);
|
||||||
final mutation = Options$Mutation$CreateUser(variables: variables);
|
final mutation = Options$Mutation$CreateUser(variables: variables);
|
||||||
final response = await client.mutate$CreateUser(mutation);
|
final response = await client.mutate$CreateUser(mutation);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
success: true,
|
success: true,
|
||||||
code: response.parsedData?.createUser.code ?? 500,
|
code: response.parsedData?.createUser.code ?? 500,
|
||||||
message: response.parsedData?.createUser.message,
|
message: response.parsedData?.createUser.message,
|
||||||
|
@ -66,7 +66,7 @@ mixin UsersApi on ApiMap {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
success: false,
|
success: false,
|
||||||
code: 0,
|
code: 0,
|
||||||
message: e.toString(),
|
message: e.toString(),
|
||||||
|
@ -75,7 +75,7 @@ mixin UsersApi on ApiMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericMutationResult<bool>> deleteUser(
|
Future<APIGenericResult<bool>> deleteUser(
|
||||||
final String username,
|
final String username,
|
||||||
) async {
|
) async {
|
||||||
try {
|
try {
|
||||||
|
@ -83,7 +83,7 @@ mixin UsersApi on ApiMap {
|
||||||
final variables = Variables$Mutation$DeleteUser(username: username);
|
final variables = Variables$Mutation$DeleteUser(username: username);
|
||||||
final mutation = Options$Mutation$DeleteUser(variables: variables);
|
final mutation = Options$Mutation$DeleteUser(variables: variables);
|
||||||
final response = await client.mutate$DeleteUser(mutation);
|
final response = await client.mutate$DeleteUser(mutation);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: response.parsedData?.deleteUser.success ?? false,
|
data: response.parsedData?.deleteUser.success ?? false,
|
||||||
success: true,
|
success: true,
|
||||||
code: response.parsedData?.deleteUser.code ?? 500,
|
code: response.parsedData?.deleteUser.code ?? 500,
|
||||||
|
@ -91,7 +91,7 @@ mixin UsersApi on ApiMap {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: false,
|
data: false,
|
||||||
success: false,
|
success: false,
|
||||||
code: 500,
|
code: 500,
|
||||||
|
@ -100,7 +100,7 @@ mixin UsersApi on ApiMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericMutationResult<User?>> updateUser(
|
Future<APIGenericResult<User?>> updateUser(
|
||||||
final String username,
|
final String username,
|
||||||
final String password,
|
final String password,
|
||||||
) async {
|
) async {
|
||||||
|
@ -111,7 +111,7 @@ mixin UsersApi on ApiMap {
|
||||||
);
|
);
|
||||||
final mutation = Options$Mutation$UpdateUser(variables: variables);
|
final mutation = Options$Mutation$UpdateUser(variables: variables);
|
||||||
final response = await client.mutate$UpdateUser(mutation);
|
final response = await client.mutate$UpdateUser(mutation);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
success: true,
|
success: true,
|
||||||
code: response.parsedData?.updateUser.code ?? 500,
|
code: response.parsedData?.updateUser.code ?? 500,
|
||||||
message: response.parsedData?.updateUser.message,
|
message: response.parsedData?.updateUser.message,
|
||||||
|
@ -121,7 +121,7 @@ mixin UsersApi on ApiMap {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: null,
|
data: null,
|
||||||
success: false,
|
success: false,
|
||||||
code: 0,
|
code: 0,
|
||||||
|
@ -130,7 +130,7 @@ mixin UsersApi on ApiMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericMutationResult<User?>> addSshKey(
|
Future<APIGenericResult<User?>> addSshKey(
|
||||||
final String username,
|
final String username,
|
||||||
final String sshKey,
|
final String sshKey,
|
||||||
) async {
|
) async {
|
||||||
|
@ -144,7 +144,7 @@ mixin UsersApi on ApiMap {
|
||||||
);
|
);
|
||||||
final mutation = Options$Mutation$AddSshKey(variables: variables);
|
final mutation = Options$Mutation$AddSshKey(variables: variables);
|
||||||
final response = await client.mutate$AddSshKey(mutation);
|
final response = await client.mutate$AddSshKey(mutation);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
success: true,
|
success: true,
|
||||||
code: response.parsedData?.addSshKey.code ?? 500,
|
code: response.parsedData?.addSshKey.code ?? 500,
|
||||||
message: response.parsedData?.addSshKey.message,
|
message: response.parsedData?.addSshKey.message,
|
||||||
|
@ -154,7 +154,7 @@ mixin UsersApi on ApiMap {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: null,
|
data: null,
|
||||||
success: false,
|
success: false,
|
||||||
code: 0,
|
code: 0,
|
||||||
|
@ -163,7 +163,7 @@ mixin UsersApi on ApiMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericMutationResult<User?>> removeSshKey(
|
Future<APIGenericResult<User?>> removeSshKey(
|
||||||
final String username,
|
final String username,
|
||||||
final String sshKey,
|
final String sshKey,
|
||||||
) async {
|
) async {
|
||||||
|
@ -177,7 +177,7 @@ mixin UsersApi on ApiMap {
|
||||||
);
|
);
|
||||||
final mutation = Options$Mutation$RemoveSshKey(variables: variables);
|
final mutation = Options$Mutation$RemoveSshKey(variables: variables);
|
||||||
final response = await client.mutate$RemoveSshKey(mutation);
|
final response = await client.mutate$RemoveSshKey(mutation);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
success: response.parsedData?.removeSshKey.success ?? false,
|
success: response.parsedData?.removeSshKey.success ?? false,
|
||||||
code: response.parsedData?.removeSshKey.code ?? 500,
|
code: response.parsedData?.removeSshKey.code ?? 500,
|
||||||
message: response.parsedData?.removeSshKey.message,
|
message: response.parsedData?.removeSshKey.message,
|
||||||
|
@ -187,7 +187,7 @@ mixin UsersApi on ApiMap {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericMutationResult(
|
return APIGenericResult(
|
||||||
data: null,
|
data: null,
|
||||||
success: false,
|
success: false,
|
||||||
code: 0,
|
code: 0,
|
||||||
|
|
|
@ -57,10 +57,10 @@ mixin VolumeApi on ApiMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericMutationResult<String?>> migrateToBinds(
|
Future<APIGenericResult<String?>> migrateToBinds(
|
||||||
final Map<String, String> serviceToDisk,
|
final Map<String, String> serviceToDisk,
|
||||||
) async {
|
) async {
|
||||||
GenericMutationResult<String?>? mutation;
|
APIGenericResult<String?>? mutation;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final GraphQLClient client = await getClient();
|
final GraphQLClient client = await getClient();
|
||||||
|
@ -78,7 +78,7 @@ mixin VolumeApi on ApiMap {
|
||||||
await client.mutate$MigrateToBinds(
|
await client.mutate$MigrateToBinds(
|
||||||
migrateMutation,
|
migrateMutation,
|
||||||
);
|
);
|
||||||
mutation = mutation = GenericMutationResult(
|
mutation = mutation = APIGenericResult(
|
||||||
success: true,
|
success: true,
|
||||||
code: result.parsedData!.migrateToBinds.code,
|
code: result.parsedData!.migrateToBinds.code,
|
||||||
message: result.parsedData!.migrateToBinds.message,
|
message: result.parsedData!.migrateToBinds.message,
|
||||||
|
@ -86,7 +86,7 @@ mixin VolumeApi on ApiMap {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
mutation = GenericMutationResult(
|
mutation = APIGenericResult(
|
||||||
success: false,
|
success: false,
|
||||||
code: 0,
|
code: 0,
|
||||||
message: e.toString(),
|
message: e.toString(),
|
||||||
|
|
|
@ -2,9 +2,12 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
|
import 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
|
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/backblaze_credential.dart';
|
import 'package:selfprivacy/logic/models/hive/backblaze_credential.dart';
|
||||||
|
|
||||||
|
export 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
|
||||||
|
|
||||||
class BackblazeApiAuth {
|
class BackblazeApiAuth {
|
||||||
BackblazeApiAuth({required this.authorizationToken, required this.apiUrl});
|
BackblazeApiAuth({required this.authorizationToken, required this.apiUrl});
|
||||||
|
|
||||||
|
@ -71,28 +74,43 @@ class BackblazeApi extends ApiMap {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> isValid(final String encodedApiKey) async {
|
Future<APIGenericResult<bool>> isApiTokenValid(
|
||||||
|
final String encodedApiKey,
|
||||||
|
) async {
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
|
bool isTokenValid = false;
|
||||||
try {
|
try {
|
||||||
final Response response = await client.get(
|
final Response response = await client.get(
|
||||||
'b2_authorize_account',
|
'b2_authorize_account',
|
||||||
options: Options(headers: {'Authorization': 'Basic $encodedApiKey'}),
|
options: Options(
|
||||||
|
followRedirects: false,
|
||||||
|
validateStatus: (final status) =>
|
||||||
|
status != null && (status >= 200 || status == 401),
|
||||||
|
headers: {'Authorization': 'Basic $encodedApiKey'},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
if (response.statusCode == HttpStatus.ok) {
|
if (response.statusCode == HttpStatus.ok) {
|
||||||
if (response.data['allowed']['capabilities'].contains('listBuckets')) {
|
isTokenValid = response.data['allowed']['capabilities'].contains('listBuckets');
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} else if (response.statusCode == HttpStatus.unauthorized) {
|
} else if (response.statusCode == HttpStatus.unauthorized) {
|
||||||
return false;
|
isTokenValid = false;
|
||||||
} else {
|
} else {
|
||||||
throw Exception('code: ${response.statusCode}');
|
throw Exception('code: ${response.statusCode}');
|
||||||
}
|
}
|
||||||
} on DioError {
|
} on DioError catch (e) {
|
||||||
return false;
|
print(e);
|
||||||
|
return APIGenericResult(
|
||||||
|
data: false,
|
||||||
|
success: false,
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return APIGenericResult(
|
||||||
|
data: isTokenValid,
|
||||||
|
success: true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create bucket
|
// Create bucket
|
||||||
|
|
|
@ -46,23 +46,37 @@ class CloudflareApi extends DnsProviderApi {
|
||||||
String rootAddress = 'https://api.cloudflare.com/client/v4';
|
String rootAddress = 'https://api.cloudflare.com/client/v4';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> isApiTokenValid(final String token) async {
|
Future<APIGenericResult<bool>> isApiTokenValid(final String token) async {
|
||||||
bool isValid = false;
|
bool isValid = false;
|
||||||
Response? response;
|
Response? response;
|
||||||
|
String message = '';
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
response = await client.get(
|
response = await client.get(
|
||||||
'/user/tokens/verify',
|
'/user/tokens/verify',
|
||||||
options: Options(headers: {'Authorization': 'Bearer $token'}),
|
options: Options(
|
||||||
|
followRedirects: false,
|
||||||
|
validateStatus: (final status) =>
|
||||||
|
status != null && (status >= 200 || status == 401),
|
||||||
|
headers: {'Authorization': 'Bearer $token'},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
isValid = false;
|
isValid = false;
|
||||||
|
message = e.toString();
|
||||||
} finally {
|
} finally {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response != null) {
|
if (response == null) {
|
||||||
|
return APIGenericResult(
|
||||||
|
data: isValid,
|
||||||
|
success: false,
|
||||||
|
message: message,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (response.statusCode == HttpStatus.ok) {
|
if (response.statusCode == HttpStatus.ok) {
|
||||||
isValid = true;
|
isValid = true;
|
||||||
} else if (response.statusCode == HttpStatus.unauthorized) {
|
} else if (response.statusCode == HttpStatus.unauthorized) {
|
||||||
|
@ -70,9 +84,12 @@ class CloudflareApi extends DnsProviderApi {
|
||||||
} else {
|
} else {
|
||||||
throw Exception('code: ${response.statusCode}');
|
throw Exception('code: ${response.statusCode}');
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return isValid;
|
return APIGenericResult(
|
||||||
|
data: isValid,
|
||||||
|
success: true,
|
||||||
|
message: response.statusMessage,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -96,7 +113,7 @@ class CloudflareApi extends DnsProviderApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> removeSimilarRecords({
|
Future<APIGenericResult<void>> removeSimilarRecords({
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
final String? ip4,
|
final String? ip4,
|
||||||
}) async {
|
}) async {
|
||||||
|
@ -122,9 +139,16 @@ class CloudflareApi extends DnsProviderApi {
|
||||||
await Future.wait(allDeleteFutures);
|
await Future.wait(allDeleteFutures);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
|
return APIGenericResult(
|
||||||
|
success: false,
|
||||||
|
data: null,
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return APIGenericResult(success: true, data: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -166,7 +190,7 @@ class CloudflareApi extends DnsProviderApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> createMultipleDnsRecords({
|
Future<APIGenericResult<void>> createMultipleDnsRecords({
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
final String? ip4,
|
final String? ip4,
|
||||||
}) async {
|
}) async {
|
||||||
|
@ -189,9 +213,18 @@ class CloudflareApi extends DnsProviderApi {
|
||||||
} on DioError catch (e) {
|
} on DioError catch (e) {
|
||||||
print(e.message);
|
print(e.message);
|
||||||
rethrow;
|
rethrow;
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
return APIGenericResult(
|
||||||
|
success: false,
|
||||||
|
data: null,
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return APIGenericResult(success: true, data: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DnsRecord> projectDnsRecords(
|
List<DnsRecord> projectDnsRecords(
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
|
import 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
|
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
||||||
|
|
||||||
|
export 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
|
||||||
|
|
||||||
class DomainNotFoundException implements Exception {
|
class DomainNotFoundException implements Exception {
|
||||||
DomainNotFoundException(this.message);
|
DomainNotFoundException(this.message);
|
||||||
final String message;
|
final String message;
|
||||||
|
@ -11,11 +14,11 @@ abstract class DnsProviderApi extends ApiMap {
|
||||||
Future<List<DnsRecord>> getDnsRecords({
|
Future<List<DnsRecord>> getDnsRecords({
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
});
|
});
|
||||||
Future<void> removeSimilarRecords({
|
Future<APIGenericResult<void>> removeSimilarRecords({
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
final String? ip4,
|
final String? ip4,
|
||||||
});
|
});
|
||||||
Future<void> createMultipleDnsRecords({
|
Future<APIGenericResult<void>> createMultipleDnsRecords({
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
final String? ip4,
|
final String? ip4,
|
||||||
});
|
});
|
||||||
|
@ -26,6 +29,6 @@ abstract class DnsProviderApi extends ApiMap {
|
||||||
Future<String?> getZoneId(final String domain);
|
Future<String?> getZoneId(final String domain);
|
||||||
Future<List<String>> domainList();
|
Future<List<String>> domainList();
|
||||||
|
|
||||||
Future<bool> isApiTokenValid(final String token);
|
Future<APIGenericResult<bool>> isApiTokenValid(final String token);
|
||||||
RegExp getApiTokenValidation();
|
RegExp getApiTokenValidation();
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,25 +59,37 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
String get displayProviderName => 'Digital Ocean';
|
String get displayProviderName => 'Digital Ocean';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> isApiTokenValid(final String token) async {
|
Future<APIGenericResult<bool>> isApiTokenValid(final String token) async {
|
||||||
bool isValid = false;
|
bool isValid = false;
|
||||||
Response? response;
|
Response? response;
|
||||||
|
String message = '';
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
response = await client.get(
|
response = await client.get(
|
||||||
'/account',
|
'/account',
|
||||||
options: Options(
|
options: Options(
|
||||||
|
followRedirects: false,
|
||||||
|
validateStatus: (final status) =>
|
||||||
|
status != null && (status >= 200 || status == 401),
|
||||||
headers: {'Authorization': 'Bearer $token'},
|
headers: {'Authorization': 'Bearer $token'},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
isValid = false;
|
isValid = false;
|
||||||
|
message = e.toString();
|
||||||
} finally {
|
} finally {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response != null) {
|
if (response == null) {
|
||||||
|
return APIGenericResult(
|
||||||
|
data: isValid,
|
||||||
|
success: false,
|
||||||
|
message: message,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (response.statusCode == HttpStatus.ok) {
|
if (response.statusCode == HttpStatus.ok) {
|
||||||
isValid = true;
|
isValid = true;
|
||||||
} else if (response.statusCode == HttpStatus.unauthorized) {
|
} else if (response.statusCode == HttpStatus.unauthorized) {
|
||||||
|
@ -85,9 +97,12 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
} else {
|
} else {
|
||||||
throw Exception('code: ${response.statusCode}');
|
throw Exception('code: ${response.statusCode}');
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return isValid;
|
return APIGenericResult(
|
||||||
|
data: isValid,
|
||||||
|
success: true,
|
||||||
|
message: response.statusMessage,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hardcoded on their documentation and there is no pricing API at all
|
/// Hardcoded on their documentation and there is no pricing API at all
|
||||||
|
@ -99,10 +114,10 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<ServerVolume?> createVolume() async {
|
Future<APIGenericResult<ServerVolume?>> createVolume() async {
|
||||||
ServerVolume? volume;
|
ServerVolume? volume;
|
||||||
|
|
||||||
final Response createVolumeResponse;
|
Response? createVolumeResponse;
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
final List<ServerVolume> volumes = await getVolumes();
|
final List<ServerVolume> volumes = await getVolumes();
|
||||||
|
@ -131,11 +146,21 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
|
return APIGenericResult(
|
||||||
|
data: null,
|
||||||
|
success: false,
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
client.close();
|
client.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
return volume;
|
return APIGenericResult(
|
||||||
|
data: volume,
|
||||||
|
success: true,
|
||||||
|
code: createVolumeResponse.statusCode,
|
||||||
|
message: createVolumeResponse.statusMessage,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -204,13 +229,13 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> attachVolume(
|
Future<APIGenericResult<bool>> attachVolume(
|
||||||
final ServerVolume volume,
|
final ServerVolume volume,
|
||||||
final int serverId,
|
final int serverId,
|
||||||
) async {
|
) async {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
final Response attachVolumeResponse;
|
Response? attachVolumeResponse;
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
attachVolumeResponse = await client.post(
|
attachVolumeResponse = await client.post(
|
||||||
|
@ -226,11 +251,21 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
attachVolumeResponse.data['action']['status'].toString() != 'error';
|
attachVolumeResponse.data['action']['status'].toString() != 'error';
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
|
return APIGenericResult(
|
||||||
|
data: false,
|
||||||
|
success: false,
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return APIGenericResult(
|
||||||
|
data: success,
|
||||||
|
success: true,
|
||||||
|
code: attachVolumeResponse.statusCode,
|
||||||
|
message: attachVolumeResponse.statusMessage,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -308,7 +343,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<ServerHostingDetails?> createServer({
|
Future<APIGenericResult<ServerHostingDetails?>> createServer({
|
||||||
required final String dnsApiToken,
|
required final String dnsApiToken,
|
||||||
required final User rootUser,
|
required final User rootUser,
|
||||||
required final String domainName,
|
required final String domainName,
|
||||||
|
@ -330,6 +365,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
"#cloud-config\nruncmd:\n- curl https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nixos-infect/raw/branch/$infectBranch/nixos-infect | PROVIDER=$infectProviderName STAGING_ACME='$stagingAcme' DOMAIN='$domainName' LUSER='${rootUser.login}' ENCODED_PASSWORD='$base64Password' CF_TOKEN=$dnsApiToken DB_PASSWORD=$dbPassword API_TOKEN=$apiToken HOSTNAME=$formattedHostname bash 2>&1 | tee /tmp/infect.log";
|
"#cloud-config\nruncmd:\n- curl https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nixos-infect/raw/branch/$infectBranch/nixos-infect | PROVIDER=$infectProviderName STAGING_ACME='$stagingAcme' DOMAIN='$domainName' LUSER='${rootUser.login}' ENCODED_PASSWORD='$base64Password' CF_TOKEN=$dnsApiToken DB_PASSWORD=$dbPassword API_TOKEN=$apiToken HOSTNAME=$formattedHostname bash 2>&1 | tee /tmp/infect.log";
|
||||||
print(userdataString);
|
print(userdataString);
|
||||||
|
|
||||||
|
Response? serverCreateResponse;
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
final Map<String, Object> data = {
|
final Map<String, Object> data = {
|
||||||
|
@ -341,14 +377,15 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
};
|
};
|
||||||
print('Decoded data: $data');
|
print('Decoded data: $data');
|
||||||
|
|
||||||
final Response serverCreateResponse = await client.post(
|
serverCreateResponse = await client.post(
|
||||||
'/droplets',
|
'/droplets',
|
||||||
data: data,
|
data: data,
|
||||||
);
|
);
|
||||||
|
|
||||||
final int serverId = serverCreateResponse.data['droplet']['id'];
|
final int serverId = serverCreateResponse.data['droplet']['id'];
|
||||||
final ServerVolume? newVolume = await createVolume();
|
final ServerVolume? newVolume = (await createVolume()).data;
|
||||||
final bool attachedVolume = await attachVolume(newVolume!, serverId);
|
final bool attachedVolume =
|
||||||
|
(await attachVolume(newVolume!, serverId)).data;
|
||||||
|
|
||||||
String? ipv4;
|
String? ipv4;
|
||||||
int attempts = 0;
|
int attempts = 0;
|
||||||
|
@ -376,11 +413,21 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
|
return APIGenericResult(
|
||||||
|
success: false,
|
||||||
|
data: null,
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
return serverDetails;
|
return APIGenericResult(
|
||||||
|
data: serverDetails,
|
||||||
|
success: true,
|
||||||
|
code: serverCreateResponse.statusCode,
|
||||||
|
message: serverCreateResponse.statusMessage,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -694,7 +741,8 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<ServerProviderLocation>> getAvailableLocations() async {
|
Future<APIGenericResult<List<ServerProviderLocation>>>
|
||||||
|
getAvailableLocations() async {
|
||||||
List<ServerProviderLocation> locations = [];
|
List<ServerProviderLocation> locations = [];
|
||||||
|
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
|
@ -715,15 +763,20 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
.toList();
|
.toList();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
|
return APIGenericResult(
|
||||||
|
data: [],
|
||||||
|
success: false,
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
return locations;
|
return APIGenericResult(data: locations, success: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<ServerType>> getServerTypesByLocation({
|
Future<APIGenericResult<List<ServerType>>> getServerTypesByLocation({
|
||||||
required final ServerProviderLocation location,
|
required final ServerProviderLocation location,
|
||||||
}) async {
|
}) async {
|
||||||
final List<ServerType> types = [];
|
final List<ServerType> types = [];
|
||||||
|
@ -756,19 +809,26 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
|
return APIGenericResult(
|
||||||
|
data: [],
|
||||||
|
success: false,
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
return types;
|
return APIGenericResult(data: types, success: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> createReverseDns({
|
Future<APIGenericResult<void>> createReverseDns({
|
||||||
required final ServerHostingDetails serverDetails,
|
required final ServerHostingDetails serverDetails,
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
}) async {
|
}) async {
|
||||||
/// TODO remove from provider interface
|
/// TODO remove from provider interface
|
||||||
|
const bool success = true;
|
||||||
|
return APIGenericResult(success: success, data: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -60,25 +60,37 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
String get displayProviderName => 'Hetzner';
|
String get displayProviderName => 'Hetzner';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> isApiTokenValid(final String token) async {
|
Future<APIGenericResult<bool>> isApiTokenValid(final String token) async {
|
||||||
bool isValid = false;
|
bool isValid = false;
|
||||||
Response? response;
|
Response? response;
|
||||||
|
String message = '';
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
response = await client.get(
|
response = await client.get(
|
||||||
'/servers',
|
'/servers',
|
||||||
options: Options(
|
options: Options(
|
||||||
|
followRedirects: false,
|
||||||
|
validateStatus: (final status) =>
|
||||||
|
status != null && (status >= 200 || status == 401),
|
||||||
headers: {'Authorization': 'Bearer $token'},
|
headers: {'Authorization': 'Bearer $token'},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
isValid = false;
|
isValid = false;
|
||||||
|
message = e.toString();
|
||||||
} finally {
|
} finally {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response != null) {
|
if (response == null) {
|
||||||
|
return APIGenericResult(
|
||||||
|
data: isValid,
|
||||||
|
success: false,
|
||||||
|
message: message,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (response.statusCode == HttpStatus.ok) {
|
if (response.statusCode == HttpStatus.ok) {
|
||||||
isValid = true;
|
isValid = true;
|
||||||
} else if (response.statusCode == HttpStatus.unauthorized) {
|
} else if (response.statusCode == HttpStatus.unauthorized) {
|
||||||
|
@ -86,9 +98,12 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
} else {
|
} else {
|
||||||
throw Exception('code: ${response.statusCode}');
|
throw Exception('code: ${response.statusCode}');
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return isValid;
|
return APIGenericResult(
|
||||||
|
data: isValid,
|
||||||
|
success: true,
|
||||||
|
message: response.statusMessage,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -125,10 +140,10 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<ServerVolume?> createVolume() async {
|
Future<APIGenericResult<ServerVolume?>> createVolume() async {
|
||||||
ServerVolume? volume;
|
ServerVolume? volume;
|
||||||
|
|
||||||
final Response createVolumeResponse;
|
Response? createVolumeResponse;
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
createVolumeResponse = await client.post(
|
createVolumeResponse = await client.post(
|
||||||
|
@ -156,11 +171,21 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
|
return APIGenericResult(
|
||||||
|
data: null,
|
||||||
|
success: false,
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
client.close();
|
client.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
return volume;
|
return APIGenericResult(
|
||||||
|
data: volume,
|
||||||
|
success: true,
|
||||||
|
code: createVolumeResponse.statusCode,
|
||||||
|
message: createVolumeResponse.statusMessage,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -244,13 +269,13 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> attachVolume(
|
Future<APIGenericResult<bool>> attachVolume(
|
||||||
final ServerVolume volume,
|
final ServerVolume volume,
|
||||||
final int serverId,
|
final int serverId,
|
||||||
) async {
|
) async {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
final Response attachVolumeResponse;
|
Response? attachVolumeResponse;
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
attachVolumeResponse = await client.post(
|
attachVolumeResponse = await client.post(
|
||||||
|
@ -268,7 +293,12 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
client.close();
|
client.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return APIGenericResult(
|
||||||
|
data: success,
|
||||||
|
success: true,
|
||||||
|
code: attachVolumeResponse?.statusCode,
|
||||||
|
message: attachVolumeResponse?.statusMessage,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -320,31 +350,33 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<ServerHostingDetails?> createServer({
|
Future<APIGenericResult<ServerHostingDetails?>> createServer({
|
||||||
required final String dnsApiToken,
|
required final String dnsApiToken,
|
||||||
required final User rootUser,
|
required final User rootUser,
|
||||||
required final String domainName,
|
required final String domainName,
|
||||||
required final String serverType,
|
required final String serverType,
|
||||||
}) async {
|
}) async {
|
||||||
ServerHostingDetails? details;
|
final APIGenericResult<ServerVolume?> newVolumeResponse =
|
||||||
|
await createVolume();
|
||||||
|
|
||||||
final ServerVolume? newVolume = await createVolume();
|
if (!newVolumeResponse.success || newVolumeResponse.data == null) {
|
||||||
if (newVolume == null) {
|
return APIGenericResult(
|
||||||
return details;
|
data: null,
|
||||||
|
success: false,
|
||||||
|
message: newVolumeResponse.message,
|
||||||
|
code: newVolumeResponse.code,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
return createServerWithVolume(
|
||||||
details = await createServerWithVolume(
|
|
||||||
dnsApiToken: dnsApiToken,
|
dnsApiToken: dnsApiToken,
|
||||||
rootUser: rootUser,
|
rootUser: rootUser,
|
||||||
domainName: domainName,
|
domainName: domainName,
|
||||||
volume: newVolume,
|
volume: newVolumeResponse.data!,
|
||||||
serverType: serverType,
|
serverType: serverType,
|
||||||
);
|
);
|
||||||
|
|
||||||
return details;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ServerHostingDetails?> createServerWithVolume({
|
Future<APIGenericResult<ServerHostingDetails?>> createServerWithVolume({
|
||||||
required final String dnsApiToken,
|
required final String dnsApiToken,
|
||||||
required final User rootUser,
|
required final User rootUser,
|
||||||
required final String domainName,
|
required final String domainName,
|
||||||
|
@ -366,6 +398,7 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
final String userdataString =
|
final String userdataString =
|
||||||
"#cloud-config\nruncmd:\n- curl https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nixos-infect/raw/branch/$infectBranch/nixos-infect | STAGING_ACME='$stagingAcme' PROVIDER=$infectProviderName NIX_CHANNEL=nixos-21.05 DOMAIN='$domainName' LUSER='${rootUser.login}' ENCODED_PASSWORD='$base64Password' CF_TOKEN=$dnsApiToken DB_PASSWORD=$dbPassword API_TOKEN=$apiToken HOSTNAME=$hostname bash 2>&1 | tee /tmp/infect.log";
|
"#cloud-config\nruncmd:\n- curl https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nixos-infect/raw/branch/$infectBranch/nixos-infect | STAGING_ACME='$stagingAcme' PROVIDER=$infectProviderName NIX_CHANNEL=nixos-21.05 DOMAIN='$domainName' LUSER='${rootUser.login}' ENCODED_PASSWORD='$base64Password' CF_TOKEN=$dnsApiToken DB_PASSWORD=$dbPassword API_TOKEN=$apiToken HOSTNAME=$hostname bash 2>&1 | tee /tmp/infect.log";
|
||||||
|
|
||||||
|
Response? serverCreateResponse;
|
||||||
ServerHostingDetails? serverDetails;
|
ServerHostingDetails? serverDetails;
|
||||||
DioError? hetznerError;
|
DioError? hetznerError;
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
@ -385,7 +418,7 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
};
|
};
|
||||||
print('Decoded data: $data');
|
print('Decoded data: $data');
|
||||||
|
|
||||||
final Response serverCreateResponse = await client.post(
|
serverCreateResponse = await client.post(
|
||||||
'/servers',
|
'/servers',
|
||||||
data: data,
|
data: data,
|
||||||
);
|
);
|
||||||
|
@ -413,11 +446,19 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
await deleteVolume(volume);
|
await deleteVolume(volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hetznerError != null) {
|
String? apiResultMessage = serverCreateResponse?.statusMessage;
|
||||||
throw hetznerError;
|
if (hetznerError != null &&
|
||||||
|
hetznerError.response!.data['error']['code'] == 'uniqueness_error') {
|
||||||
|
apiResultMessage = 'uniqueness_error';
|
||||||
}
|
}
|
||||||
|
|
||||||
return serverDetails;
|
return APIGenericResult(
|
||||||
|
data: serverDetails,
|
||||||
|
success: success && hetznerError == null,
|
||||||
|
code: serverCreateResponse?.statusCode ??
|
||||||
|
hetznerError?.response?.statusCode,
|
||||||
|
message: apiResultMessage,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getHostnameFromDomain(final String domain) {
|
static String getHostnameFromDomain(final String domain) {
|
||||||
|
@ -692,7 +733,8 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<ServerProviderLocation>> getAvailableLocations() async {
|
Future<APIGenericResult<List<ServerProviderLocation>>>
|
||||||
|
getAvailableLocations() async {
|
||||||
List<ServerProviderLocation> locations = [];
|
List<ServerProviderLocation> locations = [];
|
||||||
|
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
|
@ -713,15 +755,20 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
.toList();
|
.toList();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
|
return APIGenericResult(
|
||||||
|
success: false,
|
||||||
|
data: [],
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
return locations;
|
return APIGenericResult(success: true, data: locations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<ServerType>> getServerTypesByLocation({
|
Future<APIGenericResult<List<ServerType>>> getServerTypesByLocation({
|
||||||
required final ServerProviderLocation location,
|
required final ServerProviderLocation location,
|
||||||
}) async {
|
}) async {
|
||||||
final List<ServerType> types = [];
|
final List<ServerType> types = [];
|
||||||
|
@ -754,15 +801,20 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
|
return APIGenericResult(
|
||||||
|
data: [],
|
||||||
|
success: false,
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
return types;
|
return APIGenericResult(data: types, success: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> createReverseDns({
|
Future<APIGenericResult<void>> createReverseDns({
|
||||||
required final ServerHostingDetails serverDetails,
|
required final ServerHostingDetails serverDetails,
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
}) async {
|
}) async {
|
||||||
|
@ -777,8 +829,15 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
|
return APIGenericResult(
|
||||||
|
success: false,
|
||||||
|
data: null,
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return APIGenericResult(success: true, data: null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
|
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||||
|
@ -8,6 +9,8 @@ import 'package:selfprivacy/logic/models/server_metadata.dart';
|
||||||
import 'package:selfprivacy/logic/models/server_provider_location.dart';
|
import 'package:selfprivacy/logic/models/server_provider_location.dart';
|
||||||
import 'package:selfprivacy/logic/models/server_type.dart';
|
import 'package:selfprivacy/logic/models/server_type.dart';
|
||||||
|
|
||||||
|
export 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
|
||||||
|
|
||||||
class ProviderApiTokenValidation {
|
class ProviderApiTokenValidation {
|
||||||
ProviderApiTokenValidation({
|
ProviderApiTokenValidation({
|
||||||
required this.length,
|
required this.length,
|
||||||
|
@ -19,8 +22,9 @@ class ProviderApiTokenValidation {
|
||||||
|
|
||||||
abstract class ServerProviderApi extends ApiMap {
|
abstract class ServerProviderApi extends ApiMap {
|
||||||
Future<List<ServerBasicInfo>> getServers();
|
Future<List<ServerBasicInfo>> getServers();
|
||||||
Future<List<ServerProviderLocation>> getAvailableLocations();
|
Future<APIGenericResult<List<ServerProviderLocation>>>
|
||||||
Future<List<ServerType>> getServerTypesByLocation({
|
getAvailableLocations();
|
||||||
|
Future<APIGenericResult<List<ServerType>>> getServerTypesByLocation({
|
||||||
required final ServerProviderLocation location,
|
required final ServerProviderLocation location,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -28,18 +32,18 @@ abstract class ServerProviderApi extends ApiMap {
|
||||||
Future<ServerHostingDetails> powerOn();
|
Future<ServerHostingDetails> powerOn();
|
||||||
|
|
||||||
Future<void> deleteServer({required final String domainName});
|
Future<void> deleteServer({required final String domainName});
|
||||||
Future<ServerHostingDetails?> createServer({
|
Future<APIGenericResult<ServerHostingDetails?>> createServer({
|
||||||
required final String dnsApiToken,
|
required final String dnsApiToken,
|
||||||
required final User rootUser,
|
required final User rootUser,
|
||||||
required final String domainName,
|
required final String domainName,
|
||||||
required final String serverType,
|
required final String serverType,
|
||||||
});
|
});
|
||||||
Future<void> createReverseDns({
|
Future<APIGenericResult<void>> createReverseDns({
|
||||||
required final ServerHostingDetails serverDetails,
|
required final ServerHostingDetails serverDetails,
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
});
|
});
|
||||||
|
|
||||||
Future<bool> isApiTokenValid(final String token);
|
Future<APIGenericResult<bool>> isApiTokenValid(final String token);
|
||||||
ProviderApiTokenValidation getApiTokenValidation();
|
ProviderApiTokenValidation getApiTokenValidation();
|
||||||
Future<List<ServerMetadataEntity>> getMetadata(final int serverId);
|
Future<List<ServerMetadataEntity>> getMetadata(final int serverId);
|
||||||
Future<ServerMetrics?> getMetrics(
|
Future<ServerMetrics?> getMetrics(
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
|
import 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
|
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
|
||||||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||||
import 'package:selfprivacy/logic/models/price.dart';
|
import 'package:selfprivacy/logic/models/price.dart';
|
||||||
|
|
||||||
|
export 'package:selfprivacy/logic/api_maps/api_generic_result.dart';
|
||||||
|
|
||||||
mixin VolumeProviderApi on ApiMap {
|
mixin VolumeProviderApi on ApiMap {
|
||||||
Future<ServerVolume?> createVolume();
|
Future<APIGenericResult<ServerVolume?>> createVolume();
|
||||||
Future<List<ServerVolume>> getVolumes({final String? status});
|
Future<List<ServerVolume>> getVolumes({final String? status});
|
||||||
Future<bool> attachVolume(final ServerVolume volume, final int serverId);
|
Future<APIGenericResult<bool>> attachVolume(
|
||||||
|
final ServerVolume volume,
|
||||||
|
final int serverId,
|
||||||
|
);
|
||||||
Future<bool> detachVolume(final ServerVolume volume);
|
Future<bool> detachVolume(final ServerVolume volume);
|
||||||
Future<bool> resizeVolume(final ServerVolume volume, final DiskSize size);
|
Future<bool> resizeVolume(final ServerVolume volume, final DiskSize size);
|
||||||
Future<void> deleteVolume(final ServerVolume volume);
|
Future<void> deleteVolume(final ServerVolume volume);
|
||||||
|
|
|
@ -35,7 +35,7 @@ class ApiDevicesCubit
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<ApiToken>?> _getApiTokens() async {
|
Future<List<ApiToken>?> _getApiTokens() async {
|
||||||
final GenericResult<List<ApiToken>> response = await api.getApiTokens();
|
final APIGenericResult<List<ApiToken>> response = await api.getApiTokens();
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
return response.data;
|
return response.data;
|
||||||
} else {
|
} else {
|
||||||
|
@ -44,7 +44,8 @@ class ApiDevicesCubit
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteDevice(final ApiToken device) async {
|
Future<void> deleteDevice(final ApiToken device) async {
|
||||||
final GenericResult<void> response = await api.deleteApiToken(device.name);
|
final APIGenericResult<void> response =
|
||||||
|
await api.deleteApiToken(device.name);
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
emit(
|
emit(
|
||||||
ApiDevicesState(
|
ApiDevicesState(
|
||||||
|
@ -59,7 +60,7 @@ class ApiDevicesCubit
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> getNewDeviceKey() async {
|
Future<String?> getNewDeviceKey() async {
|
||||||
final GenericResult<String> response = await api.createDeviceToken();
|
final APIGenericResult<String> response = await api.createDeviceToken();
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
return response.data;
|
return response.data;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:cubit_form/cubit_form.dart';
|
import 'package:cubit_form/cubit_form.dart';
|
||||||
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/rest_maps/backblaze.dart';
|
import 'package:selfprivacy/logic/api_maps/rest_maps/backblaze.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/backblaze_credential.dart';
|
import 'package:selfprivacy/logic/models/hive/backblaze_credential.dart';
|
||||||
|
@ -7,7 +8,6 @@ import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
class BackblazeFormCubit extends FormCubit {
|
class BackblazeFormCubit extends FormCubit {
|
||||||
BackblazeFormCubit(this.serverInstallationCubit) {
|
BackblazeFormCubit(this.serverInstallationCubit) {
|
||||||
//var regExp = RegExp(r"\s+|[-!$%^&*()@+|~=`{}\[\]:<>?,.\/]");
|
|
||||||
keyId = FieldCubit(
|
keyId = FieldCubit(
|
||||||
initalValue: '',
|
initalValue: '',
|
||||||
validations: [
|
validations: [
|
||||||
|
@ -40,7 +40,7 @@ class BackblazeFormCubit extends FormCubit {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureOr<bool> asyncValidation() async {
|
FutureOr<bool> asyncValidation() async {
|
||||||
late bool isKeyValid;
|
late APIGenericResult<bool> backblazeResponse;
|
||||||
final BackblazeApi apiClient = BackblazeApi(isWithToken: false);
|
final BackblazeApi apiClient = BackblazeApi(isWithToken: false);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -48,18 +48,30 @@ class BackblazeFormCubit extends FormCubit {
|
||||||
keyId.state.value,
|
keyId.state.value,
|
||||||
applicationKey.state.value,
|
applicationKey.state.value,
|
||||||
);
|
);
|
||||||
isKeyValid = await apiClient.isValid(encodedApiKey);
|
backblazeResponse = await apiClient.isApiTokenValid(encodedApiKey);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
addError(e);
|
addError(e);
|
||||||
isKeyValid = false;
|
backblazeResponse = APIGenericResult(
|
||||||
|
success: false,
|
||||||
|
data: false,
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isKeyValid) {
|
if (!backblazeResponse.success) {
|
||||||
keyId.setError('initializing.backblaze_bad_key_error'.tr());
|
getIt<NavigationService>().showSnackBar(
|
||||||
applicationKey.setError('initializing.backblaze_bad_key_error'.tr());
|
'initializing.could_not_connect'.tr(),
|
||||||
|
);
|
||||||
|
keyId.setError('');
|
||||||
|
applicationKey.setError('');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
if (!backblazeResponse.data) {
|
||||||
|
keyId.setError('initializing.backblaze_bad_key_error'.tr());
|
||||||
|
applicationKey.setError('initializing.backblaze_bad_key_error'.tr());
|
||||||
|
}
|
||||||
|
|
||||||
|
return backblazeResponse.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,21 +28,24 @@ class DnsProviderFormCubit extends FormCubit {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureOr<bool> asyncValidation() async {
|
FutureOr<bool> asyncValidation() async {
|
||||||
late bool isKeyValid;
|
bool? isKeyValid;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
isKeyValid = await initializingCubit
|
isKeyValid = await initializingCubit
|
||||||
.isDnsProviderApiTokenValid(apiKey.state.value);
|
.isDnsProviderApiTokenValid(apiKey.state.value);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
addError(e);
|
addError(e);
|
||||||
isKeyValid = false;
|
}
|
||||||
|
|
||||||
|
if (isKeyValid == null) {
|
||||||
|
apiKey.setError('');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isKeyValid) {
|
if (!isKeyValid) {
|
||||||
apiKey.setError('initializing.cloudflare_bad_key_error'.tr());
|
apiKey.setError('initializing.cloudflare_bad_key_error'.tr());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return isKeyValid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,21 +29,24 @@ class ProviderFormCubit extends FormCubit {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureOr<bool> asyncValidation() async {
|
FutureOr<bool> asyncValidation() async {
|
||||||
late bool isKeyValid;
|
bool? isKeyValid;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
isKeyValid = await serverInstallationCubit
|
isKeyValid = await serverInstallationCubit
|
||||||
.isServerProviderApiTokenValid(apiKey.state.value);
|
.isServerProviderApiTokenValid(apiKey.state.value);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
addError(e);
|
addError(e);
|
||||||
isKeyValid = false;
|
}
|
||||||
|
|
||||||
|
if (isKeyValid == null) {
|
||||||
|
apiKey.setError('');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isKeyValid) {
|
if (!isKeyValid) {
|
||||||
apiKey.setError('initializing.provider_bad_key_error'.tr());
|
apiKey.setError('initializing.provider_bad_key_error'.tr());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return isKeyValid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,10 +113,11 @@ class ApiProviderVolumeCubit
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> createVolume() async {
|
Future<void> createVolume() async {
|
||||||
final ServerVolume? volume = await ApiController
|
final ServerVolume? volume = (await ApiController
|
||||||
.currentVolumeProviderApiFactory!
|
.currentVolumeProviderApiFactory!
|
||||||
.getVolumeProvider()
|
.getVolumeProvider()
|
||||||
.createVolume();
|
.createVolume())
|
||||||
|
.data;
|
||||||
|
|
||||||
final diskVolume = DiskVolume(providerVolume: volume);
|
final diskVolume = DiskVolume(providerVolume: volume);
|
||||||
await attachVolume(diskVolume);
|
await attachVolume(diskVolume);
|
||||||
|
|
|
@ -32,7 +32,7 @@ class RecoveryKeyCubit
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<RecoveryKeyStatus?> _getRecoveryKeyStatus() async {
|
Future<RecoveryKeyStatus?> _getRecoveryKeyStatus() async {
|
||||||
final GenericResult<RecoveryKeyStatus?> response =
|
final APIGenericResult<RecoveryKeyStatus?> response =
|
||||||
await api.getRecoveryTokenStatus();
|
await api.getRecoveryTokenStatus();
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
return response.data;
|
return response.data;
|
||||||
|
@ -57,7 +57,7 @@ class RecoveryKeyCubit
|
||||||
final DateTime? expirationDate,
|
final DateTime? expirationDate,
|
||||||
final int? numberOfUses,
|
final int? numberOfUses,
|
||||||
}) async {
|
}) async {
|
||||||
final GenericResult<String> response =
|
final APIGenericResult<String> response =
|
||||||
await api.generateRecoveryToken(expirationDate, numberOfUses);
|
await api.generateRecoveryToken(expirationDate, numberOfUses);
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
refresh();
|
refresh();
|
||||||
|
|
|
@ -76,10 +76,11 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
.getDnsProvider()
|
.getDnsProvider()
|
||||||
.getApiTokenValidation();
|
.getApiTokenValidation();
|
||||||
|
|
||||||
Future<bool> isServerProviderApiTokenValid(
|
Future<bool?> isServerProviderApiTokenValid(
|
||||||
final String providerToken,
|
final String providerToken,
|
||||||
) async =>
|
) async {
|
||||||
ApiController.currentServerProviderApiFactory!
|
final APIGenericResult<bool> apiResponse =
|
||||||
|
await ApiController.currentServerProviderApiFactory!
|
||||||
.getServerProvider(
|
.getServerProvider(
|
||||||
settings: const ServerProviderApiSettings(
|
settings: const ServerProviderApiSettings(
|
||||||
isWithToken: false,
|
isWithToken: false,
|
||||||
|
@ -87,7 +88,17 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
)
|
)
|
||||||
.isApiTokenValid(providerToken);
|
.isApiTokenValid(providerToken);
|
||||||
|
|
||||||
Future<bool> isDnsProviderApiTokenValid(
|
if (!apiResponse.success) {
|
||||||
|
getIt<NavigationService>().showSnackBar(
|
||||||
|
'initializing.could_not_connect'.tr(),
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiResponse.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool?> isDnsProviderApiTokenValid(
|
||||||
final String providerToken,
|
final String providerToken,
|
||||||
) async {
|
) async {
|
||||||
if (ApiController.currentDnsProviderApiFactory == null) {
|
if (ApiController.currentDnsProviderApiFactory == null) {
|
||||||
|
@ -100,11 +111,21 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ApiController.currentDnsProviderApiFactory!
|
final APIGenericResult<bool> apiResponse =
|
||||||
|
await ApiController.currentDnsProviderApiFactory!
|
||||||
.getDnsProvider(
|
.getDnsProvider(
|
||||||
settings: const DnsProviderApiSettings(isWithToken: false),
|
settings: const DnsProviderApiSettings(isWithToken: false),
|
||||||
)
|
)
|
||||||
.isApiTokenValid(providerToken);
|
.isApiTokenValid(providerToken);
|
||||||
|
|
||||||
|
if (!apiResponse.success) {
|
||||||
|
getIt<NavigationService>().showSnackBar(
|
||||||
|
'initializing.could_not_connect'.tr(),
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiResponse.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<ServerProviderLocation>> fetchAvailableLocations() async {
|
Future<List<ServerProviderLocation>> fetchAvailableLocations() async {
|
||||||
|
@ -112,9 +133,18 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ApiController.currentServerProviderApiFactory!
|
final APIGenericResult apiResult = await ApiController
|
||||||
|
.currentServerProviderApiFactory!
|
||||||
.getServerProvider()
|
.getServerProvider()
|
||||||
.getAvailableLocations();
|
.getAvailableLocations();
|
||||||
|
|
||||||
|
if (!apiResult.success) {
|
||||||
|
getIt<NavigationService>().showSnackBar(
|
||||||
|
'initializing.could_not_connect'.tr(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiResult.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<ServerType>> fetchAvailableTypesByLocation(
|
Future<List<ServerType>> fetchAvailableTypesByLocation(
|
||||||
|
@ -124,9 +154,18 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ApiController.currentServerProviderApiFactory!
|
final APIGenericResult apiResult = await ApiController
|
||||||
|
.currentServerProviderApiFactory!
|
||||||
.getServerProvider()
|
.getServerProvider()
|
||||||
.getServerTypesByLocation(location: location);
|
.getServerTypesByLocation(location: location);
|
||||||
|
|
||||||
|
if (!apiResult.success) {
|
||||||
|
getIt<NavigationService>().showSnackBar(
|
||||||
|
'initializing.could_not_connect'.tr(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiResult.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setServerProviderKey(final String serverProviderKey) async {
|
void setServerProviderKey(final String serverProviderKey) async {
|
||||||
|
|
|
@ -75,13 +75,12 @@ class ServerInstallationRepository {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serverDomain != null && serverDomain.provider != DnsProvider.unknown) {
|
// No other DNS provider is supported for now, so it's fine.
|
||||||
ApiController.initDnsProviderApiFactory(
|
ApiController.initDnsProviderApiFactory(
|
||||||
DnsProviderApiFactorySettings(
|
DnsProviderApiFactorySettings(
|
||||||
provider: serverDomain.provider,
|
provider: DnsProvider.cloudflare,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
if (box.get(BNames.hasFinalChecked, defaultValue: false)) {
|
if (box.get(BNames.hasFinalChecked, defaultValue: false)) {
|
||||||
return ServerInstallationFinished(
|
return ServerInstallationFinished(
|
||||||
|
@ -247,22 +246,52 @@ class ServerInstallationRepository {
|
||||||
}) async {
|
}) async {
|
||||||
final ServerProviderApi api =
|
final ServerProviderApi api =
|
||||||
ApiController.currentServerProviderApiFactory!.getServerProvider();
|
ApiController.currentServerProviderApiFactory!.getServerProvider();
|
||||||
|
|
||||||
|
void showInstallationErrorPopUp() {
|
||||||
|
showPopUpAlert(
|
||||||
|
alertTitle: 'modals.unexpected_error'.tr(),
|
||||||
|
description: 'modals.try_again'.tr(),
|
||||||
|
actionButtonTitle: 'modals.yes'.tr(),
|
||||||
|
actionButtonOnPressed: () async {
|
||||||
|
ServerHostingDetails? serverDetails;
|
||||||
try {
|
try {
|
||||||
final ServerHostingDetails? serverDetails = await api.createServer(
|
final APIGenericResult createResult = await api.createServer(
|
||||||
|
dnsApiToken: cloudFlareKey,
|
||||||
|
rootUser: rootUser,
|
||||||
|
domainName: domainName,
|
||||||
|
serverType: getIt<ApiConfigModel>().serverType!,
|
||||||
|
);
|
||||||
|
serverDetails = createResult.data;
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serverDetails == null) {
|
||||||
|
print('Server is not initialized!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await saveServerDetails(serverDetails);
|
||||||
|
onSuccess(serverDetails);
|
||||||
|
},
|
||||||
|
cancelButtonOnPressed: onCancel,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final APIGenericResult<ServerHostingDetails?> createServerResult =
|
||||||
|
await api.createServer(
|
||||||
dnsApiToken: cloudFlareKey,
|
dnsApiToken: cloudFlareKey,
|
||||||
rootUser: rootUser,
|
rootUser: rootUser,
|
||||||
domainName: domainName,
|
domainName: domainName,
|
||||||
serverType: getIt<ApiConfigModel>().serverType!,
|
serverType: getIt<ApiConfigModel>().serverType!,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (serverDetails == null) {
|
if (createServerResult.data == null) {
|
||||||
print('Server is not initialized!');
|
const String e = 'Server is not initialized!';
|
||||||
return;
|
print(e);
|
||||||
}
|
}
|
||||||
saveServerDetails(serverDetails);
|
|
||||||
onSuccess(serverDetails);
|
if (createServerResult.message == 'uniqueness_error') {
|
||||||
} on DioError catch (e) {
|
|
||||||
if (e.response!.data['error']['code'] == 'uniqueness_error') {
|
|
||||||
showPopUpAlert(
|
showPopUpAlert(
|
||||||
alertTitle: 'modals.already_exists'.tr(),
|
alertTitle: 'modals.already_exists'.tr(),
|
||||||
description: 'modals.destroy_server'.tr(),
|
description: 'modals.destroy_server'.tr(),
|
||||||
|
@ -274,12 +303,13 @@ class ServerInstallationRepository {
|
||||||
|
|
||||||
ServerHostingDetails? serverDetails;
|
ServerHostingDetails? serverDetails;
|
||||||
try {
|
try {
|
||||||
serverDetails = await api.createServer(
|
final APIGenericResult createResult = await api.createServer(
|
||||||
dnsApiToken: cloudFlareKey,
|
dnsApiToken: cloudFlareKey,
|
||||||
rootUser: rootUser,
|
rootUser: rootUser,
|
||||||
domainName: domainName,
|
domainName: domainName,
|
||||||
serverType: getIt<ApiConfigModel>().serverType!,
|
serverType: getIt<ApiConfigModel>().serverType!,
|
||||||
);
|
);
|
||||||
|
serverDetails = createResult.data;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
}
|
}
|
||||||
|
@ -293,34 +323,14 @@ class ServerInstallationRepository {
|
||||||
},
|
},
|
||||||
cancelButtonOnPressed: onCancel,
|
cancelButtonOnPressed: onCancel,
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
showPopUpAlert(
|
|
||||||
alertTitle: 'modals.unexpected_error'.tr(),
|
|
||||||
description: 'modals.try_again'.tr(),
|
|
||||||
actionButtonTitle: 'modals.yes'.tr(),
|
|
||||||
actionButtonOnPressed: () async {
|
|
||||||
ServerHostingDetails? serverDetails;
|
|
||||||
try {
|
|
||||||
serverDetails = await api.createServer(
|
|
||||||
dnsApiToken: cloudFlareKey,
|
|
||||||
rootUser: rootUser,
|
|
||||||
domainName: domainName,
|
|
||||||
serverType: getIt<ApiConfigModel>().serverType!,
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
print(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (serverDetails == null) {
|
|
||||||
print('Server is not initialized!');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await saveServerDetails(serverDetails);
|
|
||||||
onSuccess(serverDetails);
|
saveServerDetails(createServerResult.data!);
|
||||||
},
|
onSuccess(createServerResult.data!);
|
||||||
cancelButtonOnPressed: onCancel,
|
} catch (e) {
|
||||||
);
|
print(e);
|
||||||
}
|
showInstallationErrorPopUp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,21 +344,9 @@ class ServerInstallationRepository {
|
||||||
final ServerProviderApi serverApi =
|
final ServerProviderApi serverApi =
|
||||||
ApiController.currentServerProviderApiFactory!.getServerProvider();
|
ApiController.currentServerProviderApiFactory!.getServerProvider();
|
||||||
|
|
||||||
await dnsProviderApi.removeSimilarRecords(
|
void showDomainErrorPopUp(final String error) {
|
||||||
ip4: serverDetails.ip4,
|
|
||||||
domain: domain,
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await dnsProviderApi.createMultipleDnsRecords(
|
|
||||||
ip4: serverDetails.ip4,
|
|
||||||
domain: domain,
|
|
||||||
);
|
|
||||||
} on DioError catch (e) {
|
|
||||||
showPopUpAlert(
|
showPopUpAlert(
|
||||||
alertTitle: e.response!.data['errors'][0]['code'] == 1038
|
alertTitle: error,
|
||||||
? 'modals.you_cant_use_this_api'.tr()
|
|
||||||
: 'domain.error'.tr(),
|
|
||||||
description: 'modals.delete_server_volume'.tr(),
|
description: 'modals.delete_server_volume'.tr(),
|
||||||
cancelButtonOnPressed: onCancel,
|
cancelButtonOnPressed: onCancel,
|
||||||
actionButtonTitle: 'basis.delete'.tr(),
|
actionButtonTitle: 'basis.delete'.tr(),
|
||||||
|
@ -359,14 +357,50 @@ class ServerInstallationRepository {
|
||||||
onCancel();
|
onCancel();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final APIGenericResult removingResult =
|
||||||
|
await dnsProviderApi.removeSimilarRecords(
|
||||||
|
ip4: serverDetails.ip4,
|
||||||
|
domain: domain,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!removingResult.success) {
|
||||||
|
showDomainErrorPopUp('domain.error'.tr());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool createdSuccessfully = false;
|
||||||
|
String errorMessage = 'domain.error'.tr();
|
||||||
|
try {
|
||||||
|
final APIGenericResult createResult =
|
||||||
|
await dnsProviderApi.createMultipleDnsRecords(
|
||||||
|
ip4: serverDetails.ip4,
|
||||||
|
domain: domain,
|
||||||
|
);
|
||||||
|
createdSuccessfully = createResult.success;
|
||||||
|
} on DioError catch (e) {
|
||||||
|
if (e.response!.data['errors'][0]['code'] == 1038) {
|
||||||
|
errorMessage = 'modals.you_cant_use_this_api'.tr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!createdSuccessfully) {
|
||||||
|
showDomainErrorPopUp(errorMessage);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final APIGenericResult createReverseResult =
|
||||||
await serverApi.createReverseDns(
|
await serverApi.createReverseDns(
|
||||||
serverDetails: serverDetails,
|
serverDetails: serverDetails,
|
||||||
domain: domain,
|
domain: domain,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!createReverseResult.success) {
|
||||||
|
showDomainErrorPopUp(errorMessage);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,7 +513,7 @@ class ServerInstallationRepository {
|
||||||
overrideDomain: serverDomain.domainName,
|
overrideDomain: serverDomain.domainName,
|
||||||
);
|
);
|
||||||
final String serverIp = await getServerIpFromDomain(serverDomain);
|
final String serverIp = await getServerIpFromDomain(serverDomain);
|
||||||
final GenericResult<String> result = await serverApi.authorizeDevice(
|
final APIGenericResult<String> result = await serverApi.authorizeDevice(
|
||||||
DeviceToken(device: await getDeviceName(), token: newDeviceKey),
|
DeviceToken(device: await getDeviceName(), token: newDeviceKey),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -516,7 +550,7 @@ class ServerInstallationRepository {
|
||||||
overrideDomain: serverDomain.domainName,
|
overrideDomain: serverDomain.domainName,
|
||||||
);
|
);
|
||||||
final String serverIp = await getServerIpFromDomain(serverDomain);
|
final String serverIp = await getServerIpFromDomain(serverDomain);
|
||||||
final GenericResult<String> result = await serverApi.useRecoveryToken(
|
final APIGenericResult<String> result = await serverApi.useRecoveryToken(
|
||||||
DeviceToken(device: await getDeviceName(), token: recoveryKey),
|
DeviceToken(device: await getDeviceName(), token: recoveryKey),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -577,9 +611,9 @@ class ServerInstallationRepository {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final GenericResult<String> deviceAuthKey =
|
final APIGenericResult<String> deviceAuthKey =
|
||||||
await serverApi.createDeviceToken();
|
await serverApi.createDeviceToken();
|
||||||
final GenericResult<String> result = await serverApi.authorizeDevice(
|
final APIGenericResult<String> result = await serverApi.authorizeDevice(
|
||||||
DeviceToken(device: await getDeviceName(), token: deviceAuthKey.data),
|
DeviceToken(device: await getDeviceName(), token: deviceAuthKey.data),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// If API returned error, do nothing
|
// If API returned error, do nothing
|
||||||
final GenericMutationResult<User?> result =
|
final APIGenericResult<User?> result =
|
||||||
await api.createUser(user.login, password);
|
await api.createUser(user.login, password);
|
||||||
if (result.data == null) {
|
if (result.data == null) {
|
||||||
getIt<NavigationService>()
|
getIt<NavigationService>()
|
||||||
|
@ -101,7 +101,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final List<User> loadedUsers = List<User>.from(state.users);
|
final List<User> loadedUsers = List<User>.from(state.users);
|
||||||
final GenericMutationResult result = await api.deleteUser(user.login);
|
final APIGenericResult result = await api.deleteUser(user.login);
|
||||||
if (result.success && result.data) {
|
if (result.success && result.data) {
|
||||||
loadedUsers.removeWhere((final User u) => u.login == user.login);
|
loadedUsers.removeWhere((final User u) => u.login == user.login);
|
||||||
await box.clear();
|
await box.clear();
|
||||||
|
@ -128,7 +128,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
||||||
.showSnackBar('users.could_not_change_password'.tr());
|
.showSnackBar('users.could_not_change_password'.tr());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final GenericMutationResult<User?> result =
|
final APIGenericResult<User?> result =
|
||||||
await api.updateUser(user.login, newPassword);
|
await api.updateUser(user.login, newPassword);
|
||||||
if (result.data == null) {
|
if (result.data == null) {
|
||||||
getIt<NavigationService>().showSnackBar(
|
getIt<NavigationService>().showSnackBar(
|
||||||
|
@ -138,7 +138,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> addSshKey(final User user, final String publicKey) async {
|
Future<void> addSshKey(final User user, final String publicKey) async {
|
||||||
final GenericMutationResult<User?> result =
|
final APIGenericResult<User?> result =
|
||||||
await api.addSshKey(user.login, publicKey);
|
await api.addSshKey(user.login, publicKey);
|
||||||
if (result.data != null) {
|
if (result.data != null) {
|
||||||
final User updatedUser = result.data!;
|
final User updatedUser = result.data!;
|
||||||
|
@ -157,7 +157,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteSshKey(final User user, final String publicKey) async {
|
Future<void> deleteSshKey(final User user, final String publicKey) async {
|
||||||
final GenericMutationResult<User?> result =
|
final APIGenericResult<User?> result =
|
||||||
await api.removeSshKey(user.login, publicKey);
|
await api.removeSshKey(user.login, publicKey);
|
||||||
if (result.data != null) {
|
if (result.data != null) {
|
||||||
final User updatedUser = result.data!;
|
final User updatedUser = result.data!;
|
||||||
|
|
|
@ -77,7 +77,7 @@ class InitializingPage extends StatelessWidget {
|
||||||
'Domain',
|
'Domain',
|
||||||
'User',
|
'User',
|
||||||
'Server',
|
'Server',
|
||||||
'Check',
|
'Installation',
|
||||||
],
|
],
|
||||||
activeIndex: cubit.state.porgressBar,
|
activeIndex: cubit.state.porgressBar,
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue