chore: Continue refactoring

- Rename APIGenericResult to GenericResult
- Wrap all provider functions results with GenericResult
- Move basic server commands and getters to business logic layer from API on Hetzner
pull/213/head
NaiJi ✨ 2023-02-13 18:13:32 +04:00
parent efe4f620ee
commit bad6926567
24 changed files with 634 additions and 489 deletions

View File

@ -1,5 +1,5 @@
class APIGenericResult<T> { class GenericResult<T> {
APIGenericResult({ GenericResult({
required this.success, required this.success,
required this.data, required this.data,
this.message, this.message,

View File

@ -22,13 +22,13 @@ mixin JobsApi on ApiMap {
return jobsList; return jobsList;
} }
Future<APIGenericResult<bool>> removeApiJob(final String uid) async { Future<GenericResult<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 APIGenericResult( return GenericResult(
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 APIGenericResult( return GenericResult(
data: false, data: false,
success: false, success: false,
code: 0, code: 0,

View File

@ -1,6 +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/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';
@ -24,7 +24,7 @@ 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'; export 'package:selfprivacy/logic/api_maps/generic_result.dart';
part 'jobs_api.dart'; part 'jobs_api.dart';
part 'server_actions_api.dart'; part 'server_actions_api.dart';
@ -205,7 +205,7 @@ class ServerApi extends ApiMap
return settings; return settings;
} }
Future<APIGenericResult<RecoveryKeyStatus?>> getRecoveryTokenStatus() async { Future<GenericResult<RecoveryKeyStatus?>> getRecoveryTokenStatus() async {
RecoveryKeyStatus? key; RecoveryKeyStatus? key;
QueryResult<Query$RecoveryKey> response; QueryResult<Query$RecoveryKey> response;
String? error; String? error;
@ -222,18 +222,18 @@ class ServerApi extends ApiMap
print(e); print(e);
} }
return APIGenericResult<RecoveryKeyStatus?>( return GenericResult<RecoveryKeyStatus?>(
success: error == null, success: error == null,
data: key, data: key,
message: error, message: error,
); );
} }
Future<APIGenericResult<String>> generateRecoveryToken( Future<GenericResult<String>> generateRecoveryToken(
final DateTime? expirationDate, final DateTime? expirationDate,
final int? numberOfUses, final int? numberOfUses,
) async { ) async {
APIGenericResult<String> key; GenericResult<String> key;
QueryResult<Mutation$GetNewRecoveryApiKey> response; QueryResult<Mutation$GetNewRecoveryApiKey> response;
try { try {
@ -254,19 +254,19 @@ class ServerApi extends ApiMap
); );
if (response.hasException) { if (response.hasException) {
print(response.exception.toString()); print(response.exception.toString());
key = APIGenericResult<String>( key = GenericResult<String>(
success: false, success: false,
data: '', data: '',
message: response.exception.toString(), message: response.exception.toString(),
); );
} }
key = APIGenericResult<String>( key = GenericResult<String>(
success: true, success: true,
data: response.parsedData!.getNewRecoveryApiKey.key!, data: response.parsedData!.getNewRecoveryApiKey.key!,
); );
} catch (e) { } catch (e) {
print(e); print(e);
key = APIGenericResult<String>( key = GenericResult<String>(
success: false, success: false,
data: '', data: '',
message: e.toString(), message: e.toString(),
@ -299,8 +299,8 @@ class ServerApi extends ApiMap
return records; return records;
} }
Future<APIGenericResult<List<ApiToken>>> getApiTokens() async { Future<GenericResult<List<ApiToken>>> getApiTokens() async {
APIGenericResult<List<ApiToken>> tokens; GenericResult<List<ApiToken>> tokens;
QueryResult<Query$GetApiTokens> response; QueryResult<Query$GetApiTokens> response;
try { try {
@ -309,7 +309,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 = APIGenericResult<List<ApiToken>>( tokens = GenericResult<List<ApiToken>>(
success: false, success: false,
data: [], data: [],
message: message, message: message,
@ -323,13 +323,13 @@ class ServerApi extends ApiMap
ApiToken.fromGraphQL(device), ApiToken.fromGraphQL(device),
) )
.toList(); .toList();
tokens = APIGenericResult<List<ApiToken>>( tokens = GenericResult<List<ApiToken>>(
success: true, success: true,
data: parsed, data: parsed,
); );
} catch (e) { } catch (e) {
print(e); print(e);
tokens = APIGenericResult<List<ApiToken>>( tokens = GenericResult<List<ApiToken>>(
success: false, success: false,
data: [], data: [],
message: e.toString(), message: e.toString(),
@ -339,8 +339,8 @@ class ServerApi extends ApiMap
return tokens; return tokens;
} }
Future<APIGenericResult<void>> deleteApiToken(final String name) async { Future<GenericResult<void>> deleteApiToken(final String name) async {
APIGenericResult<void> returnable; GenericResult<void> returnable;
QueryResult<Mutation$DeleteDeviceApiToken> response; QueryResult<Mutation$DeleteDeviceApiToken> response;
try { try {
@ -357,19 +357,19 @@ class ServerApi extends ApiMap
); );
if (response.hasException) { if (response.hasException) {
print(response.exception.toString()); print(response.exception.toString());
returnable = APIGenericResult<void>( returnable = GenericResult<void>(
success: false, success: false,
data: null, data: null,
message: response.exception.toString(), message: response.exception.toString(),
); );
} }
returnable = APIGenericResult<void>( returnable = GenericResult<void>(
success: true, success: true,
data: null, data: null,
); );
} catch (e) { } catch (e) {
print(e); print(e);
returnable = APIGenericResult<void>( returnable = GenericResult<void>(
success: false, success: false,
data: null, data: null,
message: e.toString(), message: e.toString(),
@ -379,8 +379,8 @@ class ServerApi extends ApiMap
return returnable; return returnable;
} }
Future<APIGenericResult<String>> createDeviceToken() async { Future<GenericResult<String>> createDeviceToken() async {
APIGenericResult<String> token; GenericResult<String> token;
QueryResult<Mutation$GetNewDeviceApiKey> response; QueryResult<Mutation$GetNewDeviceApiKey> response;
try { try {
@ -392,19 +392,19 @@ class ServerApi extends ApiMap
); );
if (response.hasException) { if (response.hasException) {
print(response.exception.toString()); print(response.exception.toString());
token = APIGenericResult<String>( token = GenericResult<String>(
success: false, success: false,
data: '', data: '',
message: response.exception.toString(), message: response.exception.toString(),
); );
} }
token = APIGenericResult<String>( token = GenericResult<String>(
success: true, success: true,
data: response.parsedData!.getNewDeviceApiKey.key!, data: response.parsedData!.getNewDeviceApiKey.key!,
); );
} catch (e) { } catch (e) {
print(e); print(e);
token = APIGenericResult<String>( token = GenericResult<String>(
success: false, success: false,
data: '', data: '',
message: e.toString(), message: e.toString(),
@ -416,10 +416,10 @@ class ServerApi extends ApiMap
Future<bool> isHttpServerWorking() async => (await getApiVersion()) != null; Future<bool> isHttpServerWorking() async => (await getApiVersion()) != null;
Future<APIGenericResult<String>> authorizeDevice( Future<GenericResult<String>> authorizeDevice(
final DeviceToken deviceToken, final DeviceToken deviceToken,
) async { ) async {
APIGenericResult<String> token; GenericResult<String> token;
QueryResult<Mutation$AuthorizeWithNewDeviceApiKey> response; QueryResult<Mutation$AuthorizeWithNewDeviceApiKey> response;
try { try {
@ -441,19 +441,19 @@ class ServerApi extends ApiMap
); );
if (response.hasException) { if (response.hasException) {
print(response.exception.toString()); print(response.exception.toString());
token = APIGenericResult<String>( token = GenericResult<String>(
success: false, success: false,
data: '', data: '',
message: response.exception.toString(), message: response.exception.toString(),
); );
} }
token = APIGenericResult<String>( token = GenericResult<String>(
success: true, success: true,
data: response.parsedData!.authorizeWithNewDeviceApiKey.token!, data: response.parsedData!.authorizeWithNewDeviceApiKey.token!,
); );
} catch (e) { } catch (e) {
print(e); print(e);
token = APIGenericResult<String>( token = GenericResult<String>(
success: false, success: false,
data: '', data: '',
message: e.toString(), message: e.toString(),
@ -463,10 +463,10 @@ class ServerApi extends ApiMap
return token; return token;
} }
Future<APIGenericResult<String>> useRecoveryToken( Future<GenericResult<String>> useRecoveryToken(
final DeviceToken deviceToken, final DeviceToken deviceToken,
) async { ) async {
APIGenericResult<String> token; GenericResult<String> token;
QueryResult<Mutation$UseRecoveryApiKey> response; QueryResult<Mutation$UseRecoveryApiKey> response;
try { try {
@ -488,19 +488,19 @@ class ServerApi extends ApiMap
); );
if (response.hasException) { if (response.hasException) {
print(response.exception.toString()); print(response.exception.toString());
token = APIGenericResult<String>( token = GenericResult<String>(
success: false, success: false,
data: '', data: '',
message: response.exception.toString(), message: response.exception.toString(),
); );
} }
token = APIGenericResult<String>( token = GenericResult<String>(
success: true, success: true,
data: response.parsedData!.useRecoveryApiKey.token!, data: response.parsedData!.useRecoveryApiKey.token!,
); );
} catch (e) { } catch (e) {
print(e); print(e);
token = APIGenericResult<String>( token = GenericResult<String>(
success: false, success: false,
data: '', data: '',
message: e.toString(), message: e.toString(),

View File

@ -20,7 +20,7 @@ mixin ServicesApi on ApiMap {
return services; return services;
} }
Future<APIGenericResult<bool>> enableService( Future<GenericResult<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 APIGenericResult( return GenericResult(
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 APIGenericResult( return GenericResult(
data: false, data: false,
success: false, success: false,
code: 0, code: 0,
@ -45,7 +45,7 @@ mixin ServicesApi on ApiMap {
} }
} }
Future<APIGenericResult<void>> disableService( Future<GenericResult<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 APIGenericResult( return GenericResult(
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 APIGenericResult( return GenericResult(
data: null, data: null,
success: false, success: false,
code: 0, code: 0,
@ -70,7 +70,7 @@ mixin ServicesApi on ApiMap {
} }
} }
Future<APIGenericResult<bool>> stopService( Future<GenericResult<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 APIGenericResult( return GenericResult(
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 APIGenericResult( return GenericResult(
data: false, data: false,
success: false, success: false,
code: 0, code: 0,
@ -95,13 +95,13 @@ mixin ServicesApi on ApiMap {
} }
} }
Future<APIGenericResult> startService(final String serviceId) async { Future<GenericResult> 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 APIGenericResult( return GenericResult(
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 APIGenericResult( return GenericResult(
data: null, data: null,
success: false, success: false,
code: 0, code: 0,
@ -118,7 +118,7 @@ mixin ServicesApi on ApiMap {
} }
} }
Future<APIGenericResult<bool>> restartService( Future<GenericResult<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 APIGenericResult( return GenericResult(
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 APIGenericResult( return GenericResult(
data: false, data: false,
success: false, success: false,
code: 0, code: 0,
@ -143,7 +143,7 @@ mixin ServicesApi on ApiMap {
} }
} }
Future<APIGenericResult<ServerJob?>> moveService( Future<GenericResult<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 APIGenericResult( return GenericResult(
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 APIGenericResult( return GenericResult(
success: false, success: false,
code: 0, code: 0,
message: e.toString(), message: e.toString(),

View File

@ -45,7 +45,7 @@ mixin UsersApi on ApiMap {
return user; return user;
} }
Future<APIGenericResult<User?>> createUser( Future<GenericResult<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 APIGenericResult( return GenericResult(
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 APIGenericResult( return GenericResult(
success: false, success: false,
code: 0, code: 0,
message: e.toString(), message: e.toString(),
@ -75,7 +75,7 @@ mixin UsersApi on ApiMap {
} }
} }
Future<APIGenericResult<bool>> deleteUser( Future<GenericResult<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 APIGenericResult( return GenericResult(
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 APIGenericResult( return GenericResult(
data: false, data: false,
success: false, success: false,
code: 500, code: 500,
@ -100,7 +100,7 @@ mixin UsersApi on ApiMap {
} }
} }
Future<APIGenericResult<User?>> updateUser( Future<GenericResult<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 APIGenericResult( return GenericResult(
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 APIGenericResult( return GenericResult(
data: null, data: null,
success: false, success: false,
code: 0, code: 0,
@ -130,7 +130,7 @@ mixin UsersApi on ApiMap {
} }
} }
Future<APIGenericResult<User?>> addSshKey( Future<GenericResult<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 APIGenericResult( return GenericResult(
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 APIGenericResult( return GenericResult(
data: null, data: null,
success: false, success: false,
code: 0, code: 0,
@ -163,7 +163,7 @@ mixin UsersApi on ApiMap {
} }
} }
Future<APIGenericResult<User?>> removeSshKey( Future<GenericResult<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 APIGenericResult( return GenericResult(
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 APIGenericResult( return GenericResult(
data: null, data: null,
success: false, success: false,
code: 0, code: 0,

View File

@ -57,10 +57,10 @@ mixin VolumeApi on ApiMap {
} }
} }
Future<APIGenericResult<String?>> migrateToBinds( Future<GenericResult<String?>> migrateToBinds(
final Map<String, String> serviceToDisk, final Map<String, String> serviceToDisk,
) async { ) async {
APIGenericResult<String?>? mutation; GenericResult<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 = APIGenericResult( mutation = mutation = GenericResult(
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 = APIGenericResult( mutation = GenericResult(
success: false, success: false,
code: 0, code: 0,
message: e.toString(), message: e.toString(),

View File

@ -2,11 +2,11 @@ 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/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'; export 'package:selfprivacy/logic/api_maps/generic_result.dart';
class BackblazeApiAuth { class BackblazeApiAuth {
BackblazeApiAuth({required this.authorizationToken, required this.apiUrl}); BackblazeApiAuth({required this.authorizationToken, required this.apiUrl});
@ -74,7 +74,7 @@ class BackblazeApi extends ApiMap {
); );
} }
Future<APIGenericResult<bool>> isApiTokenValid( Future<GenericResult<bool>> isApiTokenValid(
final String encodedApiKey, final String encodedApiKey,
) async { ) async {
final Dio client = await getClient(); final Dio client = await getClient();
@ -99,7 +99,7 @@ class BackblazeApi extends ApiMap {
} }
} on DioError catch (e) { } on DioError catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
data: false, data: false,
success: false, success: false,
message: e.toString(), message: e.toString(),
@ -108,7 +108,7 @@ class BackblazeApi extends ApiMap {
close(client); close(client);
} }
return APIGenericResult( return GenericResult(
data: isTokenValid, data: isTokenValid,
success: true, success: true,
); );

View File

@ -46,7 +46,7 @@ class CloudflareApi extends DnsProviderApi {
String rootAddress = 'https://api.cloudflare.com/client/v4'; String rootAddress = 'https://api.cloudflare.com/client/v4';
@override @override
Future<APIGenericResult<bool>> isApiTokenValid(final String token) async { Future<GenericResult<bool>> isApiTokenValid(final String token) async {
bool isValid = false; bool isValid = false;
Response? response; Response? response;
String message = ''; String message = '';
@ -70,7 +70,7 @@ class CloudflareApi extends DnsProviderApi {
} }
if (response == null) { if (response == null) {
return APIGenericResult( return GenericResult(
data: isValid, data: isValid,
success: false, success: false,
message: message, message: message,
@ -85,7 +85,7 @@ class CloudflareApi extends DnsProviderApi {
throw Exception('code: ${response.statusCode}'); throw Exception('code: ${response.statusCode}');
} }
return APIGenericResult( return GenericResult(
data: isValid, data: isValid,
success: true, success: true,
message: response.statusMessage, message: response.statusMessage,
@ -113,7 +113,7 @@ class CloudflareApi extends DnsProviderApi {
} }
@override @override
Future<APIGenericResult<void>> removeSimilarRecords({ Future<GenericResult<void>> removeSimilarRecords({
required final ServerDomain domain, required final ServerDomain domain,
final String? ip4, final String? ip4,
}) async { }) async {
@ -139,7 +139,7 @@ class CloudflareApi extends DnsProviderApi {
await Future.wait(allDeleteFutures); await Future.wait(allDeleteFutures);
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
success: false, success: false,
data: null, data: null,
message: e.toString(), message: e.toString(),
@ -148,7 +148,7 @@ class CloudflareApi extends DnsProviderApi {
close(client); close(client);
} }
return APIGenericResult(success: true, data: null); return GenericResult(success: true, data: null);
} }
@override @override
@ -272,7 +272,7 @@ class CloudflareApi extends DnsProviderApi {
} }
@override @override
Future<APIGenericResult<void>> createMultipleDnsRecords({ Future<GenericResult<void>> createMultipleDnsRecords({
required final ServerDomain domain, required final ServerDomain domain,
final String? ip4, final String? ip4,
}) async { }) async {
@ -298,7 +298,7 @@ class CloudflareApi extends DnsProviderApi {
rethrow; rethrow;
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
success: false, success: false,
data: null, data: null,
message: e.toString(), message: e.toString(),
@ -307,7 +307,7 @@ class CloudflareApi extends DnsProviderApi {
close(client); close(client);
} }
return APIGenericResult(success: true, data: null); return GenericResult(success: true, data: null);
} }
@override @override

View File

@ -46,7 +46,7 @@ class DigitalOceanDnsApi extends DnsProviderApi {
String rootAddress = 'https://api.digitalocean.com/v2'; String rootAddress = 'https://api.digitalocean.com/v2';
@override @override
Future<APIGenericResult<bool>> isApiTokenValid(final String token) async { Future<GenericResult<bool>> isApiTokenValid(final String token) async {
bool isValid = false; bool isValid = false;
Response? response; Response? response;
String message = ''; String message = '';
@ -70,7 +70,7 @@ class DigitalOceanDnsApi extends DnsProviderApi {
} }
if (response == null) { if (response == null) {
return APIGenericResult( return GenericResult(
data: isValid, data: isValid,
success: false, success: false,
message: message, message: message,
@ -85,7 +85,7 @@ class DigitalOceanDnsApi extends DnsProviderApi {
throw Exception('code: ${response.statusCode}'); throw Exception('code: ${response.statusCode}');
} }
return APIGenericResult( return GenericResult(
data: isValid, data: isValid,
success: true, success: true,
message: response.statusMessage, message: response.statusMessage,
@ -97,7 +97,7 @@ class DigitalOceanDnsApi extends DnsProviderApi {
Future<String?> getZoneId(final String domain) async => domain; Future<String?> getZoneId(final String domain) async => domain;
@override @override
Future<APIGenericResult<void>> removeSimilarRecords({ Future<GenericResult<void>> removeSimilarRecords({
required final ServerDomain domain, required final ServerDomain domain,
final String? ip4, final String? ip4,
}) async { }) async {
@ -118,7 +118,7 @@ class DigitalOceanDnsApi extends DnsProviderApi {
await Future.wait(allDeleteFutures); await Future.wait(allDeleteFutures);
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
success: false, success: false,
data: null, data: null,
message: e.toString(), message: e.toString(),
@ -127,7 +127,7 @@ class DigitalOceanDnsApi extends DnsProviderApi {
close(client); close(client);
} }
return APIGenericResult(success: true, data: null); return GenericResult(success: true, data: null);
} }
@override @override
@ -262,7 +262,7 @@ class DigitalOceanDnsApi extends DnsProviderApi {
} }
@override @override
Future<APIGenericResult<void>> createMultipleDnsRecords({ Future<GenericResult<void>> createMultipleDnsRecords({
required final ServerDomain domain, required final ServerDomain domain,
final String? ip4, final String? ip4,
}) async { }) async {
@ -292,7 +292,7 @@ class DigitalOceanDnsApi extends DnsProviderApi {
rethrow; rethrow;
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
success: false, success: false,
data: null, data: null,
message: e.toString(), message: e.toString(),
@ -301,7 +301,7 @@ class DigitalOceanDnsApi extends DnsProviderApi {
close(client); close(client);
} }
return APIGenericResult(success: true, data: null); return GenericResult(success: true, data: null);
} }
@override @override

View File

@ -1,10 +1,10 @@
import 'package:selfprivacy/logic/api_maps/api_generic_result.dart'; import 'package:selfprivacy/logic/api_maps/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/api_maps/rest_maps/dns_providers/desired_dns_record.dart'; import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/desired_dns_record.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'; export 'package:selfprivacy/logic/api_maps/generic_result.dart';
export 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/desired_dns_record.dart'; export 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/desired_dns_record.dart';
class DomainNotFoundException implements Exception { class DomainNotFoundException implements Exception {
@ -21,11 +21,11 @@ abstract class DnsProviderApi extends ApiMap {
final String? ipAddress, final String? ipAddress,
final String? dkimPublicKey, final String? dkimPublicKey,
}); });
Future<APIGenericResult<void>> removeSimilarRecords({ Future<GenericResult<void>> removeSimilarRecords({
required final ServerDomain domain, required final ServerDomain domain,
final String? ip4, final String? ip4,
}); });
Future<APIGenericResult<void>> createMultipleDnsRecords({ Future<GenericResult<void>> createMultipleDnsRecords({
required final ServerDomain domain, required final ServerDomain domain,
final String? ip4, final String? ip4,
}); });
@ -36,7 +36,7 @@ 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<APIGenericResult<bool>> isApiTokenValid(final String token); Future<GenericResult<bool>> isApiTokenValid(final String token);
RegExp getApiTokenValidation(); RegExp getApiTokenValidation();
List<DnsRecord> getProjectDnsRecords( List<DnsRecord> getProjectDnsRecords(

View File

@ -60,7 +60,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
String get displayProviderName => 'Digital Ocean'; String get displayProviderName => 'Digital Ocean';
@override @override
Future<APIGenericResult<bool>> isApiTokenValid(final String token) async { Future<GenericResult<bool>> isApiTokenValid(final String token) async {
bool isValid = false; bool isValid = false;
Response? response; Response? response;
String message = ''; String message = '';
@ -84,7 +84,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
} }
if (response == null) { if (response == null) {
return APIGenericResult( return GenericResult(
data: isValid, data: isValid,
success: false, success: false,
message: message, message: message,
@ -99,7 +99,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
throw Exception('code: ${response.statusCode}'); throw Exception('code: ${response.statusCode}');
} }
return APIGenericResult( return GenericResult(
data: isValid, data: isValid,
success: true, success: true,
message: response.statusMessage, message: response.statusMessage,
@ -115,7 +115,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
); );
@override @override
Future<APIGenericResult<ServerVolume?>> createVolume() async { Future<GenericResult<ServerVolume?>> createVolume() async {
ServerVolume? volume; ServerVolume? volume;
Response? createVolumeResponse; Response? createVolumeResponse;
@ -147,7 +147,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
); );
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
data: null, data: null,
success: false, success: false,
message: e.toString(), message: e.toString(),
@ -156,7 +156,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
client.close(); client.close();
} }
return APIGenericResult( return GenericResult(
data: volume, data: volume,
success: true, success: true,
code: createVolumeResponse.statusCode, code: createVolumeResponse.statusCode,
@ -230,7 +230,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
} }
@override @override
Future<APIGenericResult<bool>> attachVolume( Future<GenericResult<bool>> attachVolume(
final ServerVolume volume, final ServerVolume volume,
final int serverId, final int serverId,
) async { ) async {
@ -252,7 +252,7 @@ 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( return GenericResult(
data: false, data: false,
success: false, success: false,
message: e.toString(), message: e.toString(),
@ -261,7 +261,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
close(client); close(client);
} }
return APIGenericResult( return GenericResult(
data: success, data: success,
success: true, success: true,
code: attachVolumeResponse.statusCode, code: attachVolumeResponse.statusCode,
@ -327,7 +327,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
} }
@override @override
Future<APIGenericResult<ServerHostingDetails?>> createServer({ Future<GenericResult<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,
@ -399,7 +399,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
} }
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
success: false, success: false,
data: null, data: null,
message: e.toString(), message: e.toString(),
@ -408,7 +408,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
close(client); close(client);
} }
return APIGenericResult( return GenericResult(
data: serverDetails, data: serverDetails,
success: true, success: true,
code: serverCreateResponse.statusCode, code: serverCreateResponse.statusCode,
@ -417,7 +417,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
} }
@override @override
Future<APIGenericResult<bool>> deleteServer({ Future<GenericResult<bool>> deleteServer({
required final String domainName, required final String domainName,
}) async { }) async {
final Dio client = await getClient(); final Dio client = await getClient();
@ -431,7 +431,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
); );
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
data: false, data: false,
success: false, success: false,
message: e.toString(), message: e.toString(),
@ -446,7 +446,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
); );
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
data: false, data: false,
success: false, success: false,
message: e.toString(), message: e.toString(),
@ -464,7 +464,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
await Future.wait(laterFutures); await Future.wait(laterFutures);
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
success: false, success: false,
data: false, data: false,
message: e.toString(), message: e.toString(),
@ -473,7 +473,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
close(client); close(client);
} }
return APIGenericResult( return GenericResult(
success: true, success: true,
data: true, data: true,
); );
@ -762,7 +762,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
} }
@override @override
Future<APIGenericResult<List<ServerProviderLocation>>> Future<GenericResult<List<ServerProviderLocation>>>
getAvailableLocations() async { getAvailableLocations() async {
List<ServerProviderLocation> locations = []; List<ServerProviderLocation> locations = [];
@ -784,7 +784,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
.toList(); .toList();
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
data: [], data: [],
success: false, success: false,
message: e.toString(), message: e.toString(),
@ -793,11 +793,11 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
close(client); close(client);
} }
return APIGenericResult(data: locations, success: true); return GenericResult(data: locations, success: true);
} }
@override @override
Future<APIGenericResult<List<ServerType>>> getServerTypesByLocation({ Future<GenericResult<List<ServerType>>> getAvailableServerTypes({
required final ServerProviderLocation location, required final ServerProviderLocation location,
}) async { }) async {
final List<ServerType> types = []; final List<ServerType> types = [];
@ -830,7 +830,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
} }
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
data: [], data: [],
success: false, success: false,
message: e.toString(), message: e.toString(),
@ -839,17 +839,17 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
close(client); close(client);
} }
return APIGenericResult(data: types, success: true); return GenericResult(data: types, success: true);
} }
@override @override
Future<APIGenericResult<void>> createReverseDns({ Future<GenericResult<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; const bool success = true;
return APIGenericResult(success: success, data: null); return GenericResult(success: success, data: null);
} }
@override @override

View File

@ -17,7 +17,6 @@ import 'package:selfprivacy/logic/models/price.dart';
import 'package:selfprivacy/logic/models/server_basic_info.dart'; import 'package:selfprivacy/logic/models/server_basic_info.dart';
import 'package:selfprivacy/logic/models/server_metadata.dart'; 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/utils/extensions/string_extensions.dart'; import 'package:selfprivacy/utils/extensions/string_extensions.dart';
import 'package:selfprivacy/utils/network_utils.dart'; import 'package:selfprivacy/utils/network_utils.dart';
import 'package:selfprivacy/utils/password_generator.dart'; import 'package:selfprivacy/utils/password_generator.dart';
@ -60,8 +59,7 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
@override @override
String get displayProviderName => 'Hetzner'; String get displayProviderName => 'Hetzner';
@override Future<GenericResult<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 = ''; String message = '';
@ -85,7 +83,7 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
} }
if (response == null) { if (response == null) {
return APIGenericResult( return GenericResult(
data: isValid, data: isValid,
success: false, success: false,
message: message, message: message,
@ -100,21 +98,19 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
throw Exception('code: ${response.statusCode}'); throw Exception('code: ${response.statusCode}');
} }
return APIGenericResult( return GenericResult(
data: isValid, data: isValid,
success: true, success: true,
message: response.statusMessage, message: response.statusMessage,
); );
} }
@override
ProviderApiTokenValidation getApiTokenValidation() => ProviderApiTokenValidation getApiTokenValidation() =>
ProviderApiTokenValidation( ProviderApiTokenValidation(
regexp: RegExp(r'\s+|[-!$%^&*()@+|~=`{}\[\]:<>?,.\/]'), regexp: RegExp(r'\s+|[-!$%^&*()@+|~=`{}\[\]:<>?,.\/]'),
length: 64, length: 64,
); );
@override
Future<Price?> getPricePerGb() async { Future<Price?> getPricePerGb() async {
double? price; double? price;
@ -140,8 +136,7 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
); );
} }
@override Future<GenericResult<ServerVolume?>> createVolume() async {
Future<APIGenericResult<ServerVolume?>> createVolume() async {
ServerVolume? volume; ServerVolume? volume;
Response? createVolumeResponse; Response? createVolumeResponse;
@ -172,7 +167,7 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
); );
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
data: null, data: null,
success: false, success: false,
message: e.toString(), message: e.toString(),
@ -181,7 +176,7 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
client.close(); client.close();
} }
return APIGenericResult( return GenericResult(
data: volume, data: volume,
success: true, success: true,
code: createVolumeResponse.statusCode, code: createVolumeResponse.statusCode,
@ -189,7 +184,6 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
); );
} }
@override
Future<List<ServerVolume>> getVolumes({final String? status}) async { Future<List<ServerVolume>> getVolumes({final String? status}) async {
final List<ServerVolume> volumes = []; final List<ServerVolume> volumes = [];
@ -257,7 +251,6 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
return volume; return volume;
} }
@override
Future<void> deleteVolume(final ServerVolume volume) async { Future<void> deleteVolume(final ServerVolume volume) async {
final Dio client = await getClient(); final Dio client = await getClient();
try { try {
@ -269,8 +262,7 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
} }
} }
@override Future<GenericResult<bool>> attachVolume(
Future<APIGenericResult<bool>> attachVolume(
final ServerVolume volume, final ServerVolume volume,
final int serverId, final int serverId,
) async { ) async {
@ -294,7 +286,7 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
client.close(); client.close();
} }
return APIGenericResult( return GenericResult(
data: success, data: success,
success: true, success: true,
code: attachVolumeResponse?.statusCode, code: attachVolumeResponse?.statusCode,
@ -302,7 +294,6 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
); );
} }
@override
Future<bool> detachVolume(final ServerVolume volume) async { Future<bool> detachVolume(final ServerVolume volume) async {
bool success = false; bool success = false;
@ -323,7 +314,6 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
return success; return success;
} }
@override
Future<bool> resizeVolume( Future<bool> resizeVolume(
final ServerVolume volume, final ServerVolume volume,
final DiskSize size, final DiskSize size,
@ -350,19 +340,17 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
return success; return success;
} }
@override Future<GenericResult<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,
required final DnsProviderType dnsProvider, required final DnsProviderType dnsProvider,
}) async { }) async {
final APIGenericResult<ServerVolume?> newVolumeResponse = final GenericResult<ServerVolume?> newVolumeResponse = await createVolume();
await createVolume();
if (!newVolumeResponse.success || newVolumeResponse.data == null) { if (!newVolumeResponse.success || newVolumeResponse.data == null) {
return APIGenericResult( return GenericResult(
data: null, data: null,
success: false, success: false,
message: newVolumeResponse.message, message: newVolumeResponse.message,
@ -379,7 +367,7 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
); );
} }
Future<APIGenericResult<ServerHostingDetails?>> createServerWithVolume({ Future<GenericResult<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,
@ -457,7 +445,7 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
apiResultMessage = 'uniqueness_error'; apiResultMessage = 'uniqueness_error';
} }
return APIGenericResult( return GenericResult(
data: serverDetails, data: serverDetails,
success: success && hetznerError == null, success: success && hetznerError == null,
code: serverCreateResponse?.statusCode ?? code: serverCreateResponse?.statusCode ??
@ -466,8 +454,7 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
); );
} }
@override Future<GenericResult<bool>> deleteServer({
Future<APIGenericResult<bool>> deleteServer({
required final String domainName, required final String domainName,
}) async { }) async {
final Dio client = await getClient(); final Dio client = await getClient();
@ -494,7 +481,7 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
await Future.wait(laterFutures); await Future.wait(laterFutures);
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
success: false, success: false,
data: false, data: false,
message: e.toString(), message: e.toString(),
@ -503,45 +490,55 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
close(client); close(client);
} }
return APIGenericResult( return GenericResult(
success: true, success: true,
data: true, data: true,
); );
} }
@override Future<GenericResult<void>> restart(final int serverId) async {
Future<ServerHostingDetails> restart() async {
final ServerHostingDetails server = getIt<ApiConfigModel>().serverDetails!;
final Dio client = await getClient(); final Dio client = await getClient();
try { try {
await client.post('/servers/${server.id}/actions/reset'); await client.post('/servers/$serverId/actions/reset');
} catch (e) { } catch (e) {
print(e); print(e);
return GenericResult(
success: false,
data: null,
message: e.toString(),
);
} finally { } finally {
close(client); close(client);
} }
return server.copyWith(startTime: DateTime.now()); return GenericResult(
success: true,
data: null,
);
} }
@override Future<GenericResult<void>> powerOn(final int serverId) async {
Future<ServerHostingDetails> powerOn() async {
final ServerHostingDetails server = getIt<ApiConfigModel>().serverDetails!;
final Dio client = await getClient(); final Dio client = await getClient();
try { try {
await client.post('/servers/${server.id}/actions/poweron'); await client.post('/servers/$serverId/actions/poweron');
} catch (e) { } catch (e) {
print(e); print(e);
return GenericResult(
success: false,
data: null,
message: e.toString(),
);
} finally { } finally {
close(client); close(client);
} }
return server.copyWith(startTime: DateTime.now()); return GenericResult(
success: true,
data: null,
);
} }
Future<Map<String, dynamic>> requestRawMetrics( Future<GenericResult<Map<String, dynamic>>> getMetrics(
final int serverId, final int serverId,
final DateTime start, final DateTime start,
final DateTime end, final DateTime end,
@ -562,127 +559,20 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
metrics = res.data['metrics']; metrics = res.data['metrics'];
} catch (e) { } catch (e) {
print(e); print(e);
return GenericResult(
success: false,
data: {},
message: e.toString(),
);
} finally { } finally {
close(client); close(client);
} }
return metrics; return GenericResult(data: metrics, success: true);
} }
List<TimeSeriesData> serializeTimeSeries( Future<GenericResult<List<HetznerServerInfo>>> getServers() async {
final Map<String, dynamic> json, List<HetznerServerInfo> servers = [];
final String type,
) {
final List list = json['time_series'][type]['values'];
return list
.map((final el) => TimeSeriesData(el[0], double.parse(el[1])))
.toList();
}
@override
Future<ServerMetrics?> getMetrics(
final int serverId,
final DateTime start,
final DateTime end,
) async {
ServerMetrics? metrics;
final Map<String, dynamic> rawCpuMetrics = await requestRawMetrics(
serverId,
start,
end,
'cpu',
);
final Map<String, dynamic> rawNetworkMetrics = await requestRawMetrics(
serverId,
start,
end,
'network',
);
if (rawNetworkMetrics.isEmpty || rawCpuMetrics.isEmpty) {
return metrics;
}
metrics = ServerMetrics(
cpu: serializeTimeSeries(
rawCpuMetrics,
'cpu',
),
bandwidthIn: serializeTimeSeries(
rawNetworkMetrics,
'network.0.bandwidth.in',
),
bandwidthOut: serializeTimeSeries(
rawNetworkMetrics,
'network.0.bandwidth.out',
),
end: end,
start: start,
stepsInSecond: rawCpuMetrics['step'],
);
return metrics;
}
@override
Future<List<ServerMetadataEntity>> getMetadata(final int serverId) async {
List<ServerMetadataEntity> metadata = [];
final Dio client = await getClient();
try {
final Response response = await client.get('/servers/$serverId');
final hetznerInfo = HetznerServerInfo.fromJson(response.data!['server']);
metadata = [
ServerMetadataEntity(
type: MetadataType.id,
name: 'server.server_id'.tr(),
value: hetznerInfo.id.toString(),
),
ServerMetadataEntity(
type: MetadataType.status,
name: 'server.status'.tr(),
value: hetznerInfo.status.toString().split('.')[1].capitalize(),
),
ServerMetadataEntity(
type: MetadataType.cpu,
name: 'server.cpu'.tr(),
value: 'server.core_count'.plural(hetznerInfo.serverType.cores),
),
ServerMetadataEntity(
type: MetadataType.ram,
name: 'server.ram'.tr(),
value: '${hetznerInfo.serverType.memory.toString()} GB',
),
ServerMetadataEntity(
type: MetadataType.cost,
name: 'server.monthly_cost'.tr(),
value: hetznerInfo.serverType.prices[1].monthly.toStringAsFixed(2),
),
ServerMetadataEntity(
type: MetadataType.location,
name: 'server.location'.tr(),
value:
'${hetznerInfo.location.city}, ${hetznerInfo.location.country}',
),
ServerMetadataEntity(
type: MetadataType.other,
name: 'server.provider'.tr(),
value: displayProviderName,
),
];
} catch (e) {
print(e);
} finally {
close(client);
}
return metadata;
}
@override
Future<List<ServerBasicInfo>> getServers() async {
List<ServerBasicInfo> servers = [];
final Dio client = await getClient(); final Dio client = await getClient();
try { try {
@ -691,53 +581,22 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
.map<HetznerServerInfo>( .map<HetznerServerInfo>(
(final e) => HetznerServerInfo.fromJson(e), (final e) => HetznerServerInfo.fromJson(e),
) )
.toList()
.where(
(final server) => server.publicNet.ipv4 != null,
)
.map<ServerBasicInfo>(
(final server) => ServerBasicInfo(
id: server.id,
name: server.name,
ip: server.publicNet.ipv4.ip,
reverseDns: server.publicNet.ipv4.reverseDns,
created: server.created,
),
)
.toList(); .toList();
} catch (e) { } catch (e) {
print(e); print(e);
return GenericResult(
success: false,
data: [],
message: e.toString(),
);
} finally { } finally {
close(client); close(client);
} }
print(servers); return GenericResult(data: servers, success: true);
return servers;
} }
String? getEmojiFlag(final String query) { Future<GenericResult<List>> getAvailableLocations() async {
String? emoji;
switch (query.toLowerCase()) {
case 'de':
emoji = '🇩🇪';
break;
case 'fi':
emoji = '🇫🇮';
break;
case 'us':
emoji = '🇺🇸';
break;
}
return emoji;
}
@override
Future<APIGenericResult<List<ServerProviderLocation>>>
getAvailableLocations() async {
List<ServerProviderLocation> locations = []; List<ServerProviderLocation> locations = [];
final Dio client = await getClient(); final Dio client = await getClient();
@ -746,19 +605,10 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
'/locations', '/locations',
); );
locations = response.data!['locations'] locations = response.data!['locations'];
.map<ServerProviderLocation>(
(final location) => ServerProviderLocation(
title: location['city'],
description: location['description'],
flag: getEmojiFlag(location['country']),
identifier: location['name'],
),
)
.toList();
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
success: false, success: false,
data: [], data: [],
message: e.toString(), message: e.toString(),
@ -767,44 +617,21 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
close(client); close(client);
} }
return APIGenericResult(success: true, data: locations); return GenericResult(success: true, data: locations);
} }
@override Future<GenericResult<List>> getAvailableServerTypes() async {
Future<APIGenericResult<List<ServerType>>> getServerTypesByLocation({ List types = [];
required final ServerProviderLocation location,
}) async {
final List<ServerType> types = [];
final Dio client = await getClient(); final Dio client = await getClient();
try { try {
final Response response = await client.get( final Response response = await client.get(
'/server_types', '/server_types',
); );
final rawTypes = response.data!['server_types']; types = response.data!['server_types'];
for (final rawType in rawTypes) {
for (final rawPrice in rawType['prices']) {
if (rawPrice['location'].toString() == location.identifier) {
types.add(
ServerType(
title: rawType['description'],
identifier: rawType['name'],
ram: rawType['memory'],
cores: rawType['cores'],
disk: DiskSize(byte: rawType['disk'] * 1024 * 1024 * 1024),
price: Price(
value: double.parse(rawPrice['price_monthly']['gross']),
currency: 'EUR',
),
location: location,
),
);
}
}
}
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
data: [], data: [],
success: false, success: false,
message: e.toString(), message: e.toString(),
@ -813,26 +640,26 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
close(client); close(client);
} }
return APIGenericResult(data: types, success: true); return GenericResult(data: types, success: true);
} }
@override Future<GenericResult<void>> createReverseDns({
Future<APIGenericResult<void>> createReverseDns({ required final int serverId,
required final ServerHostingDetails serverDetails, required final String ip4,
required final ServerDomain domain, required final String dnsPtr,
}) async { }) async {
final Dio client = await getClient(); final Dio client = await getClient();
try { try {
await client.post( await client.post(
'/servers/${serverDetails.id}/actions/change_dns_ptr', '/servers/$serverId/actions/change_dns_ptr',
data: { data: {
'ip': serverDetails.ip4, 'ip': ip4,
'dns_ptr': domain.domainName, 'dns_ptr': dnsPtr,
}, },
); );
} catch (e) { } catch (e) {
print(e); print(e);
return APIGenericResult( return GenericResult(
success: false, success: false,
data: null, data: null,
message: e.toString(), message: e.toString(),
@ -841,6 +668,6 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
close(client); close(client);
} }
return APIGenericResult(success: true, data: null); return GenericResult(success: true, data: null);
} }
} }

View File

@ -1,15 +1,6 @@
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_domain.dart'; import 'package:selfprivacy/logic/models/hive/server_domain.dart';
import 'package:selfprivacy/logic/models/hive/user.dart'; export 'package:selfprivacy/logic/api_maps/generic_result.dart';
import 'package:selfprivacy/logic/models/metrics.dart';
import 'package:selfprivacy/logic/models/server_basic_info.dart';
import 'package:selfprivacy/logic/models/server_metadata.dart';
import 'package:selfprivacy/logic/models/server_provider_location.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({
@ -21,40 +12,6 @@ class ProviderApiTokenValidation {
} }
abstract class ServerProviderApi extends ApiMap { abstract class ServerProviderApi extends ApiMap {
Future<List<ServerBasicInfo>> getServers();
Future<APIGenericResult<List<ServerProviderLocation>>>
getAvailableLocations();
Future<APIGenericResult<List<ServerType>>> getServerTypesByLocation({
required final ServerProviderLocation location,
});
Future<ServerHostingDetails> restart();
Future<ServerHostingDetails> powerOn();
Future<APIGenericResult<bool>> deleteServer({
required final String domainName,
});
Future<APIGenericResult<ServerHostingDetails?>> createServer({
required final String dnsApiToken,
required final User rootUser,
required final String domainName,
required final String serverType,
required final DnsProviderType dnsProvider,
});
Future<APIGenericResult<void>> createReverseDns({
required final ServerHostingDetails serverDetails,
required final ServerDomain domain,
});
Future<APIGenericResult<bool>> isApiTokenValid(final String token);
ProviderApiTokenValidation getApiTokenValidation();
Future<List<ServerMetadataEntity>> getMetadata(final int serverId);
Future<ServerMetrics?> getMetrics(
final int serverId,
final DateTime start,
final DateTime end,
);
String dnsProviderToInfectName(final DnsProviderType dnsProvider) { String dnsProviderToInfectName(final DnsProviderType dnsProvider) {
String dnsProviderType; String dnsProviderType;
switch (dnsProvider) { switch (dnsProvider) {

View File

@ -1,20 +1,5 @@
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/hive/server_details.dart';
import 'package:selfprivacy/logic/models/price.dart';
export 'package:selfprivacy/logic/api_maps/api_generic_result.dart'; export 'package:selfprivacy/logic/api_maps/generic_result.dart';
mixin VolumeProviderApi on ApiMap { mixin VolumeProviderApi on ApiMap {}
Future<APIGenericResult<ServerVolume?>> createVolume();
Future<List<ServerVolume>> getVolumes({final String? status});
Future<APIGenericResult<bool>> attachVolume(
final ServerVolume volume,
final int serverId,
);
Future<bool> detachVolume(final ServerVolume volume);
Future<bool> resizeVolume(final ServerVolume volume, final DiskSize size);
Future<void> deleteVolume(final ServerVolume volume);
Future<Price?> getPricePerGb();
}

View File

@ -35,7 +35,7 @@ class ApiDevicesCubit
} }
Future<List<ApiToken>?> _getApiTokens() async { Future<List<ApiToken>?> _getApiTokens() async {
final APIGenericResult<List<ApiToken>> response = await api.getApiTokens(); final GenericResult<List<ApiToken>> response = await api.getApiTokens();
if (response.success) { if (response.success) {
return response.data; return response.data;
} else { } else {
@ -44,8 +44,7 @@ class ApiDevicesCubit
} }
Future<void> deleteDevice(final ApiToken device) async { Future<void> deleteDevice(final ApiToken device) async {
final APIGenericResult<void> response = final GenericResult<void> response = await api.deleteApiToken(device.name);
await api.deleteApiToken(device.name);
if (response.success) { if (response.success) {
emit( emit(
ApiDevicesState( ApiDevicesState(
@ -60,7 +59,7 @@ class ApiDevicesCubit
} }
Future<String?> getNewDeviceKey() async { Future<String?> getNewDeviceKey() async {
final APIGenericResult<String> response = await api.createDeviceToken(); final GenericResult<String> response = await api.createDeviceToken();
if (response.success) { if (response.success) {
return response.data; return response.data;
} else { } else {

View File

@ -40,7 +40,7 @@ class BackblazeFormCubit extends FormCubit {
@override @override
FutureOr<bool> asyncValidation() async { FutureOr<bool> asyncValidation() async {
late APIGenericResult<bool> backblazeResponse; late GenericResult<bool> backblazeResponse;
final BackblazeApi apiClient = BackblazeApi(isWithToken: false); final BackblazeApi apiClient = BackblazeApi(isWithToken: false);
try { try {
@ -51,7 +51,7 @@ class BackblazeFormCubit extends FormCubit {
backblazeResponse = await apiClient.isApiTokenValid(encodedApiKey); backblazeResponse = await apiClient.isApiTokenValid(encodedApiKey);
} catch (e) { } catch (e) {
addError(e); addError(e);
backblazeResponse = APIGenericResult( backblazeResponse = GenericResult(
success: false, success: false,
data: false, data: false,
message: e.toString(), message: e.toString(),

View File

@ -32,7 +32,7 @@ class RecoveryKeyCubit
} }
Future<RecoveryKeyStatus?> _getRecoveryKeyStatus() async { Future<RecoveryKeyStatus?> _getRecoveryKeyStatus() async {
final APIGenericResult<RecoveryKeyStatus?> response = final GenericResult<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 APIGenericResult<String> response = final GenericResult<String> response =
await api.generateRecoveryToken(expirationDate, numberOfUses); await api.generateRecoveryToken(expirationDate, numberOfUses);
if (response.success) { if (response.success) {
refresh(); refresh();

View File

@ -77,8 +77,8 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
Future<bool?> isServerProviderApiTokenValid( Future<bool?> isServerProviderApiTokenValid(
final String providerToken, final String providerToken,
) async { ) async {
final APIGenericResult<bool> apiResponse = final GenericResult<bool> apiResponse =
await ProvidersController.currentServerProvider!.isApiTokenValid( await ProvidersController.currentServerProvider!.tryInitApiByToken(
providerToken, providerToken,
); );
@ -95,7 +95,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
Future<bool?> isDnsProviderApiTokenValid( Future<bool?> isDnsProviderApiTokenValid(
final String providerToken, final String providerToken,
) async { ) async {
final APIGenericResult<bool> apiResponse = final GenericResult<bool> apiResponse =
await ApiController.currentDnsProviderApiFactory! await ApiController.currentDnsProviderApiFactory!
.getDnsProvider( .getDnsProvider(
settings: const DnsProviderApiSettings(isWithToken: false), settings: const DnsProviderApiSettings(isWithToken: false),
@ -117,7 +117,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
return []; return [];
} }
final APIGenericResult apiResponse = await ProvidersController final GenericResult apiResponse = await ProvidersController
.currentServerProvider! .currentServerProvider!
.getAvailableLocations(); .getAvailableLocations();
@ -137,7 +137,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
return []; return [];
} }
final APIGenericResult apiResult = await ProvidersController final GenericResult apiResult = await ProvidersController
.currentServerProvider! .currentServerProvider!
.getServerTypes(location: location); .getServerTypes(location: location);
@ -173,21 +173,8 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
void setServerType(final ServerType serverType) async { void setServerType(final ServerType serverType) async {
await repository.saveServerType(serverType); await repository.saveServerType(serverType);
ApiController.initServerProviderApiFactory( await ProvidersController.currentServerProvider!
ServerProviderSettings( .trySetServerType(serverType);
provider: getIt<ApiConfigModel>().serverProvider!,
location: serverType.location.identifier,
),
);
// All server providers support volumes for now,
// so it's safe to initialize.
ApiController.initVolumeProviderApiFactory(
ServerProviderSettings(
provider: getIt<ApiConfigModel>().serverProvider!,
location: serverType.location.identifier,
),
);
emit( emit(
(state as ServerInstallationNotFinished).copyWith( (state as ServerInstallationNotFinished).copyWith(

View File

@ -259,7 +259,7 @@ class ServerInstallationRepository {
actionButtonOnPressed: () async { actionButtonOnPressed: () async {
ServerHostingDetails? serverDetails; ServerHostingDetails? serverDetails;
try { try {
final APIGenericResult createResult = await api.createServer( final GenericResult createResult = await api.createServer(
dnsProvider: getIt<ApiConfigModel>().dnsProvider!, dnsProvider: getIt<ApiConfigModel>().dnsProvider!,
dnsApiToken: cloudFlareKey, dnsApiToken: cloudFlareKey,
rootUser: rootUser, rootUser: rootUser,
@ -283,7 +283,7 @@ class ServerInstallationRepository {
} }
try { try {
final APIGenericResult<ServerHostingDetails?> createServerResult = final GenericResult<ServerHostingDetails?> createServerResult =
await api.createServer( await api.createServer(
dnsProvider: getIt<ApiConfigModel>().dnsProvider!, dnsProvider: getIt<ApiConfigModel>().dnsProvider!,
dnsApiToken: cloudFlareKey, dnsApiToken: cloudFlareKey,
@ -309,7 +309,7 @@ class ServerInstallationRepository {
ServerHostingDetails? serverDetails; ServerHostingDetails? serverDetails;
try { try {
final APIGenericResult createResult = await api.createServer( final GenericResult createResult = await api.createServer(
dnsProvider: getIt<ApiConfigModel>().dnsProvider!, dnsProvider: getIt<ApiConfigModel>().dnsProvider!,
dnsApiToken: cloudFlareKey, dnsApiToken: cloudFlareKey,
rootUser: rootUser, rootUser: rootUser,
@ -366,7 +366,7 @@ class ServerInstallationRepository {
); );
} }
final APIGenericResult removingResult = final GenericResult removingResult =
await dnsProviderApi.removeSimilarRecords( await dnsProviderApi.removeSimilarRecords(
ip4: serverDetails.ip4, ip4: serverDetails.ip4,
domain: domain, domain: domain,
@ -380,7 +380,7 @@ class ServerInstallationRepository {
bool createdSuccessfully = false; bool createdSuccessfully = false;
String errorMessage = 'domain.error'.tr(); String errorMessage = 'domain.error'.tr();
try { try {
final APIGenericResult createResult = final GenericResult createResult =
await dnsProviderApi.createMultipleDnsRecords( await dnsProviderApi.createMultipleDnsRecords(
ip4: serverDetails.ip4, ip4: serverDetails.ip4,
domain: domain, domain: domain,
@ -397,8 +397,7 @@ class ServerInstallationRepository {
return false; return false;
} }
final APIGenericResult createReverseResult = final GenericResult createReverseResult = await serverApi.createReverseDns(
await serverApi.createReverseDns(
serverDetails: serverDetails, serverDetails: serverDetails,
domain: domain, domain: domain,
); );
@ -520,7 +519,7 @@ class ServerInstallationRepository {
overrideDomain: serverDomain.domainName, overrideDomain: serverDomain.domainName,
); );
final String serverIp = await getServerIpFromDomain(serverDomain); final String serverIp = await getServerIpFromDomain(serverDomain);
final APIGenericResult<String> result = await serverApi.authorizeDevice( final GenericResult<String> result = await serverApi.authorizeDevice(
DeviceToken(device: await getDeviceName(), token: newDeviceKey), DeviceToken(device: await getDeviceName(), token: newDeviceKey),
); );
@ -557,7 +556,7 @@ class ServerInstallationRepository {
overrideDomain: serverDomain.domainName, overrideDomain: serverDomain.domainName,
); );
final String serverIp = await getServerIpFromDomain(serverDomain); final String serverIp = await getServerIpFromDomain(serverDomain);
final APIGenericResult<String> result = await serverApi.useRecoveryToken( final GenericResult<String> result = await serverApi.useRecoveryToken(
DeviceToken(device: await getDeviceName(), token: recoveryKey), DeviceToken(device: await getDeviceName(), token: recoveryKey),
); );
@ -618,9 +617,9 @@ class ServerInstallationRepository {
); );
} }
} }
final APIGenericResult<String> deviceAuthKey = final GenericResult<String> deviceAuthKey =
await serverApi.createDeviceToken(); await serverApi.createDeviceToken();
final APIGenericResult<String> result = await serverApi.authorizeDevice( final GenericResult<String> result = await serverApi.authorizeDevice(
DeviceToken(device: await getDeviceName(), token: deviceAuthKey.data), DeviceToken(device: await getDeviceName(), token: deviceAuthKey.data),
); );
@ -771,7 +770,7 @@ class ServerInstallationRepository {
} }
Future<bool> deleteServer(final ServerDomain serverDomain) async { Future<bool> deleteServer(final ServerDomain serverDomain) async {
final APIGenericResult<bool> deletionResult = await ApiController final GenericResult<bool> deletionResult = await ApiController
.currentServerProviderApiFactory! .currentServerProviderApiFactory!
.getServerProvider() .getServerProvider()
.deleteServer( .deleteServer(
@ -797,7 +796,7 @@ class ServerInstallationRepository {
await box.put(BNames.isLoading, false); await box.put(BNames.isLoading, false);
await box.put(BNames.serverDetails, null); await box.put(BNames.serverDetails, null);
final APIGenericResult<void> removalResult = await ApiController final GenericResult<void> removalResult = await ApiController
.currentDnsProviderApiFactory! .currentDnsProviderApiFactory!
.getDnsProvider() .getDnsProvider()
.removeSimilarRecords(domain: serverDomain); .removeSimilarRecords(domain: serverDomain);

View File

@ -78,7 +78,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
return; return;
} }
// If API returned error, do nothing // If API returned error, do nothing
final APIGenericResult<User?> result = final GenericResult<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 APIGenericResult result = await api.deleteUser(user.login); final GenericResult 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 APIGenericResult<User?> result = final GenericResult<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 APIGenericResult<User?> result = final GenericResult<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 APIGenericResult<User?> result = final GenericResult<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!;

View File

@ -19,11 +19,11 @@ enum MetadataType {
class ServerMetadataEntity { class ServerMetadataEntity {
ServerMetadataEntity({ ServerMetadataEntity({
required this.name, required this.trId,
required this.value, required this.value,
this.type = MetadataType.other, this.type = MetadataType.other,
}); });
final MetadataType type; final MetadataType type;
final String name; final String trId;
final String value; final String value;
} }

View File

@ -1,12 +1,16 @@
import 'package:selfprivacy/logic/api_maps/api_generic_result.dart'; import 'package:selfprivacy/logic/api_maps/generic_result.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/generic_result.dart';
abstract class ServerProvider { abstract class ServerProvider {
Future<APIGenericResult<bool>> isApiTokenValid(final String apiToken); Future<GenericResult<bool>> trySetServerType(final ServerType type);
Future<APIGenericResult<List<ServerProviderLocation>>> Future<GenericResult<bool>> tryInitApiByToken(final String token);
getAvailableLocations(); Future<GenericResult<List<ServerProviderLocation>>> getAvailableLocations();
Future<APIGenericResult<List<ServerType>>> getServerTypes({ Future<GenericResult<List<ServerType>>> getServerTypes({
required final ServerProviderLocation location, required final ServerProviderLocation location,
}); });
GenericResult<bool> get success => GenericResult(success: true, data: true);
} }

View File

@ -1,3 +1,390 @@
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/hetzner/hetzner_api.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_domain.dart';
import 'package:selfprivacy/logic/models/json/hetzner_server_info.dart';
import 'package:selfprivacy/logic/models/metrics.dart';
import 'package:selfprivacy/logic/models/price.dart';
import 'package:selfprivacy/logic/models/server_basic_info.dart';
import 'package:selfprivacy/logic/models/server_metadata.dart';
import 'package:selfprivacy/logic/models/server_provider_location.dart';
import 'package:selfprivacy/logic/models/server_type.dart';
import 'package:selfprivacy/logic/providers/server_provider.dart'; import 'package:selfprivacy/logic/providers/server_provider.dart';
import 'package:selfprivacy/utils/extensions/string_extensions.dart';
class HetznerServerProvider extends ServerProvider {} class ApiAdapter {
ApiAdapter({final String? region, final bool isWithToken = true})
: _api = HetznerApi(
region: region,
isWithToken: isWithToken,
);
HetznerApi api({final bool getInitialized = true}) => getInitialized
? _api
: HetznerApi(
region: _api.region,
isWithToken: false,
);
final HetznerApi _api;
}
class HetznerServerProvider extends ServerProvider {
HetznerServerProvider() : _adapter = ApiAdapter();
HetznerServerProvider.load(
final ServerType serverType,
final bool isAuthotized,
) : _adapter = ApiAdapter(
isWithToken: isAuthotized,
region: serverType.location.identifier,
);
ApiAdapter _adapter;
@override
Future<GenericResult<bool>> trySetServerType(final ServerType type) async {
final bool apiInitialized = _adapter.api().isWithToken;
if (!apiInitialized) {
return GenericResult(
success: true,
data: false,
message: 'Not authorized!',
);
}
_adapter = ApiAdapter(
isWithToken: true,
region: type.location.identifier,
);
return success;
}
@override
Future<GenericResult<bool>> tryInitApiByToken(final String token) async {
final api = _adapter.api(getInitialized: false);
final result = await api.isApiTokenValid(token);
if (!result.data || !result.success) {
return result;
}
_adapter = ApiAdapter(region: api.region, isWithToken: true);
return result;
}
String? getEmojiFlag(final String query) {
String? emoji;
switch (query.toLowerCase()) {
case 'de':
emoji = '🇩🇪';
break;
case 'fi':
emoji = '🇫🇮';
break;
case 'us':
emoji = '🇺🇸';
break;
}
return emoji;
}
@override
Future<GenericResult<List<ServerProviderLocation>>>
getAvailableLocations() async {
final List<ServerProviderLocation> locations = [];
final result = await _adapter.api().getAvailableLocations();
if (result.data.isEmpty || !result.success) {
return GenericResult(
success: result.success,
data: locations,
code: result.code,
message: result.message,
);
}
final List rawLocations = result.data;
for (final rawLocation in rawLocations) {
ServerProviderLocation? location;
try {
location = ServerProviderLocation(
title: rawLocation['city'],
description: rawLocation['description'],
flag: getEmojiFlag(rawLocation['country']),
identifier: rawLocation['name'],
);
} catch (e) {
continue;
}
locations.add(location);
}
return GenericResult(success: true, data: locations);
}
@override
Future<GenericResult<List<ServerType>>> getServerTypes({
required final ServerProviderLocation location,
}) async {
final List<ServerType> types = [];
final result = await _adapter.api().getAvailableServerTypes();
if (result.data.isEmpty || !result.success) {
return GenericResult(
success: result.success,
data: types,
code: result.code,
message: result.message,
);
}
final List rawTypes = result.data;
for (final rawType in rawTypes) {
for (final rawPrice in rawType['prices']) {
if (rawPrice['location'].toString() == location.identifier) {
types.add(
ServerType(
title: rawType['description'],
identifier: rawType['name'],
ram: rawType['memory'],
cores: rawType['cores'],
disk: DiskSize(byte: rawType['disk'] * 1024 * 1024 * 1024),
price: Price(
value: double.parse(rawPrice['price_monthly']['gross']),
currency: 'EUR',
),
location: location,
),
);
}
}
}
return GenericResult(success: true, data: types);
}
Future<GenericResult<void>> createReverseDns({
required final ServerHostingDetails serverDetails,
required final ServerDomain domain,
}) async =>
_adapter.api().createReverseDns(
serverId: serverDetails.id,
ip4: serverDetails.ip4,
dnsPtr: domain.domainName,
);
Future<GenericResult<List<ServerBasicInfo>>> getServers() async {
final List<ServerBasicInfo> servers = [];
final result = await _adapter.api().getServers();
if (result.data.isEmpty || !result.success) {
return GenericResult(
success: result.success,
data: servers,
code: result.code,
message: result.message,
);
}
final List<HetznerServerInfo> hetznerServers = result.data;
for (final hetznerServer in hetznerServers) {
if (hetznerServer.publicNet.ipv4 == null) {
continue;
}
ServerBasicInfo? server;
try {
server = ServerBasicInfo(
id: hetznerServer.id,
name: hetznerServer.name,
ip: hetznerServer.publicNet.ipv4!.ip,
reverseDns: hetznerServer.publicNet.ipv4!.reverseDns,
created: hetznerServer.created,
);
} catch (e) {
continue;
}
servers.add(server);
}
return GenericResult(success: true, data: servers);
}
Future<GenericResult<List<ServerMetadataEntity>>> getMetadata(
final int serverId,
) async {
List<ServerMetadataEntity> metadata = [];
final result = await _adapter.api().getServers();
if (result.data.isEmpty || !result.success) {
return GenericResult(
success: false,
data: metadata,
code: result.code,
message: result.message,
);
}
final List<HetznerServerInfo> servers = result.data;
try {
final HetznerServerInfo server = servers.firstWhere(
(final server) => server.id == serverId,
);
metadata = [
ServerMetadataEntity(
type: MetadataType.id,
trId: 'server.server_id',
value: server.id.toString(),
),
ServerMetadataEntity(
type: MetadataType.status,
trId: 'server.status',
value: server.status.toString().split('.')[1].capitalize(),
),
ServerMetadataEntity(
type: MetadataType.cpu,
trId: 'server.cpu',
value: server.serverType.cores.toString(),
),
ServerMetadataEntity(
type: MetadataType.ram,
trId: 'server.ram',
value: '${server.serverType.memory.toString()} GB',
),
ServerMetadataEntity(
type: MetadataType.cost,
trId: 'server.monthly_cost',
value: server.serverType.prices[1].monthly.toStringAsFixed(2),
),
ServerMetadataEntity(
type: MetadataType.location,
trId: 'server.location',
value: '${server.location.city}, ${server.location.country}',
),
ServerMetadataEntity(
type: MetadataType.other,
trId: 'server.provider',
value: _adapter.api().displayProviderName,
),
];
} catch (e) {
return GenericResult(
success: false,
data: [],
message: e.toString(),
);
}
return GenericResult(success: true, data: metadata);
}
Future<GenericResult<ServerMetrics?>> getMetrics(
final int serverId,
final DateTime start,
final DateTime end,
) async {
ServerMetrics? metrics;
List<TimeSeriesData> serializeTimeSeries(
final Map<String, dynamic> json,
final String type,
) {
final List list = json['time_series'][type]['values'];
return list
.map((final el) => TimeSeriesData(el[0], double.parse(el[1])))
.toList();
}
final cpuResult = await _adapter.api().getMetrics(
serverId,
start,
end,
'cpu',
);
if (cpuResult.data.isEmpty || !cpuResult.success) {
return GenericResult(
success: false,
data: metrics,
code: cpuResult.code,
message: cpuResult.message,
);
}
final netResult = await _adapter.api().getMetrics(
serverId,
start,
end,
'network',
);
if (cpuResult.data.isEmpty || !netResult.success) {
return GenericResult(
success: false,
data: metrics,
code: netResult.code,
message: netResult.message,
);
}
metrics = ServerMetrics(
cpu: serializeTimeSeries(
cpuResult.data,
'cpu',
),
bandwidthIn: serializeTimeSeries(
netResult.data,
'network.0.bandwidth.in',
),
bandwidthOut: serializeTimeSeries(
netResult.data,
'network.0.bandwidth.out',
),
end: end,
start: start,
stepsInSecond: cpuResult.data['step'],
);
return GenericResult(data: metrics, success: true);
}
Future<GenericResult<DateTime?>> restart(final int serverId) async {
DateTime? timestamp;
final result = await _adapter.api().restart(serverId);
if (!result.success) {
return GenericResult(
success: false,
data: timestamp,
code: result.code,
message: result.message,
);
}
timestamp = DateTime.now();
return GenericResult(
success: true,
data: timestamp,
);
}
Future<GenericResult<DateTime?>> powerOn(final int serverId) async {
DateTime? timestamp;
final result = await _adapter.api().powerOn(serverId);
if (!result.success) {
return GenericResult(
success: false,
data: timestamp,
code: result.code,
message: result.message,
);
}
timestamp = DateTime.now();
return GenericResult(
success: true,
data: timestamp,
);
}
}

View File

@ -27,7 +27,7 @@ class _TextDetails extends StatelessWidget {
.map( .map(
(final metadata) => ListTileOnSurfaceVariant( (final metadata) => ListTileOnSurfaceVariant(
leadingIcon: metadata.type.icon, leadingIcon: metadata.type.icon,
title: metadata.name, title: metadata.trId.tr(),
subtitle: metadata.value, subtitle: metadata.value,
), ),
) )