mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-02-02 14:16:58 +00:00
refactor: Implement better error handling on create server stage
Replace try-catch hell with APIGenericResult chain
This commit is contained in:
parent
29b0bf2397
commit
e0b32404be
|
@ -3,6 +3,7 @@ class APIGenericResult<T> {
|
|||
required this.success,
|
||||
required this.data,
|
||||
this.message,
|
||||
this.code,
|
||||
});
|
||||
|
||||
/// Whether was a response successfully received,
|
||||
|
@ -10,4 +11,5 @@ class APIGenericResult<T> {
|
|||
final bool success;
|
||||
final String? message;
|
||||
final T data;
|
||||
final int? code;
|
||||
}
|
||||
|
|
|
@ -22,13 +22,13 @@ mixin JobsApi on ApiMap {
|
|||
return jobsList;
|
||||
}
|
||||
|
||||
Future<GenericMutationResult<bool>> removeApiJob(final String uid) async {
|
||||
Future<APIGenericResult<bool>> removeApiJob(final String uid) async {
|
||||
try {
|
||||
final GraphQLClient client = await getClient();
|
||||
final variables = Variables$Mutation$RemoveJob(jobId: uid);
|
||||
final mutation = Options$Mutation$RemoveJob(variables: variables);
|
||||
final response = await client.mutate$RemoveJob(mutation);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: response.parsedData?.removeJob.success ?? false,
|
||||
success: true,
|
||||
code: response.parsedData?.removeJob.code ?? 0,
|
||||
|
@ -36,7 +36,7 @@ mixin JobsApi on ApiMap {
|
|||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: false,
|
||||
success: false,
|
||||
code: 0,
|
||||
|
|
|
@ -31,16 +31,6 @@ part 'services_api.dart';
|
|||
part 'users_api.dart';
|
||||
part 'volume_api.dart';
|
||||
|
||||
class GenericMutationResult<T> extends APIGenericResult<T> {
|
||||
GenericMutationResult({
|
||||
required super.success,
|
||||
required this.code,
|
||||
required super.data,
|
||||
super.message,
|
||||
});
|
||||
final int code;
|
||||
}
|
||||
|
||||
class ServerApi extends ApiMap
|
||||
with VolumeApi, JobsApi, ServerActionsApi, ServicesApi, UsersApi {
|
||||
ServerApi({
|
||||
|
|
|
@ -20,7 +20,7 @@ mixin ServicesApi on ApiMap {
|
|||
return services;
|
||||
}
|
||||
|
||||
Future<GenericMutationResult<bool>> enableService(
|
||||
Future<APIGenericResult<bool>> enableService(
|
||||
final String serviceId,
|
||||
) async {
|
||||
try {
|
||||
|
@ -28,7 +28,7 @@ mixin ServicesApi on ApiMap {
|
|||
final variables = Variables$Mutation$EnableService(serviceId: serviceId);
|
||||
final mutation = Options$Mutation$EnableService(variables: variables);
|
||||
final response = await client.mutate$EnableService(mutation);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: response.parsedData?.enableService.success ?? false,
|
||||
success: true,
|
||||
code: response.parsedData?.enableService.code ?? 0,
|
||||
|
@ -36,7 +36,7 @@ mixin ServicesApi on ApiMap {
|
|||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: false,
|
||||
success: false,
|
||||
code: 0,
|
||||
|
@ -45,7 +45,7 @@ mixin ServicesApi on ApiMap {
|
|||
}
|
||||
}
|
||||
|
||||
Future<GenericMutationResult<void>> disableService(
|
||||
Future<APIGenericResult<void>> disableService(
|
||||
final String serviceId,
|
||||
) async {
|
||||
try {
|
||||
|
@ -53,7 +53,7 @@ mixin ServicesApi on ApiMap {
|
|||
final variables = Variables$Mutation$DisableService(serviceId: serviceId);
|
||||
final mutation = Options$Mutation$DisableService(variables: variables);
|
||||
final response = await client.mutate$DisableService(mutation);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: null,
|
||||
success: response.parsedData?.disableService.success ?? false,
|
||||
code: response.parsedData?.disableService.code ?? 0,
|
||||
|
@ -61,7 +61,7 @@ mixin ServicesApi on ApiMap {
|
|||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: null,
|
||||
success: false,
|
||||
code: 0,
|
||||
|
@ -70,7 +70,7 @@ mixin ServicesApi on ApiMap {
|
|||
}
|
||||
}
|
||||
|
||||
Future<GenericMutationResult<bool>> stopService(
|
||||
Future<APIGenericResult<bool>> stopService(
|
||||
final String serviceId,
|
||||
) async {
|
||||
try {
|
||||
|
@ -78,7 +78,7 @@ mixin ServicesApi on ApiMap {
|
|||
final variables = Variables$Mutation$StopService(serviceId: serviceId);
|
||||
final mutation = Options$Mutation$StopService(variables: variables);
|
||||
final response = await client.mutate$StopService(mutation);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: response.parsedData?.stopService.success ?? false,
|
||||
success: true,
|
||||
code: response.parsedData?.stopService.code ?? 0,
|
||||
|
@ -86,7 +86,7 @@ mixin ServicesApi on ApiMap {
|
|||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: false,
|
||||
success: false,
|
||||
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 {
|
||||
final GraphQLClient client = await getClient();
|
||||
final variables = Variables$Mutation$StartService(serviceId: serviceId);
|
||||
final mutation = Options$Mutation$StartService(variables: variables);
|
||||
final response = await client.mutate$StartService(mutation);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: null,
|
||||
success: response.parsedData?.startService.success ?? false,
|
||||
code: response.parsedData?.startService.code ?? 0,
|
||||
|
@ -109,7 +109,7 @@ mixin ServicesApi on ApiMap {
|
|||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: null,
|
||||
success: false,
|
||||
code: 0,
|
||||
|
@ -118,7 +118,7 @@ mixin ServicesApi on ApiMap {
|
|||
}
|
||||
}
|
||||
|
||||
Future<GenericMutationResult<bool>> restartService(
|
||||
Future<APIGenericResult<bool>> restartService(
|
||||
final String serviceId,
|
||||
) async {
|
||||
try {
|
||||
|
@ -126,7 +126,7 @@ mixin ServicesApi on ApiMap {
|
|||
final variables = Variables$Mutation$RestartService(serviceId: serviceId);
|
||||
final mutation = Options$Mutation$RestartService(variables: variables);
|
||||
final response = await client.mutate$RestartService(mutation);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: response.parsedData?.restartService.success ?? false,
|
||||
success: true,
|
||||
code: response.parsedData?.restartService.code ?? 0,
|
||||
|
@ -134,7 +134,7 @@ mixin ServicesApi on ApiMap {
|
|||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: false,
|
||||
success: false,
|
||||
code: 0,
|
||||
|
@ -143,7 +143,7 @@ mixin ServicesApi on ApiMap {
|
|||
}
|
||||
}
|
||||
|
||||
Future<GenericMutationResult<ServerJob?>> moveService(
|
||||
Future<APIGenericResult<ServerJob?>> moveService(
|
||||
final String serviceId,
|
||||
final String destination,
|
||||
) async {
|
||||
|
@ -158,7 +158,7 @@ mixin ServicesApi on ApiMap {
|
|||
final mutation = Options$Mutation$MoveService(variables: variables);
|
||||
final response = await client.mutate$MoveService(mutation);
|
||||
final jobJson = response.parsedData?.moveService.job?.toJson();
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
success: true,
|
||||
code: response.parsedData?.moveService.code ?? 0,
|
||||
message: response.parsedData?.moveService.message,
|
||||
|
@ -166,7 +166,7 @@ mixin ServicesApi on ApiMap {
|
|||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
success: false,
|
||||
code: 0,
|
||||
message: e.toString(),
|
||||
|
|
|
@ -45,7 +45,7 @@ mixin UsersApi on ApiMap {
|
|||
return user;
|
||||
}
|
||||
|
||||
Future<GenericMutationResult<User?>> createUser(
|
||||
Future<APIGenericResult<User?>> createUser(
|
||||
final String username,
|
||||
final String password,
|
||||
) async {
|
||||
|
@ -56,7 +56,7 @@ mixin UsersApi on ApiMap {
|
|||
);
|
||||
final mutation = Options$Mutation$CreateUser(variables: variables);
|
||||
final response = await client.mutate$CreateUser(mutation);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
success: true,
|
||||
code: response.parsedData?.createUser.code ?? 500,
|
||||
message: response.parsedData?.createUser.message,
|
||||
|
@ -66,7 +66,7 @@ mixin UsersApi on ApiMap {
|
|||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
success: false,
|
||||
code: 0,
|
||||
message: e.toString(),
|
||||
|
@ -75,7 +75,7 @@ mixin UsersApi on ApiMap {
|
|||
}
|
||||
}
|
||||
|
||||
Future<GenericMutationResult<bool>> deleteUser(
|
||||
Future<APIGenericResult<bool>> deleteUser(
|
||||
final String username,
|
||||
) async {
|
||||
try {
|
||||
|
@ -83,7 +83,7 @@ mixin UsersApi on ApiMap {
|
|||
final variables = Variables$Mutation$DeleteUser(username: username);
|
||||
final mutation = Options$Mutation$DeleteUser(variables: variables);
|
||||
final response = await client.mutate$DeleteUser(mutation);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: response.parsedData?.deleteUser.success ?? false,
|
||||
success: true,
|
||||
code: response.parsedData?.deleteUser.code ?? 500,
|
||||
|
@ -91,7 +91,7 @@ mixin UsersApi on ApiMap {
|
|||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: false,
|
||||
success: false,
|
||||
code: 500,
|
||||
|
@ -100,7 +100,7 @@ mixin UsersApi on ApiMap {
|
|||
}
|
||||
}
|
||||
|
||||
Future<GenericMutationResult<User?>> updateUser(
|
||||
Future<APIGenericResult<User?>> updateUser(
|
||||
final String username,
|
||||
final String password,
|
||||
) async {
|
||||
|
@ -111,7 +111,7 @@ mixin UsersApi on ApiMap {
|
|||
);
|
||||
final mutation = Options$Mutation$UpdateUser(variables: variables);
|
||||
final response = await client.mutate$UpdateUser(mutation);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
success: true,
|
||||
code: response.parsedData?.updateUser.code ?? 500,
|
||||
message: response.parsedData?.updateUser.message,
|
||||
|
@ -121,7 +121,7 @@ mixin UsersApi on ApiMap {
|
|||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: null,
|
||||
success: false,
|
||||
code: 0,
|
||||
|
@ -130,7 +130,7 @@ mixin UsersApi on ApiMap {
|
|||
}
|
||||
}
|
||||
|
||||
Future<GenericMutationResult<User?>> addSshKey(
|
||||
Future<APIGenericResult<User?>> addSshKey(
|
||||
final String username,
|
||||
final String sshKey,
|
||||
) async {
|
||||
|
@ -144,7 +144,7 @@ mixin UsersApi on ApiMap {
|
|||
);
|
||||
final mutation = Options$Mutation$AddSshKey(variables: variables);
|
||||
final response = await client.mutate$AddSshKey(mutation);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
success: true,
|
||||
code: response.parsedData?.addSshKey.code ?? 500,
|
||||
message: response.parsedData?.addSshKey.message,
|
||||
|
@ -154,7 +154,7 @@ mixin UsersApi on ApiMap {
|
|||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: null,
|
||||
success: false,
|
||||
code: 0,
|
||||
|
@ -163,7 +163,7 @@ mixin UsersApi on ApiMap {
|
|||
}
|
||||
}
|
||||
|
||||
Future<GenericMutationResult<User?>> removeSshKey(
|
||||
Future<APIGenericResult<User?>> removeSshKey(
|
||||
final String username,
|
||||
final String sshKey,
|
||||
) async {
|
||||
|
@ -177,7 +177,7 @@ mixin UsersApi on ApiMap {
|
|||
);
|
||||
final mutation = Options$Mutation$RemoveSshKey(variables: variables);
|
||||
final response = await client.mutate$RemoveSshKey(mutation);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
success: response.parsedData?.removeSshKey.success ?? false,
|
||||
code: response.parsedData?.removeSshKey.code ?? 500,
|
||||
message: response.parsedData?.removeSshKey.message,
|
||||
|
@ -187,7 +187,7 @@ mixin UsersApi on ApiMap {
|
|||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return GenericMutationResult(
|
||||
return APIGenericResult(
|
||||
data: null,
|
||||
success: false,
|
||||
code: 0,
|
||||
|
|
|
@ -57,10 +57,10 @@ mixin VolumeApi on ApiMap {
|
|||
}
|
||||
}
|
||||
|
||||
Future<GenericMutationResult<String?>> migrateToBinds(
|
||||
Future<APIGenericResult<String?>> migrateToBinds(
|
||||
final Map<String, String> serviceToDisk,
|
||||
) async {
|
||||
GenericMutationResult<String?>? mutation;
|
||||
APIGenericResult<String?>? mutation;
|
||||
|
||||
try {
|
||||
final GraphQLClient client = await getClient();
|
||||
|
@ -78,7 +78,7 @@ mixin VolumeApi on ApiMap {
|
|||
await client.mutate$MigrateToBinds(
|
||||
migrateMutation,
|
||||
);
|
||||
mutation = mutation = GenericMutationResult(
|
||||
mutation = mutation = APIGenericResult(
|
||||
success: true,
|
||||
code: result.parsedData!.migrateToBinds.code,
|
||||
message: result.parsedData!.migrateToBinds.message,
|
||||
|
@ -86,7 +86,7 @@ mixin VolumeApi on ApiMap {
|
|||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
mutation = GenericMutationResult(
|
||||
mutation = APIGenericResult(
|
||||
success: false,
|
||||
code: 0,
|
||||
message: e.toString(),
|
||||
|
|
|
@ -114,10 +114,10 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
|||
);
|
||||
|
||||
@override
|
||||
Future<ServerVolume?> createVolume() async {
|
||||
Future<APIGenericResult<ServerVolume?>> createVolume() async {
|
||||
ServerVolume? volume;
|
||||
|
||||
final Response createVolumeResponse;
|
||||
Response? createVolumeResponse;
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
final List<ServerVolume> volumes = await getVolumes();
|
||||
|
@ -146,11 +146,21 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
|||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return APIGenericResult(
|
||||
data: null,
|
||||
success: false,
|
||||
message: e.toString(),
|
||||
);
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
|
||||
return volume;
|
||||
return APIGenericResult(
|
||||
data: volume,
|
||||
success: true,
|
||||
code: createVolumeResponse.statusCode,
|
||||
message: createVolumeResponse.statusMessage,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -219,13 +229,13 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<bool> attachVolume(
|
||||
Future<APIGenericResult<bool>> attachVolume(
|
||||
final ServerVolume volume,
|
||||
final int serverId,
|
||||
) async {
|
||||
bool success = false;
|
||||
|
||||
final Response attachVolumeResponse;
|
||||
Response? attachVolumeResponse;
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
attachVolumeResponse = await client.post(
|
||||
|
@ -241,11 +251,21 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
|||
attachVolumeResponse.data['action']['status'].toString() != 'error';
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return APIGenericResult(
|
||||
data: false,
|
||||
success: false,
|
||||
message: e.toString(),
|
||||
);
|
||||
} finally {
|
||||
close(client);
|
||||
}
|
||||
|
||||
return success;
|
||||
return APIGenericResult(
|
||||
data: success,
|
||||
success: true,
|
||||
code: attachVolumeResponse.statusCode,
|
||||
message: attachVolumeResponse.statusMessage,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -323,7 +343,7 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<ServerHostingDetails?> createServer({
|
||||
Future<APIGenericResult<ServerHostingDetails?>> createServer({
|
||||
required final String dnsApiToken,
|
||||
required final User rootUser,
|
||||
required final String domainName,
|
||||
|
@ -345,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";
|
||||
print(userdataString);
|
||||
|
||||
Response? serverCreateResponse;
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
final Map<String, Object> data = {
|
||||
|
@ -356,14 +377,15 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
|||
};
|
||||
print('Decoded data: $data');
|
||||
|
||||
final Response serverCreateResponse = await client.post(
|
||||
serverCreateResponse = await client.post(
|
||||
'/droplets',
|
||||
data: data,
|
||||
);
|
||||
|
||||
final int serverId = serverCreateResponse.data['droplet']['id'];
|
||||
final ServerVolume? newVolume = await createVolume();
|
||||
final bool attachedVolume = await attachVolume(newVolume!, serverId);
|
||||
final ServerVolume? newVolume = (await createVolume()).data;
|
||||
final bool attachedVolume =
|
||||
(await attachVolume(newVolume!, serverId)).data;
|
||||
|
||||
String? ipv4;
|
||||
int attempts = 0;
|
||||
|
@ -391,11 +413,21 @@ class DigitalOceanApi extends ServerProviderApi with VolumeProviderApi {
|
|||
}
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return APIGenericResult(
|
||||
success: false,
|
||||
data: null,
|
||||
message: e.toString(),
|
||||
);
|
||||
} finally {
|
||||
close(client);
|
||||
}
|
||||
|
||||
return serverDetails;
|
||||
return APIGenericResult(
|
||||
data: serverDetails,
|
||||
success: true,
|
||||
code: serverCreateResponse.statusCode,
|
||||
message: serverCreateResponse.statusMessage,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -140,10 +140,10 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<ServerVolume?> createVolume() async {
|
||||
Future<APIGenericResult<ServerVolume?>> createVolume() async {
|
||||
ServerVolume? volume;
|
||||
|
||||
final Response createVolumeResponse;
|
||||
Response? createVolumeResponse;
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
createVolumeResponse = await client.post(
|
||||
|
@ -171,11 +171,21 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
|||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return APIGenericResult(
|
||||
data: null,
|
||||
success: false,
|
||||
message: e.toString(),
|
||||
);
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
|
||||
return volume;
|
||||
return APIGenericResult(
|
||||
data: volume,
|
||||
success: true,
|
||||
code: createVolumeResponse.statusCode,
|
||||
message: createVolumeResponse.statusMessage,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -259,13 +269,13 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<bool> attachVolume(
|
||||
Future<APIGenericResult<bool>> attachVolume(
|
||||
final ServerVolume volume,
|
||||
final int serverId,
|
||||
) async {
|
||||
bool success = false;
|
||||
|
||||
final Response attachVolumeResponse;
|
||||
Response? attachVolumeResponse;
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
attachVolumeResponse = await client.post(
|
||||
|
@ -283,7 +293,12 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
|||
client.close();
|
||||
}
|
||||
|
||||
return success;
|
||||
return APIGenericResult(
|
||||
data: success,
|
||||
success: true,
|
||||
code: attachVolumeResponse?.statusCode,
|
||||
message: attachVolumeResponse?.statusMessage,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -335,31 +350,33 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<ServerHostingDetails?> createServer({
|
||||
Future<APIGenericResult<ServerHostingDetails?>> createServer({
|
||||
required final String dnsApiToken,
|
||||
required final User rootUser,
|
||||
required final String domainName,
|
||||
required final String serverType,
|
||||
}) async {
|
||||
ServerHostingDetails? details;
|
||||
final APIGenericResult<ServerVolume?> newVolumeResponse =
|
||||
await createVolume();
|
||||
|
||||
final ServerVolume? newVolume = await createVolume();
|
||||
if (newVolume == null) {
|
||||
return details;
|
||||
if (!newVolumeResponse.success || newVolumeResponse.data == null) {
|
||||
return APIGenericResult(
|
||||
data: null,
|
||||
success: false,
|
||||
message: newVolumeResponse.message,
|
||||
code: newVolumeResponse.code,
|
||||
);
|
||||
}
|
||||
|
||||
details = await createServerWithVolume(
|
||||
return createServerWithVolume(
|
||||
dnsApiToken: dnsApiToken,
|
||||
rootUser: rootUser,
|
||||
domainName: domainName,
|
||||
volume: newVolume,
|
||||
volume: newVolumeResponse.data!,
|
||||
serverType: serverType,
|
||||
);
|
||||
|
||||
return details;
|
||||
}
|
||||
|
||||
Future<ServerHostingDetails?> createServerWithVolume({
|
||||
Future<APIGenericResult<ServerHostingDetails?>> createServerWithVolume({
|
||||
required final String dnsApiToken,
|
||||
required final User rootUser,
|
||||
required final String domainName,
|
||||
|
@ -381,6 +398,7 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
|||
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";
|
||||
|
||||
Response? serverCreateResponse;
|
||||
ServerHostingDetails? serverDetails;
|
||||
DioError? hetznerError;
|
||||
bool success = false;
|
||||
|
@ -400,7 +418,7 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
|||
};
|
||||
print('Decoded data: $data');
|
||||
|
||||
final Response serverCreateResponse = await client.post(
|
||||
serverCreateResponse = await client.post(
|
||||
'/servers',
|
||||
data: data,
|
||||
);
|
||||
|
@ -428,11 +446,19 @@ class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
|||
await deleteVolume(volume);
|
||||
}
|
||||
|
||||
if (hetznerError != null) {
|
||||
throw hetznerError;
|
||||
String? apiResultMessage = serverCreateResponse?.statusMessage;
|
||||
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) {
|
||||
|
|
|
@ -32,7 +32,7 @@ abstract class ServerProviderApi extends ApiMap {
|
|||
Future<ServerHostingDetails> powerOn();
|
||||
|
||||
Future<void> deleteServer({required final String domainName});
|
||||
Future<ServerHostingDetails?> createServer({
|
||||
Future<APIGenericResult<ServerHostingDetails?>> createServer({
|
||||
required final String dnsApiToken,
|
||||
required final User rootUser,
|
||||
required final String domainName,
|
||||
|
|
|
@ -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/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';
|
||||
|
||||
mixin VolumeProviderApi on ApiMap {
|
||||
Future<ServerVolume?> createVolume();
|
||||
Future<APIGenericResult<ServerVolume?>> createVolume();
|
||||
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> resizeVolume(final ServerVolume volume, final DiskSize size);
|
||||
Future<void> deleteVolume(final ServerVolume volume);
|
||||
|
|
|
@ -3,7 +3,6 @@ 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/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/get_it/navigation.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backblaze_credential.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
|
||||
|
|
|
@ -113,10 +113,11 @@ class ApiProviderVolumeCubit
|
|||
}
|
||||
|
||||
Future<void> createVolume() async {
|
||||
final ServerVolume? volume = await ApiController
|
||||
.currentVolumeProviderApiFactory!
|
||||
.getVolumeProvider()
|
||||
.createVolume();
|
||||
final ServerVolume? volume = (await ApiController
|
||||
.currentVolumeProviderApiFactory!
|
||||
.getVolumeProvider()
|
||||
.createVolume())
|
||||
.data;
|
||||
|
||||
final diskVolume = DiskVolume(providerVolume: volume);
|
||||
await attachVolume(diskVolume);
|
||||
|
|
|
@ -246,22 +246,52 @@ class ServerInstallationRepository {
|
|||
}) async {
|
||||
final ServerProviderApi api =
|
||||
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 {
|
||||
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 ServerHostingDetails? serverDetails = await api.createServer(
|
||||
final APIGenericResult<ServerHostingDetails?> createServerResult =
|
||||
await api.createServer(
|
||||
dnsApiToken: cloudFlareKey,
|
||||
rootUser: rootUser,
|
||||
domainName: domainName,
|
||||
serverType: getIt<ApiConfigModel>().serverType!,
|
||||
);
|
||||
|
||||
if (serverDetails == null) {
|
||||
print('Server is not initialized!');
|
||||
return;
|
||||
if (createServerResult.data == null) {
|
||||
const String e = 'Server is not initialized!';
|
||||
print(e);
|
||||
}
|
||||
saveServerDetails(serverDetails);
|
||||
onSuccess(serverDetails);
|
||||
} on DioError catch (e) {
|
||||
if (e.response!.data['error']['code'] == 'uniqueness_error') {
|
||||
|
||||
if (createServerResult.message == 'uniqueness_error') {
|
||||
showPopUpAlert(
|
||||
alertTitle: 'modals.already_exists'.tr(),
|
||||
description: 'modals.destroy_server'.tr(),
|
||||
|
@ -273,39 +303,13 @@ class ServerInstallationRepository {
|
|||
|
||||
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;
|
||||
}
|
||||
await saveServerDetails(serverDetails);
|
||||
onSuccess(serverDetails);
|
||||
},
|
||||
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(
|
||||
final APIGenericResult createResult = await api.createServer(
|
||||
dnsApiToken: cloudFlareKey,
|
||||
rootUser: rootUser,
|
||||
domainName: domainName,
|
||||
serverType: getIt<ApiConfigModel>().serverType!,
|
||||
);
|
||||
serverDetails = createResult.data;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
|
@ -320,6 +324,12 @@ class ServerInstallationRepository {
|
|||
cancelButtonOnPressed: onCancel,
|
||||
);
|
||||
}
|
||||
|
||||
saveServerDetails(createServerResult.data!);
|
||||
onSuccess(createServerResult.data!);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
showInstallationErrorPopUp();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
|||
return;
|
||||
}
|
||||
// If API returned error, do nothing
|
||||
final GenericMutationResult<User?> result =
|
||||
final APIGenericResult<User?> result =
|
||||
await api.createUser(user.login, password);
|
||||
if (result.data == null) {
|
||||
getIt<NavigationService>()
|
||||
|
@ -101,7 +101,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
|||
return;
|
||||
}
|
||||
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) {
|
||||
loadedUsers.removeWhere((final User u) => u.login == user.login);
|
||||
await box.clear();
|
||||
|
@ -128,7 +128,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
|||
.showSnackBar('users.could_not_change_password'.tr());
|
||||
return;
|
||||
}
|
||||
final GenericMutationResult<User?> result =
|
||||
final APIGenericResult<User?> result =
|
||||
await api.updateUser(user.login, newPassword);
|
||||
if (result.data == null) {
|
||||
getIt<NavigationService>().showSnackBar(
|
||||
|
@ -138,7 +138,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
|||
}
|
||||
|
||||
Future<void> addSshKey(final User user, final String publicKey) async {
|
||||
final GenericMutationResult<User?> result =
|
||||
final APIGenericResult<User?> result =
|
||||
await api.addSshKey(user.login, publicKey);
|
||||
if (result.data != null) {
|
||||
final User updatedUser = result.data!;
|
||||
|
@ -157,7 +157,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
|||
}
|
||||
|
||||
Future<void> deleteSshKey(final User user, final String publicKey) async {
|
||||
final GenericMutationResult<User?> result =
|
||||
final APIGenericResult<User?> result =
|
||||
await api.removeSshKey(user.login, publicKey);
|
||||
if (result.data != null) {
|
||||
final User updatedUser = result.data!;
|
||||
|
|
Loading…
Reference in a new issue