From 7ff1e361612ec32383bea32927dcd9fcf7920a40 Mon Sep 17 00:00:00 2001 From: NaiJi Date: Thu, 13 Jul 2023 06:22:39 -0300 Subject: [PATCH] refactor(rest-api): Move rest api methods according to their business logic files positions - Rename unmatching functions --- .../cloudflare/cloudflare_api.dart | 114 +-- .../dns_providers/desec/desec_api.dart | 114 +-- .../digital_ocean_dns_api.dart | 124 +-- .../digital_ocean/digital_ocean_api.dart | 438 +++++------ .../server_providers/hetzner/hetzner_api.dart | 728 +++++++++--------- lib/logic/providers/dns_providers/desec.dart | 6 +- .../dns_providers/digital_ocean_dns.dart | 2 +- 7 files changed, 763 insertions(+), 763 deletions(-) diff --git a/lib/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare_api.dart b/lib/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare_api.dart index 9fe74841..ae015d9d 100644 --- a/lib/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare_api.dart +++ b/lib/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare_api.dart @@ -92,22 +92,23 @@ class CloudflareApi extends RestApiMap { ); } - Future>> getZones(final String domain) async { - List zones = []; + Future> getDomains() async { + final String url = '$rootAddress/zones'; + List domains = []; late final Response? response; final Dio client = await getClient(); try { response = await client.get( - '/zones', - queryParameters: {'name': domain}, + url, + queryParameters: {'per_page': 50}, ); - zones = response.data['result']; + domains = response.data['result']; } catch (e) { print(e); - GenericResult( + return GenericResult( success: false, - data: zones, + data: domains, code: response?.statusCode, message: response?.statusMessage, ); @@ -115,7 +116,47 @@ class CloudflareApi extends RestApiMap { close(client); } - return GenericResult(success: true, data: zones); + return GenericResult( + success: true, + data: domains, + code: response.statusCode, + message: response.statusMessage, + ); + } + + Future> createMultipleDnsRecords({ + required final ServerDomain domain, + required final List records, + }) async { + final String domainZoneId = domain.zoneId; + final List allCreateFutures = []; + + final Dio client = await getClient(); + try { + for (final DnsRecord record in records) { + allCreateFutures.add( + client.post( + '/zones/$domainZoneId/dns_records', + data: record.toJson(), + ), + ); + } + await Future.wait(allCreateFutures); + } on DioError catch (e) { + print(e.message); + rethrow; + } catch (e) { + print(e); + return GenericResult( + success: false, + data: null, + message: e.toString(), + ); + } finally { + close(client); + } + + return GenericResult(success: true, data: null); } Future> removeSimilarRecords({ @@ -183,58 +224,22 @@ class CloudflareApi extends RestApiMap { return GenericResult(data: allRecords, success: true); } - Future> createMultipleDnsRecords({ - required final ServerDomain domain, - required final List records, - }) async { - final String domainZoneId = domain.zoneId; - final List allCreateFutures = []; - - final Dio client = await getClient(); - try { - for (final DnsRecord record in records) { - allCreateFutures.add( - client.post( - '/zones/$domainZoneId/dns_records', - data: record.toJson(), - ), - ); - } - await Future.wait(allCreateFutures); - } on DioError catch (e) { - print(e.message); - rethrow; - } catch (e) { - print(e); - return GenericResult( - success: false, - data: null, - message: e.toString(), - ); - } finally { - close(client); - } - - return GenericResult(success: true, data: null); - } - - Future> getDomains() async { - final String url = '$rootAddress/zones'; - List domains = []; + Future>> getZones(final String domain) async { + List zones = []; late final Response? response; final Dio client = await getClient(); try { response = await client.get( - url, - queryParameters: {'per_page': 50}, + '/zones', + queryParameters: {'name': domain}, ); - domains = response.data['result']; + zones = response.data['result']; } catch (e) { print(e); - return GenericResult( + GenericResult( success: false, - data: domains, + data: zones, code: response?.statusCode, message: response?.statusMessage, ); @@ -242,11 +247,6 @@ class CloudflareApi extends RestApiMap { close(client); } - return GenericResult( - success: true, - data: domains, - code: response.statusCode, - message: response.statusMessage, - ); + return GenericResult(success: true, data: zones); } } diff --git a/lib/logic/api_maps/rest_maps/dns_providers/desec/desec_api.dart b/lib/logic/api_maps/rest_maps/dns_providers/desec/desec_api.dart index e5eff146..960df30f 100644 --- a/lib/logic/api_maps/rest_maps/dns_providers/desec/desec_api.dart +++ b/lib/logic/api_maps/rest_maps/dns_providers/desec/desec_api.dart @@ -92,7 +92,63 @@ class DesecApi extends RestApiMap { ); } - Future> updateRecords({ + Future> getDomains() async { + List domains = []; + + late final Response? response; + final Dio client = await getClient(); + try { + response = await client.get( + '', + ); + await Future.delayed(const Duration(seconds: 1)); + domains = response.data; + } catch (e) { + print(e); + return GenericResult( + success: false, + data: domains, + code: response?.statusCode, + message: response?.statusMessage, + ); + } finally { + close(client); + } + + return GenericResult( + success: true, + data: domains, + code: response.statusCode, + message: response.statusMessage, + ); + } + + Future> createMultipleDnsRecords({ + required final ServerDomain domain, + required final List records, + }) async { + final String domainName = domain.domainName; + final String url = '/$domainName/rrsets/'; + + final Dio client = await getClient(); + try { + await client.post(url, data: records); + await Future.delayed(const Duration(seconds: 1)); + } catch (e) { + print(e); + return GenericResult( + success: false, + data: null, + message: e.toString(), + ); + } finally { + close(client); + } + + return GenericResult(success: true, data: null); + } + + Future> removeSimilarRecords({ required final ServerDomain domain, required final List records, }) async { @@ -145,60 +201,4 @@ class DesecApi extends RestApiMap { return GenericResult(data: allRecords, success: true); } - - Future> createRecords({ - required final ServerDomain domain, - required final List records, - }) async { - final String domainName = domain.domainName; - final String url = '/$domainName/rrsets/'; - - final Dio client = await getClient(); - try { - await client.post(url, data: records); - await Future.delayed(const Duration(seconds: 1)); - } catch (e) { - print(e); - return GenericResult( - success: false, - data: null, - message: e.toString(), - ); - } finally { - close(client); - } - - return GenericResult(success: true, data: null); - } - - Future> getDomains() async { - List domains = []; - - late final Response? response; - final Dio client = await getClient(); - try { - response = await client.get( - '', - ); - await Future.delayed(const Duration(seconds: 1)); - domains = response.data; - } catch (e) { - print(e); - return GenericResult( - success: false, - data: domains, - code: response?.statusCode, - message: response?.statusMessage, - ); - } finally { - close(client); - } - - return GenericResult( - success: true, - data: domains, - code: response.statusCode, - message: response.statusMessage, - ); - } } diff --git a/lib/logic/api_maps/rest_maps/dns_providers/digital_ocean_dns/digital_ocean_dns_api.dart b/lib/logic/api_maps/rest_maps/dns_providers/digital_ocean_dns/digital_ocean_dns_api.dart index 348edc77..70a70b7c 100644 --- a/lib/logic/api_maps/rest_maps/dns_providers/digital_ocean_dns/digital_ocean_dns_api.dart +++ b/lib/logic/api_maps/rest_maps/dns_providers/digital_ocean_dns/digital_ocean_dns_api.dart @@ -92,6 +92,68 @@ class DigitalOceanDnsApi extends RestApiMap { ); } + Future> getDomains() async { + List domains = []; + + final Dio client = await getClient(); + try { + final Response response = await client.get('/domains'); + domains = response.data['domains']; + } catch (e) { + print(e); + return GenericResult( + data: domains, + success: false, + message: e.toString(), + ); + } finally { + close(client); + } + + return GenericResult(data: domains, success: true); + } + + Future> createMultipleDnsRecords({ + required final ServerDomain domain, + required final List records, + }) async { + final String domainName = domain.domainName; + final List allCreateFutures = []; + + final Dio client = await getClient(); + try { + for (final DnsRecord record in records) { + allCreateFutures.add( + client.post( + '/domains/$domainName/records', + data: { + 'type': record.type, + 'name': record.name, + 'data': record.content, + 'ttl': record.ttl, + 'priority': record.priority, + }, + ), + ); + } + await Future.wait(allCreateFutures); + } on DioError catch (e) { + print(e.message); + rethrow; + } catch (e) { + print(e); + return GenericResult( + success: false, + data: null, + message: e.toString(), + ); + } finally { + close(client); + } + + return GenericResult(success: true, data: null); + } + Future> removeSimilarRecords({ required final ServerDomain domain, required final List records, @@ -152,66 +214,4 @@ class DigitalOceanDnsApi extends RestApiMap { return GenericResult(data: allRecords, success: true); } - - Future> createMultipleDnsRecords({ - required final ServerDomain domain, - required final List records, - }) async { - final String domainName = domain.domainName; - final List allCreateFutures = []; - - final Dio client = await getClient(); - try { - for (final DnsRecord record in records) { - allCreateFutures.add( - client.post( - '/domains/$domainName/records', - data: { - 'type': record.type, - 'name': record.name, - 'data': record.content, - 'ttl': record.ttl, - 'priority': record.priority, - }, - ), - ); - } - await Future.wait(allCreateFutures); - } on DioError catch (e) { - print(e.message); - rethrow; - } catch (e) { - print(e); - return GenericResult( - success: false, - data: null, - message: e.toString(), - ); - } finally { - close(client); - } - - return GenericResult(success: true, data: null); - } - - Future> domainList() async { - List domains = []; - - final Dio client = await getClient(); - try { - final Response response = await client.get('/domains'); - domains = response.data['domains']; - } catch (e) { - print(e); - return GenericResult( - data: domains, - success: false, - message: e.toString(), - ); - } finally { - close(client); - } - - return GenericResult(data: domains, success: true); - } } diff --git a/lib/logic/api_maps/rest_maps/server_providers/digital_ocean/digital_ocean_api.dart b/lib/logic/api_maps/rest_maps/server_providers/digital_ocean/digital_ocean_api.dart index 807d03a0..cebb568c 100644 --- a/lib/logic/api_maps/rest_maps/server_providers/digital_ocean/digital_ocean_api.dart +++ b/lib/logic/api_maps/rest_maps/server_providers/digital_ocean/digital_ocean_api.dart @@ -48,6 +48,100 @@ class DigitalOceanApi extends RestApiMap { String get infectProviderName => 'digitalocean'; String get displayProviderName => 'Digital Ocean'; + Future> getServers() async { + List servers = []; + + final Dio client = await getClient(); + try { + final Response response = await client.get('/droplets'); + servers = response.data['droplets']; + } catch (e) { + print(e); + return GenericResult( + success: false, + data: servers, + message: e.toString(), + ); + } finally { + close(client); + } + + return GenericResult(success: true, data: servers); + } + + Future> createServer({ + required final String dnsApiToken, + required final String dnsProviderType, + required final String serverApiToken, + required final User rootUser, + required final String base64Password, + required final String databasePassword, + required final String domainName, + required final String hostName, + required final String serverType, + }) async { + final String stagingAcme = TlsOptions.stagingAcme ? 'true' : 'false'; + + int? dropletId; + Response? serverCreateResponse; + final Dio client = await getClient(); + try { + final Map data = { + 'name': hostName, + 'size': serverType, + 'image': 'ubuntu-20-04-x64', + 'user_data': '#cloud-config\n' + 'runcmd:\n' + '- curl https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nixos-infect/raw/branch/providers/digital-ocean/nixos-infect | ' + "PROVIDER=$infectProviderName DNS_PROVIDER_TYPE=$dnsProviderType STAGING_ACME='$stagingAcme' DOMAIN='$domainName' " + "LUSER='${rootUser.login}' ENCODED_PASSWORD='$base64Password' CF_TOKEN=$dnsApiToken DB_PASSWORD=$databasePassword " + 'API_TOKEN=$serverApiToken HOSTNAME=$hostName bash 2>&1 | tee /tmp/infect.log', + 'region': region!, + }; + print('Decoded data: $data'); + + serverCreateResponse = await client.post( + '/droplets', + data: data, + ); + dropletId = serverCreateResponse.data['droplet']['id']; + } catch (e) { + print(e); + return GenericResult( + success: false, + data: null, + message: e.toString(), + ); + } finally { + close(client); + } + + return GenericResult( + data: dropletId, + success: true, + code: serverCreateResponse.statusCode, + message: serverCreateResponse.statusMessage, + ); + } + + Future> deleteServer(final int serverId) async { + final Dio client = await getClient(); + try { + await client.delete('/droplets/$serverId'); + } catch (e) { + print(e); + return GenericResult( + success: false, + data: null, + message: e.toString(), + ); + } finally { + close(client); + } + + return GenericResult(success: true, data: null); + } + Future> isApiTokenValid(final String token) async { bool isValid = false; Response? response; @@ -94,41 +188,103 @@ class DigitalOceanApi extends RestApiMap { ); } - Future> createVolume() async { - DigitalOceanVolume? volume; - Response? createVolumeResponse; + Future>> + getAvailableLocations() async { + final List locations = []; + final Dio client = await getClient(); try { - await Future.delayed(const Duration(seconds: 6)); - - createVolumeResponse = await client.post( - '/volumes', - data: { - 'size_gigabytes': 10, - 'name': 'volume${StringGenerators.storageName()}', - 'labels': {'labelkey': 'value'}, - 'region': region, - 'filesystem_type': 'ext4', - }, + final Response response = await client.get( + '/regions', ); - volume = DigitalOceanVolume.fromJson(createVolumeResponse.data['volume']); + + for (final region in response.data!['regions']) { + locations.add(DigitalOceanLocation.fromJson(region)); + } } catch (e) { print(e); return GenericResult( - data: null, + data: [], success: false, message: e.toString(), ); } finally { - client.close(); + close(client); } - return GenericResult( - data: volume, - success: true, - code: createVolumeResponse.statusCode, - message: createVolumeResponse.statusMessage, - ); + return GenericResult(data: locations, success: true); + } + + Future>> + getAvailableServerTypes() async { + final List types = []; + + final Dio client = await getClient(); + try { + final Response response = await client.get( + '/sizes', + ); + for (final size in response.data!['sizes']) { + types.add(DigitalOceanServerType.fromJson(size)); + } + } catch (e) { + print(e); + return GenericResult( + data: [], + success: false, + message: e.toString(), + ); + } finally { + close(client); + } + + return GenericResult(data: types, success: true); + } + + Future> powerOn(final int serverId) async { + final Dio client = await getClient(); + try { + await client.post( + '/droplets/$serverId/actions', + data: { + 'type': 'power_on', + }, + ); + } catch (e) { + print(e); + return GenericResult( + success: false, + data: null, + message: e.toString(), + ); + } finally { + close(client); + } + + return GenericResult(success: true, data: null); + } + + Future> restart(final int serverId) async { + final Dio client = await getClient(); + try { + await client.post( + '/droplets/$serverId/actions', + data: { + 'type': 'reboot', + }, + ); + } catch (e) { + print(e); + return GenericResult( + success: false, + data: null, + message: e.toString(), + ); + } finally { + close(client); + } + + return GenericResult(success: true, data: null); } Future>> getVolumes({ @@ -165,10 +321,24 @@ class DigitalOceanApi extends RestApiMap { ); } - Future> deleteVolume(final String uuid) async { + Future> createVolume() async { + DigitalOceanVolume? volume; + Response? createVolumeResponse; final Dio client = await getClient(); try { - await client.delete('/volumes/$uuid'); + await Future.delayed(const Duration(seconds: 6)); + + createVolumeResponse = await client.post( + '/volumes', + data: { + 'size_gigabytes': 10, + 'name': 'volume${StringGenerators.storageName()}', + 'labels': {'labelkey': 'value'}, + 'region': region, + 'filesystem_type': 'ext4', + }, + ); + volume = DigitalOceanVolume.fromJson(createVolumeResponse.data['volume']); } catch (e) { print(e); return GenericResult( @@ -181,8 +351,10 @@ class DigitalOceanApi extends RestApiMap { } return GenericResult( - data: null, + data: volume, success: true, + code: createVolumeResponse.statusCode, + message: createVolumeResponse.statusMessage, ); } @@ -262,6 +434,27 @@ class DigitalOceanApi extends RestApiMap { ); } + Future> deleteVolume(final String uuid) async { + final Dio client = await getClient(); + try { + await client.delete('/volumes/$uuid'); + } catch (e) { + print(e); + return GenericResult( + data: null, + success: false, + message: e.toString(), + ); + } finally { + client.close(); + } + + return GenericResult( + data: null, + success: true, + ); + } + Future> resizeVolume( final String name, final DiskSize size, @@ -299,125 +492,6 @@ class DigitalOceanApi extends RestApiMap { ); } - Future> createServer({ - required final String dnsApiToken, - required final String dnsProviderType, - required final String serverApiToken, - required final User rootUser, - required final String base64Password, - required final String databasePassword, - required final String domainName, - required final String hostName, - required final String serverType, - }) async { - final String stagingAcme = TlsOptions.stagingAcme ? 'true' : 'false'; - - int? dropletId; - Response? serverCreateResponse; - final Dio client = await getClient(); - try { - final Map data = { - 'name': hostName, - 'size': serverType, - 'image': 'ubuntu-20-04-x64', - 'user_data': '#cloud-config\n' - 'runcmd:\n' - '- curl https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nixos-infect/raw/branch/providers/digital-ocean/nixos-infect | ' - "PROVIDER=$infectProviderName DNS_PROVIDER_TYPE=$dnsProviderType STAGING_ACME='$stagingAcme' DOMAIN='$domainName' " - "LUSER='${rootUser.login}' ENCODED_PASSWORD='$base64Password' CF_TOKEN=$dnsApiToken DB_PASSWORD=$databasePassword " - 'API_TOKEN=$serverApiToken HOSTNAME=$hostName bash 2>&1 | tee /tmp/infect.log', - 'region': region!, - }; - print('Decoded data: $data'); - - serverCreateResponse = await client.post( - '/droplets', - data: data, - ); - dropletId = serverCreateResponse.data['droplet']['id']; - } catch (e) { - print(e); - return GenericResult( - success: false, - data: null, - message: e.toString(), - ); - } finally { - close(client); - } - - return GenericResult( - data: dropletId, - success: true, - code: serverCreateResponse.statusCode, - message: serverCreateResponse.statusMessage, - ); - } - - Future> deleteServer(final int serverId) async { - final Dio client = await getClient(); - try { - await client.delete('/droplets/$serverId'); - } catch (e) { - print(e); - return GenericResult( - success: false, - data: null, - message: e.toString(), - ); - } finally { - close(client); - } - - return GenericResult(success: true, data: null); - } - - Future> restart(final int serverId) async { - final Dio client = await getClient(); - try { - await client.post( - '/droplets/$serverId/actions', - data: { - 'type': 'reboot', - }, - ); - } catch (e) { - print(e); - return GenericResult( - success: false, - data: null, - message: e.toString(), - ); - } finally { - close(client); - } - - return GenericResult(success: true, data: null); - } - - Future> powerOn(final int serverId) async { - final Dio client = await getClient(); - try { - await client.post( - '/droplets/$serverId/actions', - data: { - 'type': 'power_on', - }, - ); - } catch (e) { - print(e); - return GenericResult( - success: false, - data: null, - message: e.toString(), - ); - } finally { - close(client); - } - - return GenericResult(success: true, data: null); - } - Future> getMetricsCpu( final int serverId, final DateTime start, @@ -484,78 +558,4 @@ class DigitalOceanApi extends RestApiMap { return GenericResult(success: true, data: metrics); } - - Future> getServers() async { - List servers = []; - - final Dio client = await getClient(); - try { - final Response response = await client.get('/droplets'); - servers = response.data['droplets']; - } catch (e) { - print(e); - return GenericResult( - success: false, - data: servers, - message: e.toString(), - ); - } finally { - close(client); - } - - return GenericResult(success: true, data: servers); - } - - Future>> - getAvailableLocations() async { - final List locations = []; - - final Dio client = await getClient(); - try { - final Response response = await client.get( - '/regions', - ); - - for (final region in response.data!['regions']) { - locations.add(DigitalOceanLocation.fromJson(region)); - } - } catch (e) { - print(e); - return GenericResult( - data: [], - success: false, - message: e.toString(), - ); - } finally { - close(client); - } - - return GenericResult(data: locations, success: true); - } - - Future>> - getAvailableServerTypes() async { - final List types = []; - - final Dio client = await getClient(); - try { - final Response response = await client.get( - '/sizes', - ); - for (final size in response.data!['sizes']) { - types.add(DigitalOceanServerType.fromJson(size)); - } - } catch (e) { - print(e); - return GenericResult( - data: [], - success: false, - message: e.toString(), - ); - } finally { - close(client); - } - - return GenericResult(data: types, success: true); - } } diff --git a/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner_api.dart b/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner_api.dart index b320d4f5..7fbf3dac 100644 --- a/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner_api.dart +++ b/lib/logic/api_maps/rest_maps/server_providers/hetzner/hetzner_api.dart @@ -48,289 +48,29 @@ class HetznerApi extends RestApiMap { String get infectProviderName => 'hetzner'; String get displayProviderName => 'Hetzner'; - Future> isApiTokenValid(final String token) async { - bool isValid = false; - Response? response; - String message = ''; + Future>> getServers() async { + List servers = []; + final Dio client = await getClient(); try { - response = await client.get( - '/servers', - options: Options( - followRedirects: false, - validateStatus: (final status) => - status != null && (status >= 200 || status == 401), - headers: {'Authorization': 'Bearer $token'}, - ), - ); + final Response response = await client.get('/servers'); + servers = response.data!['servers'] + .map( + (final e) => HetznerServerInfo.fromJson(e), + ) + .toList(); } catch (e) { print(e); - isValid = false; - message = e.toString(); + return GenericResult( + success: false, + data: [], + message: e.toString(), + ); } finally { close(client); } - if (response == null) { - return GenericResult( - data: isValid, - success: false, - message: message, - ); - } - - if (response.statusCode == HttpStatus.ok) { - isValid = true; - } else if (response.statusCode == HttpStatus.unauthorized) { - isValid = false; - } else { - throw Exception('code: ${response.statusCode}'); - } - - return GenericResult( - data: isValid, - success: true, - message: response.statusMessage, - ); - } - - Future> getPricePerGb() async { - double? price; - - final Response pricingResponse; - final Dio client = await getClient(); - try { - pricingResponse = await client.get('/pricing'); - - final volume = pricingResponse.data['pricing']['volume']; - final volumePrice = volume['price_per_gb_month']['gross']; - price = double.parse(volumePrice); - } catch (e) { - print(e); - return GenericResult( - success: false, - data: price, - message: e.toString(), - ); - } finally { - client.close(); - } - - return GenericResult(success: true, data: price); - } - - Future> createVolume() async { - Response? createVolumeResponse; - HetznerVolume? volume; - final Dio client = await getClient(); - try { - createVolumeResponse = await client.post( - '/volumes', - data: { - 'size': 10, - 'name': StringGenerators.storageName(), - 'labels': {'labelkey': 'value'}, - 'location': region, - 'automount': false, - 'format': 'ext4' - }, - ); - volume = HetznerVolume.fromJson(createVolumeResponse.data['volume']); - } catch (e) { - print(e); - return GenericResult( - data: null, - success: false, - message: e.toString(), - ); - } finally { - client.close(); - } - - return GenericResult( - data: volume, - success: true, - code: createVolumeResponse.statusCode, - message: createVolumeResponse.statusMessage, - ); - } - - Future>> getVolumes({ - final String? status, - }) async { - final List volumes = []; - - Response? getVolumesResonse; - final Dio client = await getClient(); - try { - getVolumesResonse = await client.get( - '/volumes', - queryParameters: { - 'status': status, - }, - ); - for (final volume in getVolumesResonse.data['volumes']) { - volumes.add(HetznerVolume.fromJson(volume)); - } - } catch (e) { - print(e); - return GenericResult( - data: [], - success: false, - message: e.toString(), - ); - } finally { - client.close(); - } - - return GenericResult( - data: volumes, - success: true, - code: getVolumesResonse.statusCode, - message: getVolumesResonse.statusMessage, - ); - } - - Future> getVolume( - final String volumeId, - ) async { - HetznerVolume? volume; - - final Response getVolumeResponse; - final Dio client = await getClient(); - try { - getVolumeResponse = await client.get('/volumes/$volumeId'); - volume = HetznerVolume.fromJson(getVolumeResponse.data['volume']); - } catch (e) { - print(e); - return GenericResult( - data: null, - success: false, - message: e.toString(), - ); - } finally { - client.close(); - } - - return GenericResult( - data: volume, - success: true, - ); - } - - Future> deleteVolume(final int volumeId) async { - final Dio client = await getClient(); - try { - await client.delete('/volumes/$volumeId'); - } catch (e) { - print(e); - return GenericResult( - success: false, - data: false, - message: e.toString(), - ); - } finally { - client.close(); - } - - return GenericResult( - success: true, - data: true, - ); - } - - Future> attachVolume( - final HetznerVolume volume, - final int serverId, - ) async { - bool success = false; - - Response? attachVolumeResponse; - final Dio client = await getClient(); - try { - attachVolumeResponse = await client.post( - '/volumes/${volume.id}/actions/attach', - data: { - 'automount': true, - 'server': serverId, - }, - ); - success = - attachVolumeResponse.data['action']['status'].toString() != 'error'; - } catch (e) { - print(e); - } finally { - client.close(); - } - - return GenericResult( - data: success, - success: true, - code: attachVolumeResponse?.statusCode, - message: attachVolumeResponse?.statusMessage, - ); - } - - Future> detachVolume(final int volumeId) async { - bool success = false; - - final Response detachVolumeResponse; - final Dio client = await getClient(); - try { - detachVolumeResponse = await client.post( - '/volumes/$volumeId/actions/detach', - ); - success = - detachVolumeResponse.data['action']['status'].toString() != 'error'; - } catch (e) { - print(e); - return GenericResult( - success: false, - data: false, - message: e.toString(), - ); - } finally { - client.close(); - } - - return GenericResult( - success: false, - data: success, - ); - } - - Future> resizeVolume( - final HetznerVolume volume, - final DiskSize size, - ) async { - bool success = false; - - final Response resizeVolumeResponse; - final Dio client = await getClient(); - try { - resizeVolumeResponse = await client.post( - '/volumes/${volume.id}/actions/resize', - data: { - 'size': size.gibibyte, - }, - ); - success = - resizeVolumeResponse.data['action']['status'].toString() != 'error'; - } catch (e) { - print(e); - return GenericResult( - data: false, - success: false, - message: e.toString(), - ); - } finally { - client.close(); - } - - return GenericResult( - data: success, - success: true, - ); + return GenericResult(data: servers, success: true); } Future> createServer({ @@ -402,6 +142,34 @@ class HetznerApi extends RestApiMap { ); } + Future> createReverseDns({ + required final int serverId, + required final String ip4, + required final String dnsPtr, + }) async { + final Dio client = await getClient(); + try { + await client.post( + '/servers/$serverId/actions/change_dns_ptr', + data: { + 'ip': ip4, + 'dns_ptr': dnsPtr, + }, + ); + } catch (e) { + print(e); + return GenericResult( + success: false, + data: null, + message: e.toString(), + ); + } finally { + close(client); + } + + return GenericResult(success: true, data: null); + } + Future> deleteServer({ required final int serverId, }) async { @@ -422,98 +190,50 @@ class HetznerApi extends RestApiMap { return GenericResult(success: true, data: null); } - Future> restart(final int serverId) async { + Future> isApiTokenValid(final String token) async { + bool isValid = false; + Response? response; + String message = ''; final Dio client = await getClient(); try { - await client.post('/servers/$serverId/actions/reset'); + response = await client.get( + '/servers', + options: Options( + followRedirects: false, + validateStatus: (final status) => + status != null && (status >= 200 || status == 401), + headers: {'Authorization': 'Bearer $token'}, + ), + ); } catch (e) { print(e); - return GenericResult( - success: false, - data: null, - message: e.toString(), - ); + isValid = false; + message = e.toString(); } finally { close(client); } - return GenericResult(success: true, data: null); - } - - Future> powerOn(final int serverId) async { - final Dio client = await getClient(); - try { - await client.post('/servers/$serverId/actions/poweron'); - } catch (e) { - print(e); + if (response == null) { return GenericResult( + data: isValid, success: false, - data: null, - message: e.toString(), + message: message, ); - } finally { - close(client); } - return GenericResult(success: true, data: null); - } - - Future>> getMetrics( - final int serverId, - final DateTime start, - final DateTime end, - final String type, - ) async { - Map metrics = {}; - final Dio client = await getClient(); - try { - final Map queryParameters = { - 'start': start.toUtc().toIso8601String(), - 'end': end.toUtc().toIso8601String(), - 'type': type - }; - final Response res = await client.get( - '/servers/$serverId/metrics', - queryParameters: queryParameters, - ); - metrics = res.data['metrics']; - } catch (e) { - print(e); - return GenericResult( - success: false, - data: {}, - message: e.toString(), - ); - } finally { - close(client); + if (response.statusCode == HttpStatus.ok) { + isValid = true; + } else if (response.statusCode == HttpStatus.unauthorized) { + isValid = false; + } else { + throw Exception('code: ${response.statusCode}'); } - return GenericResult(data: metrics, success: true); - } - - Future>> getServers() async { - List servers = []; - - final Dio client = await getClient(); - try { - final Response response = await client.get('/servers'); - servers = response.data!['servers'] - .map( - (final e) => HetznerServerInfo.fromJson(e), - ) - .toList(); - } catch (e) { - print(e); - return GenericResult( - success: false, - data: [], - message: e.toString(), - ); - } finally { - close(client); - } - - return GenericResult(data: servers, success: true); + return GenericResult( + data: isValid, + success: true, + message: response.statusMessage, + ); } Future>> getAvailableLocations() async { @@ -565,20 +285,10 @@ class HetznerApi extends RestApiMap { return GenericResult(data: types, success: true); } - Future> createReverseDns({ - required final int serverId, - required final String ip4, - required final String dnsPtr, - }) async { + Future> powerOn(final int serverId) async { final Dio client = await getClient(); try { - await client.post( - '/servers/$serverId/actions/change_dns_ptr', - data: { - 'ip': ip4, - 'dns_ptr': dnsPtr, - }, - ); + await client.post('/servers/$serverId/actions/poweron'); } catch (e) { print(e); return GenericResult( @@ -592,4 +302,294 @@ class HetznerApi extends RestApiMap { return GenericResult(success: true, data: null); } + + Future> restart(final int serverId) async { + final Dio client = await getClient(); + try { + await client.post('/servers/$serverId/actions/reset'); + } catch (e) { + print(e); + return GenericResult( + success: false, + data: null, + message: e.toString(), + ); + } finally { + close(client); + } + + return GenericResult(success: true, data: null); + } + + Future> getPricePerGb() async { + double? price; + + final Response pricingResponse; + final Dio client = await getClient(); + try { + pricingResponse = await client.get('/pricing'); + + final volume = pricingResponse.data['pricing']['volume']; + final volumePrice = volume['price_per_gb_month']['gross']; + price = double.parse(volumePrice); + } catch (e) { + print(e); + return GenericResult( + success: false, + data: price, + message: e.toString(), + ); + } finally { + client.close(); + } + + return GenericResult(success: true, data: price); + } + + Future>> getVolumes({ + final String? status, + }) async { + final List volumes = []; + + Response? getVolumesResonse; + final Dio client = await getClient(); + try { + getVolumesResonse = await client.get( + '/volumes', + queryParameters: { + 'status': status, + }, + ); + for (final volume in getVolumesResonse.data['volumes']) { + volumes.add(HetznerVolume.fromJson(volume)); + } + } catch (e) { + print(e); + return GenericResult( + data: [], + success: false, + message: e.toString(), + ); + } finally { + client.close(); + } + + return GenericResult( + data: volumes, + success: true, + code: getVolumesResonse.statusCode, + message: getVolumesResonse.statusMessage, + ); + } + + Future> createVolume() async { + Response? createVolumeResponse; + HetznerVolume? volume; + final Dio client = await getClient(); + try { + createVolumeResponse = await client.post( + '/volumes', + data: { + 'size': 10, + 'name': StringGenerators.storageName(), + 'labels': {'labelkey': 'value'}, + 'location': region, + 'automount': false, + 'format': 'ext4' + }, + ); + volume = HetznerVolume.fromJson(createVolumeResponse.data['volume']); + } catch (e) { + print(e); + return GenericResult( + data: null, + success: false, + message: e.toString(), + ); + } finally { + client.close(); + } + + return GenericResult( + data: volume, + success: true, + code: createVolumeResponse.statusCode, + message: createVolumeResponse.statusMessage, + ); + } + + Future> deleteVolume(final int volumeId) async { + final Dio client = await getClient(); + try { + await client.delete('/volumes/$volumeId'); + } catch (e) { + print(e); + return GenericResult( + success: false, + data: false, + message: e.toString(), + ); + } finally { + client.close(); + } + + return GenericResult( + success: true, + data: true, + ); + } + + Future> getVolume( + final String volumeId, + ) async { + HetznerVolume? volume; + + final Response getVolumeResponse; + final Dio client = await getClient(); + try { + getVolumeResponse = await client.get('/volumes/$volumeId'); + volume = HetznerVolume.fromJson(getVolumeResponse.data['volume']); + } catch (e) { + print(e); + return GenericResult( + data: null, + success: false, + message: e.toString(), + ); + } finally { + client.close(); + } + + return GenericResult( + data: volume, + success: true, + ); + } + + Future> detachVolume(final int volumeId) async { + bool success = false; + + final Response detachVolumeResponse; + final Dio client = await getClient(); + try { + detachVolumeResponse = await client.post( + '/volumes/$volumeId/actions/detach', + ); + success = + detachVolumeResponse.data['action']['status'].toString() != 'error'; + } catch (e) { + print(e); + return GenericResult( + success: false, + data: false, + message: e.toString(), + ); + } finally { + client.close(); + } + + return GenericResult( + success: false, + data: success, + ); + } + + Future> attachVolume( + final HetznerVolume volume, + final int serverId, + ) async { + bool success = false; + + Response? attachVolumeResponse; + final Dio client = await getClient(); + try { + attachVolumeResponse = await client.post( + '/volumes/${volume.id}/actions/attach', + data: { + 'automount': true, + 'server': serverId, + }, + ); + success = + attachVolumeResponse.data['action']['status'].toString() != 'error'; + } catch (e) { + print(e); + } finally { + client.close(); + } + + return GenericResult( + data: success, + success: true, + code: attachVolumeResponse?.statusCode, + message: attachVolumeResponse?.statusMessage, + ); + } + + Future> resizeVolume( + final HetznerVolume volume, + final DiskSize size, + ) async { + bool success = false; + + final Response resizeVolumeResponse; + final Dio client = await getClient(); + try { + resizeVolumeResponse = await client.post( + '/volumes/${volume.id}/actions/resize', + data: { + 'size': size.gibibyte, + }, + ); + success = + resizeVolumeResponse.data['action']['status'].toString() != 'error'; + } catch (e) { + print(e); + return GenericResult( + data: false, + success: false, + message: e.toString(), + ); + } finally { + client.close(); + } + + return GenericResult( + data: success, + success: true, + ); + } + + Future>> getMetrics( + final int serverId, + final DateTime start, + final DateTime end, + final String type, + ) async { + Map metrics = {}; + final Dio client = await getClient(); + try { + final Map queryParameters = { + 'start': start.toUtc().toIso8601String(), + 'end': end.toUtc().toIso8601String(), + 'type': type + }; + final Response res = await client.get( + '/servers/$serverId/metrics', + queryParameters: queryParameters, + ); + metrics = res.data['metrics']; + } catch (e) { + print(e); + return GenericResult( + success: false, + data: {}, + message: e.toString(), + ); + } finally { + close(client); + } + + return GenericResult(data: metrics, success: true); + } } diff --git a/lib/logic/providers/dns_providers/desec.dart b/lib/logic/providers/dns_providers/desec.dart index acf384c6..41d504e4 100644 --- a/lib/logic/providers/dns_providers/desec.dart +++ b/lib/logic/providers/dns_providers/desec.dart @@ -91,7 +91,7 @@ class DesecDnsProvider extends DnsProvider { ); } - return _adapter.api().createRecords( + return _adapter.api().createMultipleDnsRecords( domain: domain, records: bulkRecords, ); @@ -127,7 +127,7 @@ class DesecDnsProvider extends DnsProvider { }, ); - return _adapter.api().updateRecords( + return _adapter.api().removeSimilarRecords( domain: domain, records: bulkRecords, ); @@ -179,7 +179,7 @@ class DesecDnsProvider extends DnsProvider { final DnsRecord record, final ServerDomain domain, ) async { - final result = await _adapter.api().createRecords( + final result = await _adapter.api().createMultipleDnsRecords( domain: domain, records: [ { diff --git a/lib/logic/providers/dns_providers/digital_ocean_dns.dart b/lib/logic/providers/dns_providers/digital_ocean_dns.dart index 17e1a085..87f8a479 100644 --- a/lib/logic/providers/dns_providers/digital_ocean_dns.dart +++ b/lib/logic/providers/dns_providers/digital_ocean_dns.dart @@ -47,7 +47,7 @@ class DigitalOceanDnsProvider extends DnsProvider { @override Future>> domainList() async { List domains = []; - final result = await _adapter.api().domainList(); + final result = await _adapter.api().getDomains(); if (result.data.isEmpty || !result.success) { return GenericResult( success: result.success,