refactor: Server location is no longer a part of server provider controller.

This commit is contained in:
Inex Code 2024-08-14 06:12:47 +03:00
parent 55616c3e69
commit e13b324afa
23 changed files with 187 additions and 140 deletions

View file

@ -10,7 +10,6 @@ import 'package:selfprivacy/utils/password_generator.dart';
class DigitalOceanApi extends RestApiMap { class DigitalOceanApi extends RestApiMap {
DigitalOceanApi({ DigitalOceanApi({
required this.region,
this.token = '', this.token = '',
this.hasLogger = true, this.hasLogger = true,
this.isWithToken = true, this.isWithToken = true,
@ -21,7 +20,6 @@ class DigitalOceanApi extends RestApiMap {
@override @override
bool isWithToken; bool isWithToken;
final String? region;
final String token; final String token;
@override @override
@ -79,6 +77,7 @@ class DigitalOceanApi extends RestApiMap {
required final String hostName, required final String hostName,
required final String serverType, required final String serverType,
required final String? customSshKey, required final String? customSshKey,
required final String region,
}) async { }) async {
final String stagingAcme = TlsOptions.stagingAcme ? 'true' : 'false'; final String stagingAcme = TlsOptions.stagingAcme ? 'true' : 'false';
@ -98,7 +97,7 @@ class DigitalOceanApi extends RestApiMap {
"HOSTNAME=$hostName LUSER='${rootUser.login}' NIX_VERSION=2.18.1 PROVIDER=$infectProviderName STAGING_ACME='$stagingAcme' " "HOSTNAME=$hostName LUSER='${rootUser.login}' NIX_VERSION=2.18.1 PROVIDER=$infectProviderName STAGING_ACME='$stagingAcme' "
"${customSshKey != null ? "SSH_AUTHORIZED_KEY='$customSshKey'" : ""} " "${customSshKey != null ? "SSH_AUTHORIZED_KEY='$customSshKey'" : ""} "
'bash 2>&1 | tee /root/nixos-infect.log', 'bash 2>&1 | tee /root/nixos-infect.log',
'region': region!, 'region': region,
}; };
print('Decoded data: $data'); print('Decoded data: $data');
@ -326,7 +325,10 @@ class DigitalOceanApi extends RestApiMap {
); );
} }
Future<GenericResult<DigitalOceanVolume?>> createVolume(final int gb) async { Future<GenericResult<DigitalOceanVolume?>> createVolume({
required final int gb,
required final String region,
}) async {
DigitalOceanVolume? volume; DigitalOceanVolume? volume;
Response? createVolumeResponse; Response? createVolumeResponse;
final Dio client = await getClient(); final Dio client = await getClient();
@ -363,10 +365,11 @@ class DigitalOceanApi extends RestApiMap {
); );
} }
Future<GenericResult<bool>> attachVolume( Future<GenericResult<bool>> attachVolume({
final String name, required final String name,
final int serverId, required final int serverId,
) async { required final String region,
}) async {
bool success = false; bool success = false;
Response? attachVolumeResponse; Response? attachVolumeResponse;
@ -402,10 +405,11 @@ class DigitalOceanApi extends RestApiMap {
); );
} }
Future<GenericResult<bool>> detachVolume( Future<GenericResult<bool>> detachVolume({
final String name, required final String name,
final int serverId, required final int serverId,
) async { required final String region,
}) async {
bool success = false; bool success = false;
final Response detachVolumeResponse; final Response detachVolumeResponse;
@ -460,10 +464,11 @@ class DigitalOceanApi extends RestApiMap {
); );
} }
Future<GenericResult<bool>> resizeVolume( Future<GenericResult<bool>> resizeVolume({
final String uuid, required final String uuid,
final int gb, required final int gb,
) async { required final String region,
}) async {
bool success = false; bool success = false;
final Response resizeVolumeResponse; final Response resizeVolumeResponse;

View file

@ -11,7 +11,6 @@ import 'package:selfprivacy/utils/password_generator.dart';
class HetznerApi extends RestApiMap { class HetznerApi extends RestApiMap {
HetznerApi({ HetznerApi({
this.region,
this.token = '', this.token = '',
this.hasLogger = true, this.hasLogger = true,
this.isWithToken = true, this.isWithToken = true,
@ -22,7 +21,6 @@ class HetznerApi extends RestApiMap {
@override @override
bool isWithToken; bool isWithToken;
final String? region;
final String token; final String token;
@override @override
@ -85,6 +83,7 @@ class HetznerApi extends RestApiMap {
required final int volumeId, required final int volumeId,
required final String serverType, required final String serverType,
required final String? customSshKey, required final String? customSshKey,
required final String region,
}) async { }) async {
final String stagingAcme = TlsOptions.stagingAcme ? 'true' : 'false'; final String stagingAcme = TlsOptions.stagingAcme ? 'true' : 'false';
Response? serverCreateResponse; Response? serverCreateResponse;
@ -111,7 +110,7 @@ class HetznerApi extends RestApiMap {
'bash 2>&1 | tee /root/nixos-infect.log', 'bash 2>&1 | tee /root/nixos-infect.log',
'labels': {}, 'labels': {},
'automount': true, 'automount': true,
'location': region!, 'location': region,
}; };
print('Decoded data: $data'); print('Decoded data: $data');
@ -326,7 +325,9 @@ class HetznerApi extends RestApiMap {
return GenericResult(success: true, data: null); return GenericResult(success: true, data: null);
} }
Future<GenericResult<HetznerPricing?>> getPricing() async { Future<GenericResult<HetznerPricing?>> getPricing({
required final String region,
}) async {
HetznerPricing? pricing; HetznerPricing? pricing;
final Response pricingResponse; final Response pricingResponse;
@ -341,14 +342,14 @@ class HetznerApi extends RestApiMap {
for (final primaryIp in primaryIps) { for (final primaryIp in primaryIps) {
if (primaryIp['type'] == 'ipv4') { if (primaryIp['type'] == 'ipv4') {
for (final primaryIpPrice in primaryIp['prices']) { for (final primaryIpPrice in primaryIp['prices']) {
if (primaryIpPrice['location'] == region!) { if (primaryIpPrice['location'] == region) {
ipPrice = primaryIpPrice['price_monthly']['gross']; ipPrice = primaryIpPrice['price_monthly']['gross'];
} }
} }
} }
} }
pricing = HetznerPricing( pricing = HetznerPricing(
region!, region,
double.parse(volumePrice), double.parse(volumePrice),
double.parse(ipPrice!), double.parse(ipPrice!),
); );
@ -395,7 +396,10 @@ class HetznerApi extends RestApiMap {
); );
} }
Future<GenericResult<HetznerVolume?>> createVolume(final int gb) async { Future<GenericResult<HetznerVolume?>> createVolume({
required final int gb,
required final String region,
}) async {
Response? createVolumeResponse; Response? createVolumeResponse;
HetznerVolume? volume; HetznerVolume? volume;
final Dio client = await getClient(); final Dio client = await getClient();

View file

@ -201,7 +201,7 @@ class TokensBloc extends Bloc<TokensEvent, TokensState> {
), ),
apiToken: event.server.hostingDetails.apiToken, apiToken: event.server.hostingDetails.apiToken,
provider: event.serverProviderCredential.provider, provider: event.serverProviderCredential.provider,
serverLocation: event.server.hostingDetails.serverLocation, serverLocation: event.providerServer.location,
serverType: event.server.hostingDetails.serverType, serverType: event.server.hostingDetails.serverType,
), ),
); );

View file

@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'package:bloc_concurrency/bloc_concurrency.dart'; import 'package:bloc_concurrency/bloc_concurrency.dart';
import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -88,14 +89,21 @@ class VolumesBloc extends Bloc<VolumesEvent, VolumesState> {
return null; return null;
} }
Price? price; Price? price;
final pricingResult = final location = state.location;
await ProvidersController.currentServerProvider!.getAdditionalPricing(); if (location != null) {
if (pricingResult.data == null || !pricingResult.success) { final pricingResult = await ProvidersController.currentServerProvider!
.getAdditionalPricing(location);
if (pricingResult.data == null || !pricingResult.success) {
getIt<NavigationService>().showSnackBar('server.pricing_error'.tr());
return price;
}
price = pricingResult.data!.perVolumeGb;
return price;
} else {
await Future.delayed(Duration.zero);
getIt<NavigationService>().showSnackBar('server.pricing_error'.tr()); getIt<NavigationService>().showSnackBar('server.pricing_error'.tr());
return price; return price;
} }
price = pricingResult.data!.perVolumeGb;
return price;
} }
Future<void> _loadState( Future<void> _loadState(

View file

@ -17,6 +17,11 @@ sealed class VolumesState extends Equatable {
orElse: () => DiskVolume(), orElse: () => DiskVolume(),
); );
String? get location => volumes
.firstWhereOrNull((final volume) => volume.isResizable)
?.providerVolume
?.location;
bool get isProviderVolumesLoaded => providerVolumes.isNotEmpty; bool get isProviderVolumesLoaded => providerVolumes.isNotEmpty;
VolumesState copyWith({ VolumesState copyWith({

View file

@ -45,17 +45,26 @@ class ServerDetailsCubit
Future<List<ServerMetadataEntity>> get _metadata async { Future<List<ServerMetadataEntity>> get _metadata async {
final List<ServerMetadataEntity> data = []; final List<ServerMetadataEntity> data = [];
final Server? server = getIt<ResourcesModel>().servers.firstOrNull;
if (server == null) {
return data;
}
final serverProviderApi = ProvidersController.currentServerProvider; final serverProviderApi = ProvidersController.currentServerProvider;
final dnsProviderApi = ProvidersController.currentDnsProvider; final dnsProviderApi = ProvidersController.currentDnsProvider;
if (serverProviderApi?.isAuthorized ?? false) { if (server.hostingDetails.serverLocation != null &&
final serverId = getIt<ResourcesModel>().serverDetails?.id ?? 0; (serverProviderApi?.isAuthorized ?? false)) {
final metadataResult = await serverProviderApi?.getMetadata(serverId); final serverId = server.hostingDetails.id;
final metadataResult = await serverProviderApi?.getMetadata(
serverId,
server.hostingDetails.serverLocation!,
);
data.addAll(metadataResult?.data ?? []); data.addAll(metadataResult?.data ?? []);
} }
if (serverProviderApi == null || !serverProviderApi.isAuthorized) { if (serverProviderApi == null || !serverProviderApi.isAuthorized) {
final Server server = getIt<ResourcesModel>().servers.first;
data.add( data.add(
ServerMetadataEntity( ServerMetadataEntity(
type: MetadataType.other, type: MetadataType.other,
@ -74,7 +83,6 @@ class ServerDetailsCubit
), ),
); );
} else { } else {
final Server server = getIt<ResourcesModel>().servers.first;
data.add( data.add(
ServerMetadataEntity( ServerMetadataEntity(
trId: 'server.dns_provider', trId: 'server.dns_provider',

View file

@ -168,10 +168,12 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
return apiResult.data; return apiResult.data;
} }
Future<AdditionalPricing?> fetchAvailableAdditionalPricing() async { Future<AdditionalPricing?> fetchAvailableAdditionalPricing(
final ServerProviderLocation location,
) async {
AdditionalPricing? prices; AdditionalPricing? prices;
final pricingResult = final pricingResult = await ProvidersController.currentServerProvider!
await ProvidersController.currentServerProvider!.getAdditionalPricing(); .getAdditionalPricing(location.identifier);
if (pricingResult.data == null || !pricingResult.success) { if (pricingResult.data == null || !pricingResult.success) {
getIt<NavigationService>().showSnackBar('server.pricing_error'.tr()); getIt<NavigationService>().showSnackBar('server.pricing_error'.tr());
return prices; return prices;
@ -202,8 +204,11 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
} }
Future<void> setLocationIdentifier(final String locationId) async { Future<void> setLocationIdentifier(final String locationId) async {
await ProvidersController.currentServerProvider! emit(
.trySetServerLocation(locationId); (state as ServerInstallationNotFinished).copyWith(
serverLocation: locationId,
),
);
} }
void setServerType(final ServerType serverType) async { void setServerType(final ServerType serverType) async {
@ -212,6 +217,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
emit( emit(
(state as ServerInstallationNotFinished).copyWith( (state as ServerInstallationNotFinished).copyWith(
serverTypeIdentificator: serverType.identifier, serverTypeIdentificator: serverType.identifier,
serverLocation: serverType.location.identifier,
), ),
); );
} }
@ -335,6 +341,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
successCallback: onCreateServerSuccess, successCallback: onCreateServerSuccess,
storageSize: initialStorage, storageSize: initialStorage,
customSshKey: (state as ServerInstallationNotFinished).customSshKey, customSshKey: (state as ServerInstallationNotFinished).customSshKey,
location: state.serverLocation!,
); );
final result = final result =
@ -794,12 +801,14 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
), ),
apiToken: dataState.serverDetails!.apiToken, apiToken: dataState.serverDetails!.apiToken,
provider: dataState.serverDetails!.provider, provider: dataState.serverDetails!.provider,
serverLocation: server.location,
); );
await repository.saveDomain(serverDomain); await repository.saveDomain(serverDomain);
await repository.saveServerDetails(serverDetails); await repository.saveServerDetails(serverDetails);
emit( emit(
dataState.copyWith( dataState.copyWith(
serverDetails: serverDetails, serverDetails: serverDetails,
serverLocation: server.location,
currentStep: RecoveryStep.dnsProviderToken, currentStep: RecoveryStep.dnsProviderToken,
), ),
); );
@ -858,8 +867,6 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
?.getServerType(state.serverDetails!.id); ?.getServerType(state.serverDetails!.id);
if (serverType != null) { if (serverType != null) {
await repository.saveServerType(serverType.data!); await repository.saveServerType(serverType.data!);
await ProvidersController.currentServerProvider!
.trySetServerLocation(serverType.data!.location.identifier);
} }
} else { } else {
serverType = null; serverType = null;

View file

@ -64,7 +64,6 @@ class ServerInstallationRepository {
ServerProviderSettings( ServerProviderSettings(
provider: serverProvider ?? serverDetails!.provider, provider: serverProvider ?? serverDetails!.provider,
isAuthorized: providerApiToken != null, isAuthorized: providerApiToken != null,
location: location,
token: providerApiToken, token: providerApiToken,
), ),
); );
@ -100,6 +99,7 @@ class ServerInstallationRepository {
serverDomain: serverDomain!, serverDomain: serverDomain!,
backblazeCredential: backblazeCredential!, backblazeCredential: backblazeCredential!,
serverDetails: serverDetails!, serverDetails: serverDetails!,
serverLocation: location,
); );
} }
} }
@ -111,7 +111,6 @@ class ServerInstallationRepository {
ServerProviderSettings( ServerProviderSettings(
provider: wizardData.serverProviderType!, provider: wizardData.serverProviderType!,
isAuthorized: wizardData.serverProviderKey != null, isAuthorized: wizardData.serverProviderKey != null,
location: wizardData.serverLocation,
token: wizardData.serverProviderKey, token: wizardData.serverProviderKey,
), ),
); );
@ -134,6 +133,7 @@ class ServerInstallationRepository {
dnsApiToken: wizardData.dnsProviderKey, dnsApiToken: wizardData.dnsProviderKey,
serverDomain: wizardData.serverDomain, serverDomain: wizardData.serverDomain,
serverTypeIdentificator: wizardData.serverTypeIdentifier, serverTypeIdentificator: wizardData.serverTypeIdentifier,
serverLocation: wizardData.serverLocation,
backblazeCredential: wizardData.backupsCredential, backblazeCredential: wizardData.backupsCredential,
serverDetails: wizardData.serverDetails, serverDetails: wizardData.serverDetails,
currentStep: _getCurrentRecoveryStep( currentStep: _getCurrentRecoveryStep(

View file

@ -13,6 +13,7 @@ abstract class ServerInstallationState extends Equatable {
required this.isServerResetedFirstTime, required this.isServerResetedFirstTime,
required this.isServerResetedSecondTime, required this.isServerResetedSecondTime,
required this.installationDialoguePopUp, required this.installationDialoguePopUp,
required this.serverLocation,
}); });
@override @override
@ -27,11 +28,13 @@ abstract class ServerInstallationState extends Equatable {
isServerStarted, isServerStarted,
isServerResetedFirstTime, isServerResetedFirstTime,
installationDialoguePopUp, installationDialoguePopUp,
serverLocation,
]; ];
final String? providerApiToken; final String? providerApiToken;
final String? dnsApiToken; final String? dnsApiToken;
final String? serverTypeIdentificator; final String? serverTypeIdentificator;
final String? serverLocation;
final BackupsCredential? backblazeCredential; final BackupsCredential? backblazeCredential;
final ServerDomain? serverDomain; final ServerDomain? serverDomain;
final User? rootUser; final User? rootUser;
@ -91,6 +94,7 @@ class TimerState extends ServerInstallationNotFinished {
}) : super( }) : super(
providerApiToken: dataState.providerApiToken, providerApiToken: dataState.providerApiToken,
serverTypeIdentificator: dataState.serverTypeIdentificator, serverTypeIdentificator: dataState.serverTypeIdentificator,
serverLocation: dataState.serverLocation,
dnsApiToken: dataState.dnsApiToken, dnsApiToken: dataState.dnsApiToken,
backblazeCredential: dataState.backblazeCredential, backblazeCredential: dataState.backblazeCredential,
serverDomain: dataState.serverDomain, serverDomain: dataState.serverDomain,
@ -139,6 +143,7 @@ class ServerInstallationNotFinished extends ServerInstallationState {
required this.dnsMatches, required this.dnsMatches,
required this.customSshKey, required this.customSshKey,
super.providerApiToken, super.providerApiToken,
super.serverLocation,
super.serverTypeIdentificator, super.serverTypeIdentificator,
super.dnsApiToken, super.dnsApiToken,
super.backblazeCredential, super.backblazeCredential,
@ -155,6 +160,7 @@ class ServerInstallationNotFinished extends ServerInstallationState {
dnsApiToken: data.dnsProviderKey, dnsApiToken: data.dnsProviderKey,
serverDomain: data.serverDomain, serverDomain: data.serverDomain,
serverTypeIdentificator: data.serverTypeIdentifier, serverTypeIdentificator: data.serverTypeIdentifier,
serverLocation: data.serverLocation,
backblazeCredential: data.backupsCredential, backblazeCredential: data.backupsCredential,
serverDetails: data.serverDetails, serverDetails: data.serverDetails,
rootUser: data.rootUser, rootUser: data.rootUser,
@ -175,6 +181,7 @@ class ServerInstallationNotFinished extends ServerInstallationState {
List<Object?> get props => [ List<Object?> get props => [
providerApiToken, providerApiToken,
serverTypeIdentificator, serverTypeIdentificator,
serverLocation,
dnsApiToken, dnsApiToken,
backblazeCredential, backblazeCredential,
serverDomain, serverDomain,
@ -190,6 +197,7 @@ class ServerInstallationNotFinished extends ServerInstallationState {
ServerInstallationNotFinished copyWith({ ServerInstallationNotFinished copyWith({
final String? providerApiToken, final String? providerApiToken,
final String? serverLocation,
final String? serverTypeIdentificator, final String? serverTypeIdentificator,
final String? dnsApiToken, final String? dnsApiToken,
final BackupsCredential? backblazeCredential, final BackupsCredential? backblazeCredential,
@ -206,6 +214,7 @@ class ServerInstallationNotFinished extends ServerInstallationState {
}) => }) =>
ServerInstallationNotFinished( ServerInstallationNotFinished(
providerApiToken: providerApiToken ?? this.providerApiToken, providerApiToken: providerApiToken ?? this.providerApiToken,
serverLocation: serverLocation ?? this.serverLocation,
serverTypeIdentificator: serverTypeIdentificator:
serverTypeIdentificator ?? this.serverTypeIdentificator, serverTypeIdentificator ?? this.serverTypeIdentificator,
dnsApiToken: dnsApiToken ?? this.dnsApiToken, dnsApiToken: dnsApiToken ?? this.dnsApiToken,
@ -227,6 +236,7 @@ class ServerInstallationNotFinished extends ServerInstallationState {
ServerInstallationFinished finish() => ServerInstallationFinished( ServerInstallationFinished finish() => ServerInstallationFinished(
providerApiToken: providerApiToken, providerApiToken: providerApiToken,
serverLocation: serverLocation,
serverTypeIdentificator: serverTypeIdentificator, serverTypeIdentificator: serverTypeIdentificator,
dnsApiToken: dnsApiToken!, dnsApiToken: dnsApiToken!,
backblazeCredential: backblazeCredential!, backblazeCredential: backblazeCredential!,
@ -239,6 +249,7 @@ class ServerInstallationEmpty extends ServerInstallationNotFinished {
const ServerInstallationEmpty() const ServerInstallationEmpty()
: super( : super(
providerApiToken: null, providerApiToken: null,
serverLocation: null,
serverTypeIdentificator: null, serverTypeIdentificator: null,
dnsApiToken: null, dnsApiToken: null,
backblazeCredential: null, backblazeCredential: null,
@ -263,6 +274,7 @@ class ServerInstallationFinished extends ServerInstallationState {
required ServerHostingDetails super.serverDetails, required ServerHostingDetails super.serverDetails,
super.providerApiToken, super.providerApiToken,
super.serverTypeIdentificator, super.serverTypeIdentificator,
super.serverLocation,
}) : super( }) : super(
rootUser: null, rootUser: null,
isServerStarted: true, isServerStarted: true,
@ -275,6 +287,7 @@ class ServerInstallationFinished extends ServerInstallationState {
List<Object?> get props => [ List<Object?> get props => [
providerApiToken, providerApiToken,
serverTypeIdentificator, serverTypeIdentificator,
serverLocation,
dnsApiToken, dnsApiToken,
backblazeCredential, backblazeCredential,
serverDomain, serverDomain,
@ -315,6 +328,7 @@ class ServerInstallationRecovery extends ServerInstallationState {
required this.recoveryCapabilities, required this.recoveryCapabilities,
super.providerApiToken, super.providerApiToken,
super.serverTypeIdentificator, super.serverTypeIdentificator,
super.serverLocation,
super.dnsApiToken, super.dnsApiToken,
super.backblazeCredential, super.backblazeCredential,
super.serverDomain, super.serverDomain,
@ -333,6 +347,7 @@ class ServerInstallationRecovery extends ServerInstallationState {
List<Object?> get props => [ List<Object?> get props => [
providerApiToken, providerApiToken,
serverTypeIdentificator, serverTypeIdentificator,
serverLocation,
dnsApiToken, dnsApiToken,
backblazeCredential, backblazeCredential,
serverDomain, serverDomain,
@ -346,6 +361,7 @@ class ServerInstallationRecovery extends ServerInstallationState {
ServerInstallationRecovery copyWith({ ServerInstallationRecovery copyWith({
final String? providerApiToken, final String? providerApiToken,
final String? serverLocation,
final String? serverTypeIdentificator, final String? serverTypeIdentificator,
final String? dnsApiToken, final String? dnsApiToken,
final BackupsCredential? backblazeCredential, final BackupsCredential? backblazeCredential,
@ -356,6 +372,7 @@ class ServerInstallationRecovery extends ServerInstallationState {
}) => }) =>
ServerInstallationRecovery( ServerInstallationRecovery(
providerApiToken: providerApiToken ?? this.providerApiToken, providerApiToken: providerApiToken ?? this.providerApiToken,
serverLocation: serverLocation ?? this.serverLocation,
serverTypeIdentificator: serverTypeIdentificator:
serverTypeIdentificator ?? this.serverTypeIdentificator, serverTypeIdentificator ?? this.serverTypeIdentificator,
dnsApiToken: dnsApiToken ?? this.dnsApiToken, dnsApiToken: dnsApiToken ?? this.dnsApiToken,
@ -368,6 +385,7 @@ class ServerInstallationRecovery extends ServerInstallationState {
ServerInstallationFinished finish() => ServerInstallationFinished( ServerInstallationFinished finish() => ServerInstallationFinished(
providerApiToken: providerApiToken, providerApiToken: providerApiToken,
serverLocation: serverLocation,
serverTypeIdentificator: serverTypeIdentificator, serverTypeIdentificator: serverTypeIdentificator,
dnsApiToken: dnsApiToken!, dnsApiToken: dnsApiToken!,
backblazeCredential: backblazeCredential!, backblazeCredential: backblazeCredential!,

View file

@ -76,6 +76,7 @@ class ServerProviderVolume {
required this.serverId, required this.serverId,
required this.linuxDevice, required this.linuxDevice,
this.uuid, this.uuid,
this.location,
}); });
@HiveField(1) @HiveField(1)
@ -90,6 +91,8 @@ class ServerProviderVolume {
String? linuxDevice; String? linuxDevice;
@HiveField(6, defaultValue: null) @HiveField(6, defaultValue: null)
String? uuid; String? uuid;
@HiveField(7, defaultValue: null)
String? location;
} }
@HiveType(typeId: 101) @HiveType(typeId: 101)

View file

@ -83,13 +83,14 @@ class ServerProviderVolumeAdapter extends TypeAdapter<ServerProviderVolume> {
serverId: fields[4] as int?, serverId: fields[4] as int?,
linuxDevice: fields[5] as String?, linuxDevice: fields[5] as String?,
uuid: fields[6] as String?, uuid: fields[6] as String?,
location: fields[7] as String?,
); );
} }
@override @override
void write(BinaryWriter writer, ServerProviderVolume obj) { void write(BinaryWriter writer, ServerProviderVolume obj) {
writer writer
..writeByte(6) ..writeByte(7)
..writeByte(1) ..writeByte(1)
..write(obj.id) ..write(obj.id)
..writeByte(2) ..writeByte(2)
@ -101,7 +102,9 @@ class ServerProviderVolumeAdapter extends TypeAdapter<ServerProviderVolume> {
..writeByte(5) ..writeByte(5)
..write(obj.linuxDevice) ..write(obj.linuxDevice)
..writeByte(6) ..writeByte(6)
..write(obj.uuid); ..write(obj.uuid)
..writeByte(7)
..write(obj.location);
} }
@override @override

View file

@ -9,6 +9,7 @@ class DigitalOceanVolume {
this.name, this.name,
this.sizeGigabytes, this.sizeGigabytes,
this.dropletIds, this.dropletIds,
this.region,
); );
final String id; final String id;
@ -20,6 +21,8 @@ class DigitalOceanVolume {
@JsonKey(name: 'size_gigabytes') @JsonKey(name: 'size_gigabytes')
final int sizeGigabytes; final int sizeGigabytes;
final DigitalOceanLocation region;
static DigitalOceanVolume fromJson(final Map<String, dynamic> json) => static DigitalOceanVolume fromJson(final Map<String, dynamic> json) =>
_$DigitalOceanVolumeFromJson(json); _$DigitalOceanVolumeFromJson(json);
} }

View file

@ -14,6 +14,7 @@ DigitalOceanVolume _$DigitalOceanVolumeFromJson(Map<String, dynamic> json) =>
(json['droplet_ids'] as List<dynamic>?) (json['droplet_ids'] as List<dynamic>?)
?.map((e) => (e as num).toInt()) ?.map((e) => (e as num).toInt())
.toList(), .toList(),
DigitalOceanLocation.fromJson(json['region'] as Map<String, dynamic>),
); );
Map<String, dynamic> _$DigitalOceanVolumeToJson(DigitalOceanVolume instance) => Map<String, dynamic> _$DigitalOceanVolumeToJson(DigitalOceanVolume instance) =>
@ -22,6 +23,7 @@ Map<String, dynamic> _$DigitalOceanVolumeToJson(DigitalOceanVolume instance) =>
'name': instance.name, 'name': instance.name,
'droplet_ids': instance.dropletIds, 'droplet_ids': instance.dropletIds,
'size_gigabytes': instance.sizeGigabytes, 'size_gigabytes': instance.sizeGigabytes,
'region': instance.region,
}; };
DigitalOceanLocation _$DigitalOceanLocationFromJson( DigitalOceanLocation _$DigitalOceanLocationFromJson(

View file

@ -127,6 +127,9 @@ class HetznerLocation {
this.zone, this.zone,
this.name, this.name,
); );
HetznerLocation.empty() : this('', '', '', '', '');
final String name; final String name;
final String country; final String country;
final String city; final String city;
@ -192,6 +195,7 @@ class HetznerVolume {
this.serverId, this.serverId,
this.name, this.name,
this.linuxDevice, this.linuxDevice,
this.location,
); );
/// ID of the Resource /// ID of the Resource
@ -210,6 +214,8 @@ class HetznerVolume {
@JsonKey(name: 'linux_device') @JsonKey(name: 'linux_device')
final String? linuxDevice; final String? linuxDevice;
final HetznerLocation location;
static HetznerVolume fromJson(final Map<String, dynamic> json) => static HetznerVolume fromJson(final Map<String, dynamic> json) =>
_$HetznerVolumeFromJson(json); _$HetznerVolumeFromJson(json);
} }

View file

@ -139,6 +139,7 @@ HetznerVolume _$HetznerVolumeFromJson(Map<String, dynamic> json) =>
(json['serverId'] as num?)?.toInt(), (json['serverId'] as num?)?.toInt(),
json['name'] as String, json['name'] as String,
json['linux_device'] as String?, json['linux_device'] as String?,
HetznerLocation.fromJson(json['location'] as Map<String, dynamic>),
); );
Map<String, dynamic> _$HetznerVolumeToJson(HetznerVolume instance) => Map<String, dynamic> _$HetznerVolumeToJson(HetznerVolume instance) =>
@ -148,4 +149,5 @@ Map<String, dynamic> _$HetznerVolumeToJson(HetznerVolume instance) =>
'serverId': instance.serverId, 'serverId': instance.serverId,
'name': instance.name, 'name': instance.name,
'linux_device': instance.linuxDevice, 'linux_device': instance.linuxDevice,
'location': instance.location,
}; };

View file

@ -14,6 +14,7 @@ class LaunchInstallationData {
required this.successCallback, required this.successCallback,
required this.storageSize, required this.storageSize,
required this.customSshKey, required this.customSshKey,
required this.location,
}); });
final User rootUser; final User rootUser;
@ -25,4 +26,5 @@ class LaunchInstallationData {
final Function(ServerHostingDetails details) successCallback; final Function(ServerHostingDetails details) successCallback;
final DiskSize storageSize; final DiskSize storageSize;
final String? customSshKey; final String? customSshKey;
final String location;
} }

View file

@ -5,12 +5,14 @@ class ServerBasicInfo {
required this.reverseDns, required this.reverseDns,
required this.ip, required this.ip,
required this.created, required this.created,
required this.location,
}); });
final int id; final int id;
final String name; final String name;
final String reverseDns; final String reverseDns;
final String ip; final String ip;
final DateTime created; final DateTime created;
final String location;
} }
class ServerBasicInfoWithValidators extends ServerBasicInfo { class ServerBasicInfoWithValidators extends ServerBasicInfo {
@ -24,6 +26,7 @@ class ServerBasicInfoWithValidators extends ServerBasicInfo {
reverseDns: serverBasicInfo.reverseDns, reverseDns: serverBasicInfo.reverseDns,
ip: serverBasicInfo.ip, ip: serverBasicInfo.ip,
created: serverBasicInfo.created, created: serverBasicInfo.created,
location: serverBasicInfo.location,
isIpValid: isIpValid, isIpValid: isIpValid,
isReverseDnsValid: isReverseDnsValid, isReverseDnsValid: isReverseDnsValid,
); );
@ -34,6 +37,7 @@ class ServerBasicInfoWithValidators extends ServerBasicInfo {
required super.reverseDns, required super.reverseDns,
required super.ip, required super.ip,
required super.created, required super.created,
required super.location,
required this.isIpValid, required this.isIpValid,
required this.isReverseDnsValid, required this.isReverseDnsValid,
}); });

View file

@ -7,13 +7,11 @@ class ServerProviderSettings {
required this.provider, required this.provider,
this.token, this.token,
this.isAuthorized = false, this.isAuthorized = false,
this.location,
}); });
final bool isAuthorized; final bool isAuthorized;
final ServerProviderType provider; final ServerProviderType provider;
final String? token; final String? token;
final String? location;
} }
class DnsProviderSettings { class DnsProviderSettings {

View file

@ -19,11 +19,9 @@ import 'package:selfprivacy/utils/password_generator.dart';
class ApiAdapter { class ApiAdapter {
ApiAdapter({ ApiAdapter({
final String? region,
final bool isWithToken = true, final bool isWithToken = true,
final String? token, final String? token,
}) : _api = DigitalOceanApi( }) : _api = DigitalOceanApi(
region: region,
isWithToken: isWithToken, isWithToken: isWithToken,
token: token ?? '', token: token ?? '',
); );
@ -31,7 +29,6 @@ class ApiAdapter {
DigitalOceanApi api({final bool getInitialized = true}) => getInitialized DigitalOceanApi api({final bool getInitialized = true}) => getInitialized
? _api ? _api
: DigitalOceanApi( : DigitalOceanApi(
region: _api.region,
isWithToken: false, isWithToken: false,
); );
@ -41,16 +38,14 @@ class ApiAdapter {
class DigitalOceanServerProvider extends ServerProvider { class DigitalOceanServerProvider extends ServerProvider {
DigitalOceanServerProvider() : _adapter = ApiAdapter(isWithToken: false); DigitalOceanServerProvider() : _adapter = ApiAdapter(isWithToken: false);
DigitalOceanServerProvider.load( DigitalOceanServerProvider.load(
final String? location,
final bool isAuthorized, final bool isAuthorized,
final String? token, final String? token,
) : _adapter = ApiAdapter( ) : _adapter = ApiAdapter(
isWithToken: isAuthorized, isWithToken: isAuthorized,
region: location,
token: token, token: token,
); );
ApiAdapter _adapter; final ApiAdapter _adapter;
final Currency currency = Currency.fromType(CurrencyType.usd); final Currency currency = Currency.fromType(CurrencyType.usd);
@override @override
@ -90,6 +85,7 @@ class DigitalOceanServerProvider extends ServerProvider {
created: DateTime.now(), created: DateTime.now(),
ip: ipv4, ip: ipv4,
name: server['name'], name: server['name'],
location: server['region']['slug'],
); );
}, },
).toList(); ).toList();
@ -238,6 +234,7 @@ class DigitalOceanServerProvider extends ServerProvider {
databasePassword: StringGenerators.dbPassword(), databasePassword: StringGenerators.dbPassword(),
serverApiToken: serverApiToken, serverApiToken: serverApiToken,
customSshKey: installationData.customSshKey, customSshKey: installationData.customSshKey,
region: installationData.location,
); );
if (!serverResult.success || serverResult.data == null) { if (!serverResult.success || serverResult.data == null) {
@ -264,12 +261,15 @@ class DigitalOceanServerProvider extends ServerProvider {
try { try {
final int dropletId = serverResult.data!; final int dropletId = serverResult.data!;
final newVolume = final newVolume = (await createVolume(
(await createVolume(installationData.storageSize.gibibyte.toInt())) installationData.storageSize.gibibyte.toInt(),
.data; installationData.location,
))
.data;
final bool attachedVolume = (await _adapter.api().attachVolume( final bool attachedVolume = (await _adapter.api().attachVolume(
newVolume!.name, name: newVolume!.name,
dropletId, serverId: dropletId,
region: installationData.location,
)) ))
.data; .data;
@ -350,9 +350,14 @@ class DigitalOceanServerProvider extends ServerProvider {
(final el) => el.serverId == foundServer!.id, (final el) => el.serverId == foundServer!.id,
); );
if (volumeToRemove.location == null) {
throw Exception('Volume location is null!');
}
await _adapter.api().detachVolume( await _adapter.api().detachVolume(
volumeToRemove.name, name: volumeToRemove.name,
volumeToRemove.serverId!, serverId: volumeToRemove.serverId!,
region: volumeToRemove.location!,
); );
await Future.delayed(const Duration(seconds: 10)); await Future.delayed(const Duration(seconds: 10));
@ -400,33 +405,9 @@ class DigitalOceanServerProvider extends ServerProvider {
return result; return result;
} }
_adapter = ApiAdapter(region: api.region, isWithToken: true);
return result; return result;
} }
@override
Future<GenericResult<bool>> trySetServerLocation(
final String location,
) async {
final bool apiInitialized = _adapter.api().isWithToken;
final String token = _adapter._api.token;
if (!apiInitialized || token.isEmpty) {
return GenericResult(
success: true,
data: false,
message: 'Not authorized!',
);
}
_adapter = ApiAdapter(
isWithToken: true,
region: location,
token: token,
);
return success;
}
@override @override
Future<GenericResult<List<ServerProviderLocation>>> Future<GenericResult<List<ServerProviderLocation>>>
getAvailableLocations() async { getAvailableLocations() async {
@ -544,7 +525,9 @@ class DigitalOceanServerProvider extends ServerProvider {
} }
@override @override
Future<GenericResult<AdditionalPricing?>> getAdditionalPricing() async => Future<GenericResult<AdditionalPricing?>> getAdditionalPricing(
final String location,
) async =>
GenericResult( GenericResult(
success: true, success: true,
data: AdditionalPricing( data: AdditionalPricing(
@ -591,6 +574,7 @@ class DigitalOceanServerProvider extends ServerProvider {
: null, : null,
linuxDevice: 'scsi-0DO_Volume_$volumeName', linuxDevice: 'scsi-0DO_Volume_$volumeName',
uuid: rawVolume.id, uuid: rawVolume.id,
location: rawVolume.region.slug,
); );
volumes.add(volume); volumes.add(volume);
} }
@ -612,10 +596,11 @@ class DigitalOceanServerProvider extends ServerProvider {
@override @override
Future<GenericResult<ServerProviderVolume?>> createVolume( Future<GenericResult<ServerProviderVolume?>> createVolume(
final int gb, final int gb,
final String location,
) async { ) async {
ServerProviderVolume? volume; ServerProviderVolume? volume;
final result = await _adapter.api().createVolume(gb); final result = await _adapter.api().createVolume(gb: gb, region: location);
if (!result.success || result.data == null) { if (!result.success || result.data == null) {
return GenericResult( return GenericResult(
@ -687,8 +672,9 @@ class DigitalOceanServerProvider extends ServerProvider {
final int serverId, final int serverId,
) async => ) async =>
_adapter.api().attachVolume( _adapter.api().attachVolume(
volume.name, name: volume.name,
serverId, serverId: serverId,
region: volume.location!,
); );
@override @override
@ -696,8 +682,9 @@ class DigitalOceanServerProvider extends ServerProvider {
final ServerProviderVolume volume, final ServerProviderVolume volume,
) async => ) async =>
_adapter.api().detachVolume( _adapter.api().detachVolume(
volume.name, name: volume.name,
volume.serverId!, serverId: volume.serverId!,
region: volume.location!,
); );
@override @override
@ -714,13 +701,15 @@ class DigitalOceanServerProvider extends ServerProvider {
final DiskSize size, final DiskSize size,
) async => ) async =>
_adapter.api().resizeVolume( _adapter.api().resizeVolume(
volume.uuid!, uuid: volume.uuid!,
size.gibibyte.toInt(), gb: size.gibibyte.toInt(),
region: volume.location!,
); );
@override @override
Future<GenericResult<List<ServerMetadataEntity>>> getMetadata( Future<GenericResult<List<ServerMetadataEntity>>> getMetadata(
final int serverId, final int serverId,
final String location,
) async { ) async {
List<ServerMetadataEntity> metadata = []; List<ServerMetadataEntity> metadata = [];
final result = await _adapter.api().getServers(); final result = await _adapter.api().getServers();
@ -741,7 +730,7 @@ class DigitalOceanServerProvider extends ServerProvider {
message: resultVolumes.message, message: resultVolumes.message,
); );
} }
final resultPricePerGb = await getAdditionalPricing(); final resultPricePerGb = await getAdditionalPricing(location);
if (resultPricePerGb.data == null || !resultPricePerGb.success) { if (resultPricePerGb.data == null || !resultPricePerGb.success) {
return GenericResult( return GenericResult(
success: false, success: false,

View file

@ -19,11 +19,9 @@ import 'package:selfprivacy/utils/password_generator.dart';
class ApiAdapter { class ApiAdapter {
ApiAdapter({ ApiAdapter({
final String? region,
final bool isWithToken = true, final bool isWithToken = true,
final String? token, final String? token,
}) : _api = HetznerApi( }) : _api = HetznerApi(
region: region,
isWithToken: isWithToken, isWithToken: isWithToken,
token: token ?? '', token: token ?? '',
); );
@ -31,7 +29,6 @@ class ApiAdapter {
HetznerApi api({final bool getInitialized = true}) => getInitialized HetznerApi api({final bool getInitialized = true}) => getInitialized
? _api ? _api
: HetznerApi( : HetznerApi(
region: _api.region,
isWithToken: false, isWithToken: false,
); );
@ -41,16 +38,14 @@ class ApiAdapter {
class HetznerServerProvider extends ServerProvider { class HetznerServerProvider extends ServerProvider {
HetznerServerProvider() : _adapter = ApiAdapter(isWithToken: false); HetznerServerProvider() : _adapter = ApiAdapter(isWithToken: false);
HetznerServerProvider.load( HetznerServerProvider.load(
final String? location,
final bool isAuthorized, final bool isAuthorized,
final String? token, final String? token,
) : _adapter = ApiAdapter( ) : _adapter = ApiAdapter(
isWithToken: isAuthorized, isWithToken: isAuthorized,
region: location,
token: token, token: token,
); );
ApiAdapter _adapter; final ApiAdapter _adapter;
final Currency currency = Currency.fromType(CurrencyType.eur); final Currency currency = Currency.fromType(CurrencyType.eur);
int? cachedCoreAmount; int? cachedCoreAmount;
@ -87,6 +82,7 @@ class HetznerServerProvider extends ServerProvider {
ip: hetznerServer.publicNet.ipv4!.ip, ip: hetznerServer.publicNet.ipv4!.ip,
reverseDns: hetznerServer.publicNet.ipv4!.reverseDns, reverseDns: hetznerServer.publicNet.ipv4!.reverseDns,
created: hetznerServer.created, created: hetznerServer.created,
location: hetznerServer.location.name,
); );
} catch (e) { } catch (e) {
continue; continue;
@ -176,7 +172,8 @@ class HetznerServerProvider extends ServerProvider {
final LaunchInstallationData installationData, final LaunchInstallationData installationData,
) async { ) async {
final volumeResult = await _adapter.api().createVolume( final volumeResult = await _adapter.api().createVolume(
installationData.storageSize.gibibyte.toInt(), gb: installationData.storageSize.gibibyte.toInt(),
region: installationData.location,
); );
if (!volumeResult.success || volumeResult.data == null) { if (!volumeResult.success || volumeResult.data == null) {
@ -222,6 +219,7 @@ class HetznerServerProvider extends ServerProvider {
databasePassword: StringGenerators.dbPassword(), databasePassword: StringGenerators.dbPassword(),
serverApiToken: serverApiToken, serverApiToken: serverApiToken,
customSshKey: installationData.customSshKey, customSshKey: installationData.customSshKey,
region: installationData.location,
); );
if (!serverResult.success || serverResult.data == null) { if (!serverResult.success || serverResult.data == null) {
@ -419,33 +417,9 @@ class HetznerServerProvider extends ServerProvider {
return result; return result;
} }
// _adapter = ApiAdapter(region: api.region, isWithToken: true);
return result; return result;
} }
@override
Future<GenericResult<bool>> trySetServerLocation(
final String location,
) async {
final bool apiInitialized = _adapter.api().isWithToken;
final String token = _adapter._api.token;
if (!apiInitialized || token.isEmpty) {
return GenericResult(
success: true,
data: false,
message: 'Not authorized!',
);
}
_adapter = ApiAdapter(
isWithToken: true,
region: location,
token: token,
);
return success;
}
@override @override
Future<GenericResult<List<ServerProviderLocation>>> Future<GenericResult<List<ServerProviderLocation>>>
getAvailableLocations() async { getAvailableLocations() async {
@ -566,8 +540,10 @@ class HetznerServerProvider extends ServerProvider {
} }
@override @override
Future<GenericResult<AdditionalPricing?>> getAdditionalPricing() async { Future<GenericResult<AdditionalPricing?>> getAdditionalPricing(
final result = await _adapter.api().getPricing(); final String location,
) async {
final result = await _adapter.api().getPricing(region: location);
if (!result.success || result.data == null) { if (!result.success || result.data == null) {
return GenericResult( return GenericResult(
@ -617,12 +593,14 @@ class HetznerServerProvider extends ServerProvider {
final volumeServer = rawVolume.serverId; final volumeServer = rawVolume.serverId;
final String volumeName = rawVolume.name; final String volumeName = rawVolume.name;
final volumeDevice = rawVolume.linuxDevice; final volumeDevice = rawVolume.linuxDevice;
final volumeLocation = rawVolume.location.name;
final volume = ServerProviderVolume( final volume = ServerProviderVolume(
id: volumeId, id: volumeId,
name: volumeName, name: volumeName,
sizeByte: volumeSize, sizeByte: volumeSize,
serverId: volumeServer, serverId: volumeServer,
linuxDevice: volumeDevice, linuxDevice: volumeDevice,
location: volumeLocation,
); );
volumes.add(volume); volumes.add(volume);
} }
@ -645,10 +623,11 @@ class HetznerServerProvider extends ServerProvider {
@override @override
Future<GenericResult<ServerProviderVolume?>> createVolume( Future<GenericResult<ServerProviderVolume?>> createVolume(
final int gb, final int gb,
final String location,
) async { ) async {
ServerProviderVolume? volume; ServerProviderVolume? volume;
final result = await _adapter.api().createVolume(gb); final result = await _adapter.api().createVolume(gb: gb, region: location);
if (!result.success || result.data == null) { if (!result.success || result.data == null) {
return GenericResult( return GenericResult(
@ -702,6 +681,7 @@ class HetznerServerProvider extends ServerProvider {
volume.serverId, volume.serverId,
volume.name, volume.name,
volume.linuxDevice, volume.linuxDevice,
HetznerLocation.empty(),
), ),
size, size,
); );
@ -718,6 +698,7 @@ class HetznerServerProvider extends ServerProvider {
volume.serverId, volume.serverId,
volume.name, volume.name,
volume.linuxDevice, volume.linuxDevice,
HetznerLocation.empty(),
), ),
serverId, serverId,
); );
@ -733,6 +714,7 @@ class HetznerServerProvider extends ServerProvider {
@override @override
Future<GenericResult<List<ServerMetadataEntity>>> getMetadata( Future<GenericResult<List<ServerMetadataEntity>>> getMetadata(
final int serverId, final int serverId,
final String location,
) async { ) async {
List<ServerMetadataEntity> metadata = []; List<ServerMetadataEntity> metadata = [];
final resultServers = await _adapter.api().getServers(); final resultServers = await _adapter.api().getServers();
@ -753,7 +735,7 @@ class HetznerServerProvider extends ServerProvider {
message: resultVolumes.message, message: resultVolumes.message,
); );
} }
final resultPricePerGb = await getAdditionalPricing(); final resultPricePerGb = await getAdditionalPricing(location);
if (resultPricePerGb.data == null || !resultPricePerGb.success) { if (resultPricePerGb.data == null || !resultPricePerGb.success) {
return GenericResult( return GenericResult(
success: false, success: false,

View file

@ -60,12 +60,6 @@ abstract class ServerProvider {
/// server provider respectfully. /// server provider respectfully.
Future<GenericResult<bool>> tryInitApiByToken(final String token); Future<GenericResult<bool>> tryInitApiByToken(final String token);
/// Tries to assign the location shortcode for future usage.
///
/// If API wasn't initialized with token by [tryInitApiByToken] beforehand,
/// returns 'Not authorized!' error.
Future<GenericResult<bool>> trySetServerLocation(final String location);
/// Returns all available server locations /// Returns all available server locations
/// of the authorized user's server provider. /// of the authorized user's server provider.
Future<GenericResult<List<ServerProviderLocation>>> getAvailableLocations(); Future<GenericResult<List<ServerProviderLocation>>> getAvailableLocations();
@ -92,7 +86,9 @@ abstract class ServerProvider {
/// Returns [Price] information map of all additional resources, excluding /// Returns [Price] information map of all additional resources, excluding
/// main server type pricing /// main server type pricing
Future<GenericResult<AdditionalPricing?>> getAdditionalPricing(); Future<GenericResult<AdditionalPricing?>> getAdditionalPricing(
final String location,
);
/// Returns [ServerProviderVolume] of all available volumes /// Returns [ServerProviderVolume] of all available volumes
/// assigned to the authorized user and attached to active machine. /// assigned to the authorized user and attached to active machine.
@ -103,7 +99,10 @@ abstract class ServerProvider {
/// Tries to create an empty unattached [ServerProviderVolume]. /// Tries to create an empty unattached [ServerProviderVolume].
/// ///
/// If success, returns this volume information. /// If success, returns this volume information.
Future<GenericResult<ServerProviderVolume?>> createVolume(final int gb); Future<GenericResult<ServerProviderVolume?>> createVolume(
final int gb,
final String location,
);
/// Tries to delete the requested accessible [ServerProviderVolume]. /// Tries to delete the requested accessible [ServerProviderVolume].
Future<GenericResult<void>> deleteVolume(final ServerProviderVolume volume); Future<GenericResult<void>> deleteVolume(final ServerProviderVolume volume);
@ -126,10 +125,11 @@ abstract class ServerProvider {
/// from any machine. /// from any machine.
Future<GenericResult<bool>> detachVolume(final ServerProviderVolume volume); Future<GenericResult<bool>> detachVolume(final ServerProviderVolume volume);
/// Returns metedata of an accessible machine by the provided identificator /// Returns metadata of an accessible machine by the provided identificator
/// to show on ServerDetailsScreen. /// to show on ServerDetailsScreen.
Future<GenericResult<List<ServerMetadataEntity>>> getMetadata( Future<GenericResult<List<ServerMetadataEntity>>> getMetadata(
final int serverId, final int serverId,
final String location,
); );
/// Returns information about cpu and bandwidth load within the provided /// Returns information about cpu and bandwidth load within the provided

View file

@ -17,7 +17,6 @@ class ServerProviderFactory {
case ServerProviderType.hetzner: case ServerProviderType.hetzner:
return settings.isAuthorized return settings.isAuthorized
? HetznerServerProvider.load( ? HetznerServerProvider.load(
settings.location,
settings.isAuthorized, settings.isAuthorized,
settings.token, settings.token,
) )
@ -25,7 +24,6 @@ class ServerProviderFactory {
case ServerProviderType.digitalOcean: case ServerProviderType.digitalOcean:
return settings.isAuthorized return settings.isAuthorized
? DigitalOceanServerProvider.load( ? DigitalOceanServerProvider.load(
settings.location,
settings.isAuthorized, settings.isAuthorized,
settings.token, settings.token,
) )

View file

@ -172,7 +172,7 @@ class SelectTypePage extends StatelessWidget {
final Future<List<ServerType>> serverTypes = final Future<List<ServerType>> serverTypes =
serverInstallationCubit.fetchAvailableTypesByLocation(location); serverInstallationCubit.fetchAvailableTypesByLocation(location);
final Future<AdditionalPricing?> prices = final Future<AdditionalPricing?> prices =
serverInstallationCubit.fetchAvailableAdditionalPricing(); serverInstallationCubit.fetchAvailableAdditionalPricing(location);
return FutureBuilder( return FutureBuilder(
future: Future.wait([ future: Future.wait([
serverTypes, serverTypes,