mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-11 18:39:45 +00:00
refactor(rest-api): Move rest api methods according to their business logic files positions
- Rename unmatching functions
This commit is contained in:
parent
5af30bce4d
commit
7ff1e36161
|
@ -92,22 +92,23 @@ class CloudflareApi extends RestApiMap {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<List<dynamic>>> getZones(final String domain) async {
|
Future<GenericResult<List>> getDomains() async {
|
||||||
List zones = [];
|
final String url = '$rootAddress/zones';
|
||||||
|
List domains = [];
|
||||||
|
|
||||||
late final Response? response;
|
late final Response? response;
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
response = await client.get(
|
response = await client.get(
|
||||||
'/zones',
|
url,
|
||||||
queryParameters: {'name': domain},
|
queryParameters: {'per_page': 50},
|
||||||
);
|
);
|
||||||
zones = response.data['result'];
|
domains = response.data['result'];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
GenericResult(
|
return GenericResult(
|
||||||
success: false,
|
success: false,
|
||||||
data: zones,
|
data: domains,
|
||||||
code: response?.statusCode,
|
code: response?.statusCode,
|
||||||
message: response?.statusMessage,
|
message: response?.statusMessage,
|
||||||
);
|
);
|
||||||
|
@ -115,7 +116,47 @@ class CloudflareApi extends RestApiMap {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GenericResult(success: true, data: zones);
|
return GenericResult(
|
||||||
|
success: true,
|
||||||
|
data: domains,
|
||||||
|
code: response.statusCode,
|
||||||
|
message: response.statusMessage,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<GenericResult<void>> createMultipleDnsRecords({
|
||||||
|
required final ServerDomain domain,
|
||||||
|
required final List<DnsRecord> records,
|
||||||
|
}) async {
|
||||||
|
final String domainZoneId = domain.zoneId;
|
||||||
|
final List<Future> allCreateFutures = <Future>[];
|
||||||
|
|
||||||
|
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<GenericResult<void>> removeSimilarRecords({
|
Future<GenericResult<void>> removeSimilarRecords({
|
||||||
|
@ -183,58 +224,22 @@ class CloudflareApi extends RestApiMap {
|
||||||
return GenericResult(data: allRecords, success: true);
|
return GenericResult(data: allRecords, success: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<void>> createMultipleDnsRecords({
|
Future<GenericResult<List<dynamic>>> getZones(final String domain) async {
|
||||||
required final ServerDomain domain,
|
List zones = [];
|
||||||
required final List<DnsRecord> records,
|
|
||||||
}) async {
|
|
||||||
final String domainZoneId = domain.zoneId;
|
|
||||||
final List<Future> allCreateFutures = <Future>[];
|
|
||||||
|
|
||||||
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<GenericResult<List>> getDomains() async {
|
|
||||||
final String url = '$rootAddress/zones';
|
|
||||||
List domains = [];
|
|
||||||
|
|
||||||
late final Response? response;
|
late final Response? response;
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
response = await client.get(
|
response = await client.get(
|
||||||
url,
|
'/zones',
|
||||||
queryParameters: {'per_page': 50},
|
queryParameters: {'name': domain},
|
||||||
);
|
);
|
||||||
domains = response.data['result'];
|
zones = response.data['result'];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericResult(
|
GenericResult(
|
||||||
success: false,
|
success: false,
|
||||||
data: domains,
|
data: zones,
|
||||||
code: response?.statusCode,
|
code: response?.statusCode,
|
||||||
message: response?.statusMessage,
|
message: response?.statusMessage,
|
||||||
);
|
);
|
||||||
|
@ -242,11 +247,6 @@ class CloudflareApi extends RestApiMap {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GenericResult(
|
return GenericResult(success: true, data: zones);
|
||||||
success: true,
|
|
||||||
data: domains,
|
|
||||||
code: response.statusCode,
|
|
||||||
message: response.statusMessage,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,63 @@ class DesecApi extends RestApiMap {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<void>> updateRecords({
|
Future<GenericResult<List>> 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<GenericResult<void>> createMultipleDnsRecords({
|
||||||
|
required final ServerDomain domain,
|
||||||
|
required final List<dynamic> 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<GenericResult<void>> removeSimilarRecords({
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
required final List<dynamic> records,
|
required final List<dynamic> records,
|
||||||
}) async {
|
}) async {
|
||||||
|
@ -145,60 +201,4 @@ class DesecApi extends RestApiMap {
|
||||||
|
|
||||||
return GenericResult(data: allRecords, success: true);
|
return GenericResult(data: allRecords, success: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<void>> createRecords({
|
|
||||||
required final ServerDomain domain,
|
|
||||||
required final List<dynamic> 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<GenericResult<List>> 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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,68 @@ class DigitalOceanDnsApi extends RestApiMap {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<GenericResult<List>> 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<GenericResult<void>> createMultipleDnsRecords({
|
||||||
|
required final ServerDomain domain,
|
||||||
|
required final List<DnsRecord> records,
|
||||||
|
}) async {
|
||||||
|
final String domainName = domain.domainName;
|
||||||
|
final List<Future> allCreateFutures = <Future>[];
|
||||||
|
|
||||||
|
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<GenericResult<void>> removeSimilarRecords({
|
Future<GenericResult<void>> removeSimilarRecords({
|
||||||
required final ServerDomain domain,
|
required final ServerDomain domain,
|
||||||
required final List records,
|
required final List records,
|
||||||
|
@ -152,66 +214,4 @@ class DigitalOceanDnsApi extends RestApiMap {
|
||||||
|
|
||||||
return GenericResult(data: allRecords, success: true);
|
return GenericResult(data: allRecords, success: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<void>> createMultipleDnsRecords({
|
|
||||||
required final ServerDomain domain,
|
|
||||||
required final List<DnsRecord> records,
|
|
||||||
}) async {
|
|
||||||
final String domainName = domain.domainName;
|
|
||||||
final List<Future> allCreateFutures = <Future>[];
|
|
||||||
|
|
||||||
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<GenericResult<List>> 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,100 @@ class DigitalOceanApi extends RestApiMap {
|
||||||
String get infectProviderName => 'digitalocean';
|
String get infectProviderName => 'digitalocean';
|
||||||
String get displayProviderName => 'Digital Ocean';
|
String get displayProviderName => 'Digital Ocean';
|
||||||
|
|
||||||
|
Future<GenericResult<List>> 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<GenericResult<int?>> 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<String, Object> 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<GenericResult<void>> 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<GenericResult<bool>> isApiTokenValid(final String token) async {
|
Future<GenericResult<bool>> isApiTokenValid(final String token) async {
|
||||||
bool isValid = false;
|
bool isValid = false;
|
||||||
Response? response;
|
Response? response;
|
||||||
|
@ -94,41 +188,103 @@ class DigitalOceanApi extends RestApiMap {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<DigitalOceanVolume?>> createVolume() async {
|
Future<GenericResult<List<DigitalOceanLocation>>>
|
||||||
DigitalOceanVolume? volume;
|
getAvailableLocations() async {
|
||||||
Response? createVolumeResponse;
|
final List<DigitalOceanLocation> locations = [];
|
||||||
|
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
await Future.delayed(const Duration(seconds: 6));
|
final Response response = await client.get(
|
||||||
|
'/regions',
|
||||||
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']);
|
|
||||||
|
for (final region in response.data!['regions']) {
|
||||||
|
locations.add(DigitalOceanLocation.fromJson(region));
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericResult(
|
return GenericResult(
|
||||||
data: null,
|
data: [],
|
||||||
success: false,
|
success: false,
|
||||||
message: e.toString(),
|
message: e.toString(),
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
client.close();
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GenericResult(
|
return GenericResult(data: locations, success: true);
|
||||||
data: volume,
|
}
|
||||||
success: true,
|
|
||||||
code: createVolumeResponse.statusCode,
|
Future<GenericResult<List<DigitalOceanServerType>>>
|
||||||
message: createVolumeResponse.statusMessage,
|
getAvailableServerTypes() async {
|
||||||
);
|
final List<DigitalOceanServerType> 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<GenericResult<void>> 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<GenericResult<void>> 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<GenericResult<List<DigitalOceanVolume>>> getVolumes({
|
Future<GenericResult<List<DigitalOceanVolume>>> getVolumes({
|
||||||
|
@ -165,10 +321,24 @@ class DigitalOceanApi extends RestApiMap {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<void>> deleteVolume(final String uuid) async {
|
Future<GenericResult<DigitalOceanVolume?>> createVolume() async {
|
||||||
|
DigitalOceanVolume? volume;
|
||||||
|
Response? createVolumeResponse;
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
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) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericResult(
|
return GenericResult(
|
||||||
|
@ -181,8 +351,10 @@ class DigitalOceanApi extends RestApiMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
return GenericResult(
|
return GenericResult(
|
||||||
data: null,
|
data: volume,
|
||||||
success: true,
|
success: true,
|
||||||
|
code: createVolumeResponse.statusCode,
|
||||||
|
message: createVolumeResponse.statusMessage,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,6 +434,27 @@ class DigitalOceanApi extends RestApiMap {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<GenericResult<void>> 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<GenericResult<bool>> resizeVolume(
|
Future<GenericResult<bool>> resizeVolume(
|
||||||
final String name,
|
final String name,
|
||||||
final DiskSize size,
|
final DiskSize size,
|
||||||
|
@ -299,125 +492,6 @@ class DigitalOceanApi extends RestApiMap {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<int?>> 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<String, Object> 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<GenericResult<void>> 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<GenericResult<void>> 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<GenericResult<void>> 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<GenericResult<List>> getMetricsCpu(
|
Future<GenericResult<List>> getMetricsCpu(
|
||||||
final int serverId,
|
final int serverId,
|
||||||
final DateTime start,
|
final DateTime start,
|
||||||
|
@ -484,78 +558,4 @@ class DigitalOceanApi extends RestApiMap {
|
||||||
|
|
||||||
return GenericResult(success: true, data: metrics);
|
return GenericResult(success: true, data: metrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<List>> 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<GenericResult<List<DigitalOceanLocation>>>
|
|
||||||
getAvailableLocations() async {
|
|
||||||
final List<DigitalOceanLocation> 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<GenericResult<List<DigitalOceanServerType>>>
|
|
||||||
getAvailableServerTypes() async {
|
|
||||||
final List<DigitalOceanServerType> 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,289 +48,29 @@ class HetznerApi extends RestApiMap {
|
||||||
String get infectProviderName => 'hetzner';
|
String get infectProviderName => 'hetzner';
|
||||||
String get displayProviderName => 'Hetzner';
|
String get displayProviderName => 'Hetzner';
|
||||||
|
|
||||||
Future<GenericResult<bool>> isApiTokenValid(final String token) async {
|
Future<GenericResult<List<HetznerServerInfo>>> getServers() async {
|
||||||
bool isValid = false;
|
List<HetznerServerInfo> servers = [];
|
||||||
Response? response;
|
|
||||||
String message = '';
|
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
response = await client.get(
|
final Response response = await client.get('/servers');
|
||||||
'/servers',
|
servers = response.data!['servers']
|
||||||
options: Options(
|
.map<HetznerServerInfo>(
|
||||||
followRedirects: false,
|
(final e) => HetznerServerInfo.fromJson(e),
|
||||||
validateStatus: (final status) =>
|
)
|
||||||
status != null && (status >= 200 || status == 401),
|
.toList();
|
||||||
headers: {'Authorization': 'Bearer $token'},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
isValid = false;
|
return GenericResult(
|
||||||
message = e.toString();
|
success: false,
|
||||||
|
data: [],
|
||||||
|
message: e.toString(),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response == null) {
|
return GenericResult(data: servers, success: true);
|
||||||
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<GenericResult<double?>> 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<GenericResult<HetznerVolume?>> 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<GenericResult<List<HetznerVolume>>> getVolumes({
|
|
||||||
final String? status,
|
|
||||||
}) async {
|
|
||||||
final List<HetznerVolume> 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<GenericResult<HetznerVolume?>> 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<GenericResult<bool>> 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<GenericResult<bool>> 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<GenericResult<bool>> 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<GenericResult<bool>> 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<GenericResult<HetznerServerInfo?>> createServer({
|
Future<GenericResult<HetznerServerInfo?>> createServer({
|
||||||
|
@ -402,6 +142,34 @@ class HetznerApi extends RestApiMap {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<GenericResult<void>> 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<GenericResult<void>> deleteServer({
|
Future<GenericResult<void>> deleteServer({
|
||||||
required final int serverId,
|
required final int serverId,
|
||||||
}) async {
|
}) async {
|
||||||
|
@ -422,98 +190,50 @@ class HetznerApi extends RestApiMap {
|
||||||
return GenericResult(success: true, data: null);
|
return GenericResult(success: true, data: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<void>> restart(final int serverId) async {
|
Future<GenericResult<bool>> isApiTokenValid(final String token) async {
|
||||||
|
bool isValid = false;
|
||||||
|
Response? response;
|
||||||
|
String message = '';
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
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) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericResult(
|
isValid = false;
|
||||||
success: false,
|
message = e.toString();
|
||||||
data: null,
|
|
||||||
message: e.toString(),
|
|
||||||
);
|
|
||||||
} finally {
|
} finally {
|
||||||
close(client);
|
close(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GenericResult(success: true, data: null);
|
if (response == null) {
|
||||||
}
|
|
||||||
|
|
||||||
Future<GenericResult<void>> powerOn(final int serverId) async {
|
|
||||||
final Dio client = await getClient();
|
|
||||||
try {
|
|
||||||
await client.post('/servers/$serverId/actions/poweron');
|
|
||||||
} catch (e) {
|
|
||||||
print(e);
|
|
||||||
return GenericResult(
|
return GenericResult(
|
||||||
|
data: isValid,
|
||||||
success: false,
|
success: false,
|
||||||
data: null,
|
message: message,
|
||||||
message: e.toString(),
|
|
||||||
);
|
);
|
||||||
} finally {
|
|
||||||
close(client);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GenericResult(success: true, data: null);
|
if (response.statusCode == HttpStatus.ok) {
|
||||||
}
|
isValid = true;
|
||||||
|
} else if (response.statusCode == HttpStatus.unauthorized) {
|
||||||
Future<GenericResult<Map<String, dynamic>>> getMetrics(
|
isValid = false;
|
||||||
final int serverId,
|
} else {
|
||||||
final DateTime start,
|
throw Exception('code: ${response.statusCode}');
|
||||||
final DateTime end,
|
|
||||||
final String type,
|
|
||||||
) async {
|
|
||||||
Map<String, dynamic> metrics = {};
|
|
||||||
final Dio client = await getClient();
|
|
||||||
try {
|
|
||||||
final Map<String, dynamic> 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);
|
return GenericResult(
|
||||||
}
|
data: isValid,
|
||||||
|
success: true,
|
||||||
Future<GenericResult<List<HetznerServerInfo>>> getServers() async {
|
message: response.statusMessage,
|
||||||
List<HetznerServerInfo> servers = [];
|
);
|
||||||
|
|
||||||
final Dio client = await getClient();
|
|
||||||
try {
|
|
||||||
final Response response = await client.get('/servers');
|
|
||||||
servers = response.data!['servers']
|
|
||||||
.map<HetznerServerInfo>(
|
|
||||||
(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<List<HetznerLocation>>> getAvailableLocations() async {
|
Future<GenericResult<List<HetznerLocation>>> getAvailableLocations() async {
|
||||||
|
@ -565,20 +285,10 @@ class HetznerApi extends RestApiMap {
|
||||||
return GenericResult(data: types, success: true);
|
return GenericResult(data: types, success: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GenericResult<void>> createReverseDns({
|
Future<GenericResult<void>> powerOn(final int serverId) async {
|
||||||
required final int serverId,
|
|
||||||
required final String ip4,
|
|
||||||
required final String dnsPtr,
|
|
||||||
}) async {
|
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
try {
|
try {
|
||||||
await client.post(
|
await client.post('/servers/$serverId/actions/poweron');
|
||||||
'/servers/$serverId/actions/change_dns_ptr',
|
|
||||||
data: {
|
|
||||||
'ip': ip4,
|
|
||||||
'dns_ptr': dnsPtr,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
return GenericResult(
|
return GenericResult(
|
||||||
|
@ -592,4 +302,294 @@ class HetznerApi extends RestApiMap {
|
||||||
|
|
||||||
return GenericResult(success: true, data: null);
|
return GenericResult(success: true, data: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<GenericResult<void>> 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<GenericResult<double?>> 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<GenericResult<List<HetznerVolume>>> getVolumes({
|
||||||
|
final String? status,
|
||||||
|
}) async {
|
||||||
|
final List<HetznerVolume> 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<GenericResult<HetznerVolume?>> 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<GenericResult<bool>> 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<GenericResult<HetznerVolume?>> 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<GenericResult<bool>> 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<GenericResult<bool>> 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<GenericResult<bool>> 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<GenericResult<Map<String, dynamic>>> getMetrics(
|
||||||
|
final int serverId,
|
||||||
|
final DateTime start,
|
||||||
|
final DateTime end,
|
||||||
|
final String type,
|
||||||
|
) async {
|
||||||
|
Map<String, dynamic> metrics = {};
|
||||||
|
final Dio client = await getClient();
|
||||||
|
try {
|
||||||
|
final Map<String, dynamic> 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ class DesecDnsProvider extends DnsProvider {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _adapter.api().createRecords(
|
return _adapter.api().createMultipleDnsRecords(
|
||||||
domain: domain,
|
domain: domain,
|
||||||
records: bulkRecords,
|
records: bulkRecords,
|
||||||
);
|
);
|
||||||
|
@ -127,7 +127,7 @@ class DesecDnsProvider extends DnsProvider {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return _adapter.api().updateRecords(
|
return _adapter.api().removeSimilarRecords(
|
||||||
domain: domain,
|
domain: domain,
|
||||||
records: bulkRecords,
|
records: bulkRecords,
|
||||||
);
|
);
|
||||||
|
@ -179,7 +179,7 @@ class DesecDnsProvider extends DnsProvider {
|
||||||
final DnsRecord record,
|
final DnsRecord record,
|
||||||
final ServerDomain domain,
|
final ServerDomain domain,
|
||||||
) async {
|
) async {
|
||||||
final result = await _adapter.api().createRecords(
|
final result = await _adapter.api().createMultipleDnsRecords(
|
||||||
domain: domain,
|
domain: domain,
|
||||||
records: [
|
records: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,7 +47,7 @@ class DigitalOceanDnsProvider extends DnsProvider {
|
||||||
@override
|
@override
|
||||||
Future<GenericResult<List<String>>> domainList() async {
|
Future<GenericResult<List<String>>> domainList() async {
|
||||||
List<String> domains = [];
|
List<String> domains = [];
|
||||||
final result = await _adapter.api().domainList();
|
final result = await _adapter.api().getDomains();
|
||||||
if (result.data.isEmpty || !result.success) {
|
if (result.data.isEmpty || !result.success) {
|
||||||
return GenericResult(
|
return GenericResult(
|
||||||
success: result.success,
|
success: result.success,
|
||||||
|
|
Loading…
Reference in a new issue