forked from SelfPrivacy/selfprivacy.org.app
Compare commits
No commits in common. "graphql" and "master" have entirely different histories.
|
@ -13,7 +13,6 @@ analyzer:
|
|||
exclude:
|
||||
- lib/generated_plugin_registrant.dart
|
||||
- lib/**.g.dart
|
||||
- lib/**.graphql.dart
|
||||
|
||||
linter:
|
||||
# The lint rules applied to this project can be customized in the
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 22 KiB |
Binary file not shown.
Before Width: | Height: | Size: 11 KiB |
|
@ -1,14 +1,11 @@
|
|||
### Как получить Cloudflare API Token
|
||||
1. Переходим по [ссылке](https://dash.cloudflare.com/) и авторизуемся в ранее созданном аккаунте. https://dash.cloudflare.com/
|
||||
2. В правом верхнем углу кликаем на иконку профиля (для мобильной версии сайта: в верхнем левом углу нажимаем кнопку **Меню** с тремя горизонтальными полосками). В выпавшем меню кликаем на пункт **My Profile**.
|
||||
![My profile](resource:assets/images/pics/myprofile.png)
|
||||
В правом углу кликаем на иконку профиля (человечек в кружочке). Для мобильной версии сайта, в верхнем левом углу, нажимаем кнопку **Меню** (три горизонтальных полоски), в выпавшем меню, ищем пункт **My Profile**.
|
||||
3. Нам предлагается на выбор, четыре категории настройки: **Preferences**, **Authentication**, **API Tokens**, **Sessions**. Выбираем **API Tokens**.
|
||||
4. Самым первым пунктом видим кнопку **Create Token**. С полной уверенностью в себе и желанием обрести приватность, нажимаем на неё.
|
||||
5. Спускаемся в самый низ и видим поле **Create Custom Token** и кнопку **Get Started** с правой стороны. Нажимаем.
|
||||
6. В поле **Token Name** даём своему токену имя. Можете покреативить и отнестись к этому как к наименованию домашнего зверька :)
|
||||
7. Далее, у нас **Permissions**. В первом поле выбираем **Zone**. Во втором поле, по центру, выбираем **DNS**. В последнем поле выбираем **Edit**.
|
||||
8. Нажимаем на синюю надпись снизу **+ Add more** (сразу же под левым полем которое мы заполняли ранее). Вуаля, у нас появились новые поля. Заполняем по аналогии с предыдущим пунктом, в первом поле выбираем **Zone**, во-втором тоже **Zone**. А уже в третьем нажимаем на **Read**. Давайте сверим с тем, что у вас получилось:
|
||||
![Permissions](resource:assets/images/pics/permissions.png)
|
||||
7. Далее, у нас **Permissions**. В первом поле выбираем Zone. Во втором поле, по центру, выбираем **DNS**. В последнем поле выбираем **Edit**.
|
||||
8. Далее смотрим на **Zone Resources**. Под этой надписью есть строка с двумя полями. В первом должно быть **Include**, а во втором — **Specific Zone**. Как только Вы выберите **Specific Zone**, справа появится ещё одно поле. В нём выбираем наш домен.
|
||||
9. Листаем в самый низ и нажимаем на синюю кнопку **Continue to Summary**.
|
||||
10. Проверяем, всё ли мы правильно выбрали. Должна присутствовать подобная строка: ваш.домен — **DNS:Edit, Zone:Read**.
|
||||
|
|
|
@ -52,8 +52,7 @@
|
|||
"copied_ssh": "SSH copied to clipboard",
|
||||
"delete_ssh_text": "Delete SSH key?",
|
||||
"about_app_page": {
|
||||
"application_version_text": "Application version v.{}",
|
||||
"api_version_text": "Server API version v.{}"
|
||||
"text": "Application version v.{}"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Application settings",
|
||||
|
@ -163,24 +162,6 @@
|
|||
"refresh": "Refresh status",
|
||||
"refetchBackups": "Refetch backup list",
|
||||
"refetchingList": "In a few minutes list will be updated"
|
||||
},
|
||||
"storage": {
|
||||
"card_title": "Server Storage",
|
||||
"status_ok": "Disk usage is OK",
|
||||
"status_error": "Low disk space",
|
||||
"disk_usage": "{} GB used",
|
||||
"disk_total": "{} GB total · {}",
|
||||
"gb": "{} GB",
|
||||
"mb": "{} MB",
|
||||
"extend_volume_button": "Extend volume",
|
||||
"extending_volume_title": "Extending volume",
|
||||
"extending_volume_description": "Resizing volume will allow you to store more data on your server without extending the server itself. Volume can only be extended: shrinking is not possible.",
|
||||
"extending_volume_price_info": "Price includes VAT and is estimated from pricing data provided by Hetzner.",
|
||||
"size": "Size",
|
||||
"euro": "Euro",
|
||||
"data_migration_title": "Data migration",
|
||||
"data_migration_notice": "During migration all services will be turned off.",
|
||||
"start_migration_button": "Start migration"
|
||||
}
|
||||
},
|
||||
"not_ready_card": {
|
||||
|
@ -256,15 +237,6 @@
|
|||
"bottom_sheet": {
|
||||
"1": "Openconnect VPN Server. Engine for secure and scalable VPN infrastructure"
|
||||
}
|
||||
},
|
||||
"page": {
|
||||
"up_and_running": "Up and running",
|
||||
"resource_usage": "Resource usage",
|
||||
"disk_used": "{} of disk space used",
|
||||
"users": "Users",
|
||||
"controlled_by": "Controlled by {}",
|
||||
"apps": "Apps",
|
||||
"settings": "Settings and maintenance"
|
||||
}
|
||||
},
|
||||
"users": {
|
||||
|
@ -287,9 +259,6 @@
|
|||
"1": "Connect a server",
|
||||
"2": "A place where your data and SelfPrivacy services will reside:",
|
||||
"how": "How to obtain API token",
|
||||
"hetzner_bad_key_error": "Hetzner API key is invalid",
|
||||
"cloudflare_bad_key_error": "Cloudflare API key is invalid",
|
||||
"backblaze_bad_key_error": "Backblaze storage information is invalid",
|
||||
"3": "Connect CloudFlare",
|
||||
"4": "To manage your domain's DNS",
|
||||
"5": "CloudFlare API Token",
|
||||
|
@ -312,7 +281,7 @@
|
|||
"22": "Create master account",
|
||||
"23": "Enter a nickname and strong password",
|
||||
"finish": "Everything is initialized",
|
||||
"checks": "Checks have been completed \n{} out of {}"
|
||||
"checks": "Checks have been completed \n{} ouf of {}"
|
||||
},
|
||||
"recovering": {
|
||||
"recovery_main_header": "Connect to an existing server",
|
||||
|
@ -404,10 +373,8 @@
|
|||
},
|
||||
"modals": {
|
||||
"_comment": "messages in modals",
|
||||
"1": "Server with such name, already exist.",
|
||||
"1_1": "Unexpected error during placement from the provider side.",
|
||||
"1": "Server with such name, already exist",
|
||||
"2": "Destroy server and create a new one?",
|
||||
"2_2": "Try again?",
|
||||
"3": "Are you sure?",
|
||||
"4": "Purge all authentication keys?",
|
||||
"5": "Yes, purge all my tokens",
|
||||
|
|
|
@ -52,8 +52,7 @@
|
|||
"copied_ssh": "SSH ключ cкопирован в буфер",
|
||||
"delete_ssh_text": "Удалить SSH ключ?",
|
||||
"about_app_page": {
|
||||
"application_version_text": "Версия приложения v.{}",
|
||||
"api_version_text": "Версия API сервера v.{}"
|
||||
"text": "Версия приложения: v.{}"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Настройки приложения",
|
||||
|
@ -261,9 +260,6 @@
|
|||
"1": "Подключите сервер",
|
||||
"2": "Здесь будут жить наши данные и SelfPrivacy-сервисы",
|
||||
"how": "Как получить API Token",
|
||||
"hetzner_bad_key_error": "Hetzner API ключ неверен",
|
||||
"cloudflare_bad_key_error": "Cloudflare API ключ неверен",
|
||||
"backblaze_bad_key_error": "Информация о Backblaze хранилище неверна",
|
||||
"3": "Подключите CloudFlare",
|
||||
"4": "Для управления DNS вашего домена",
|
||||
"5": "CloudFlare API Token",
|
||||
|
@ -375,10 +371,8 @@
|
|||
},
|
||||
"modals": {
|
||||
"_comment": "messages in modals",
|
||||
"1": "Сервер с таким именем уже существует.",
|
||||
"1.1": "Непредвиденная ошибка при создании со стороны провайдера.",
|
||||
"1": "Сервер с таким именем уже существует",
|
||||
"2": "Уничтожить сервер и создать новый?",
|
||||
"2.2": "Попробовать ещё раз?",
|
||||
"3": "Подтвердите",
|
||||
"4": "Сбросить все ключи?",
|
||||
"5": "Да, сбросить",
|
||||
|
|
12
build.yaml
12
build.yaml
|
@ -1,17 +1,7 @@
|
|||
targets:
|
||||
$default:
|
||||
builders:
|
||||
graphql_codegen:
|
||||
options:
|
||||
scalars:
|
||||
DateTime:
|
||||
type: DateTime
|
||||
fromJsonFunctionName: dateTimeFromJson
|
||||
toJsonFunctionName: dateTimeToJson
|
||||
import: package:selfprivacy/utils/scalars.dart
|
||||
clients:
|
||||
- graphql
|
||||
json_serializable:
|
||||
options:
|
||||
create_factory: true
|
||||
create_to_json: true
|
||||
create_to_json: false
|
|
@ -1,3 +0,0 @@
|
|||
- Fixed routing errors and broken "back" buttons on recovery stages
|
||||
- Fixed broken validation on api token fields
|
||||
- Minor improvements
|
|
@ -10,7 +10,6 @@ import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
|||
import 'package:selfprivacy/logic/cubit/providers/providers_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart';
|
||||
|
||||
class BlocAndProviderConfig extends StatelessWidget {
|
||||
const BlocAndProviderConfig({final super.key, this.child});
|
||||
|
@ -27,7 +26,6 @@ class BlocAndProviderConfig extends StatelessWidget {
|
|||
final dnsRecordsCubit = DnsRecordsCubit(serverInstallationCubit);
|
||||
final recoveryKeyCubit = RecoveryKeyCubit(serverInstallationCubit);
|
||||
final apiDevicesCubit = ApiDevicesCubit(serverInstallationCubit);
|
||||
final apiVolumesCubit = ApiProviderVolumeCubit(serverInstallationCubit);
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
BlocProvider(
|
||||
|
@ -62,9 +60,6 @@ class BlocAndProviderConfig extends StatelessWidget {
|
|||
BlocProvider(
|
||||
create: (final _) => apiDevicesCubit..load(),
|
||||
),
|
||||
BlocProvider(
|
||||
create: (final _) => apiVolumesCubit..load(),
|
||||
),
|
||||
BlocProvider(
|
||||
create: (final _) =>
|
||||
JobsCubit(usersCubit: usersCubit, servicesCubit: servicesCubit),
|
||||
|
|
|
@ -2,7 +2,7 @@ import 'dart:io';
|
|||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/api_map.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backblaze_credential.dart';
|
||||
|
||||
class BackblazeApiAuth {
|
|
@ -2,11 +2,16 @@ import 'dart:io';
|
|||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/dns_provider.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/api_map.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
||||
|
||||
class CloudflareApi extends DnsProviderApi {
|
||||
class DomainNotFoundException implements Exception {
|
||||
DomainNotFoundException(this.message);
|
||||
final String message;
|
||||
}
|
||||
|
||||
class CloudflareApi extends ApiMap {
|
||||
CloudflareApi({
|
||||
this.hasLogger = false,
|
||||
this.isWithToken = true,
|
||||
|
@ -19,10 +24,6 @@ class CloudflareApi extends DnsProviderApi {
|
|||
|
||||
final String? customToken;
|
||||
|
||||
@override
|
||||
RegExp getApiTokenValidation() =>
|
||||
RegExp(r'\s+|[!$%^&*()@+|~=`{}\[\]:<>?,.\/]');
|
||||
|
||||
@override
|
||||
BaseOptions get options {
|
||||
final BaseOptions options = BaseOptions(baseUrl: rootAddress);
|
||||
|
@ -45,37 +46,27 @@ class CloudflareApi extends DnsProviderApi {
|
|||
@override
|
||||
String rootAddress = 'https://api.cloudflare.com/client/v4';
|
||||
|
||||
@override
|
||||
Future<bool> isApiTokenValid(final String token) async {
|
||||
bool isValid = false;
|
||||
Response? response;
|
||||
Future<bool> isValid(final String token) async {
|
||||
validateStatus = (final status) =>
|
||||
status == HttpStatus.ok || status == HttpStatus.unauthorized;
|
||||
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
response = await client.get(
|
||||
'/user/tokens/verify',
|
||||
options: Options(headers: {'Authorization': 'Bearer $token'}),
|
||||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
isValid = false;
|
||||
} finally {
|
||||
close(client);
|
||||
}
|
||||
final Response response = await client.get(
|
||||
'/user/tokens/verify',
|
||||
options: Options(headers: {'Authorization': 'Bearer $token'}),
|
||||
);
|
||||
|
||||
if (response != null) {
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
isValid = true;
|
||||
} else if (response.statusCode == HttpStatus.unauthorized) {
|
||||
isValid = false;
|
||||
} else {
|
||||
throw Exception('code: ${response.statusCode}');
|
||||
}
|
||||
}
|
||||
close(client);
|
||||
|
||||
return isValid;
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
return true;
|
||||
} else if (response.statusCode == HttpStatus.unauthorized) {
|
||||
return false;
|
||||
} else {
|
||||
throw Exception('code: ${response.statusCode}');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> getZoneId(final String domain) async {
|
||||
validateStatus = (final status) =>
|
||||
status == HttpStatus.ok || status == HttpStatus.forbidden;
|
||||
|
@ -94,13 +85,12 @@ class CloudflareApi extends DnsProviderApi {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> removeSimilarRecords({
|
||||
required final ServerDomain domain,
|
||||
required final ServerDomain cloudFlareDomain,
|
||||
final String? ip4,
|
||||
}) async {
|
||||
final String domainName = domain.domainName;
|
||||
final String domainZoneId = domain.zoneId;
|
||||
final String domainName = cloudFlareDomain.domainName;
|
||||
final String domainZoneId = cloudFlareDomain.zoneId;
|
||||
|
||||
final String url = '/zones/$domainZoneId/dns_records';
|
||||
|
||||
|
@ -122,12 +112,11 @@ class CloudflareApi extends DnsProviderApi {
|
|||
close(client);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<DnsRecord>> getDnsRecords({
|
||||
required final ServerDomain domain,
|
||||
required final ServerDomain cloudFlareDomain,
|
||||
}) async {
|
||||
final String domainName = domain.domainName;
|
||||
final String domainZoneId = domain.zoneId;
|
||||
final String domainName = cloudFlareDomain.domainName;
|
||||
final String domainZoneId = cloudFlareDomain.zoneId;
|
||||
|
||||
final String url = '/zones/$domainZoneId/dns_records';
|
||||
|
||||
|
@ -155,13 +144,12 @@ class CloudflareApi extends DnsProviderApi {
|
|||
return allRecords;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> createMultipleDnsRecords({
|
||||
required final ServerDomain domain,
|
||||
required final ServerDomain cloudFlareDomain,
|
||||
final String? ip4,
|
||||
}) async {
|
||||
final String domainName = domain.domainName;
|
||||
final String domainZoneId = domain.zoneId;
|
||||
final String domainName = cloudFlareDomain.domainName;
|
||||
final String domainZoneId = cloudFlareDomain.zoneId;
|
||||
final List<DnsRecord> listDnsRecords = projectDnsRecords(domainName, ip4);
|
||||
final List<Future> allCreateFutures = <Future>[];
|
||||
|
||||
|
@ -231,12 +219,11 @@ class CloudflareApi extends DnsProviderApi {
|
|||
];
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setDkim(
|
||||
final String dkimRecordString,
|
||||
final ServerDomain domain,
|
||||
final ServerDomain cloudFlareDomain,
|
||||
) async {
|
||||
final String domainZoneId = domain.zoneId;
|
||||
final String domainZoneId = cloudFlareDomain.zoneId;
|
||||
final String url = '$rootAddress/zones/$domainZoneId/dns_records';
|
||||
|
||||
final DnsRecord dkimRecord = DnsRecord(
|
||||
|
@ -255,7 +242,6 @@ class CloudflareApi extends DnsProviderApi {
|
|||
client.close();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<String>> domainList() async {
|
||||
final String url = '$rootAddress/zones';
|
||||
final Dio client = await getClient();
|
|
@ -1,55 +0,0 @@
|
|||
import 'package:graphql_flutter/graphql_flutter.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
|
||||
abstract class ApiMap {
|
||||
Future<GraphQLClient> getClient() async {
|
||||
final httpLink = HttpLink(
|
||||
'https://api.$rootAddress/graphql',
|
||||
);
|
||||
|
||||
final String token = _getApiToken();
|
||||
|
||||
final Link graphQLLink = isWithToken
|
||||
? AuthLink(
|
||||
getToken: () async =>
|
||||
customToken == '' ? 'Bearer $token' : customToken,
|
||||
).concat(httpLink)
|
||||
: httpLink;
|
||||
|
||||
return GraphQLClient(
|
||||
cache: GraphQLCache(),
|
||||
link: graphQLLink,
|
||||
);
|
||||
}
|
||||
|
||||
Future<GraphQLClient> getSubscriptionClient() async {
|
||||
final String token = _getApiToken();
|
||||
|
||||
final WebSocketLink webSocketLink = WebSocketLink(
|
||||
'ws://api.$rootAddress/graphql',
|
||||
config: SocketClientConfig(
|
||||
autoReconnect: true,
|
||||
headers: token.isEmpty ? null : {'Authorization': 'Bearer $token'},
|
||||
),
|
||||
);
|
||||
|
||||
return GraphQLClient(
|
||||
cache: GraphQLCache(),
|
||||
link: webSocketLink,
|
||||
);
|
||||
}
|
||||
|
||||
String _getApiToken() {
|
||||
String token = '';
|
||||
final serverDetails = getIt<ApiConfigModel>().serverDetails;
|
||||
if (serverDetails != null) {
|
||||
token = getIt<ApiConfigModel>().serverDetails!.apiToken;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
abstract final String? rootAddress;
|
||||
abstract final bool hasLogger;
|
||||
abstract final bool isWithToken;
|
||||
abstract final String customToken;
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
fragment basicMutationReturnFields on MutationReturnInterface{
|
||||
code
|
||||
message
|
||||
success
|
||||
}
|
||||
|
||||
query GetServerDiskVolumes {
|
||||
storage {
|
||||
volumes {
|
||||
freeSpace
|
||||
model
|
||||
name
|
||||
root
|
||||
serial
|
||||
totalSpace
|
||||
type
|
||||
usages {
|
||||
title
|
||||
usedSpace
|
||||
__typename
|
||||
... on ServiceStorageUsage {
|
||||
service {
|
||||
id
|
||||
isMovable
|
||||
displayName
|
||||
}
|
||||
}
|
||||
}
|
||||
usedSpace
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutation MountVolume($name: String!) {
|
||||
mountVolume(name: $name) {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation ResizeVolume($name: String!) {
|
||||
resizeVolume(name: $name) {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation UnmountVolume($name: String!) {
|
||||
unmountVolume(name: $name) {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation MigrateToBinds($input: MigrateToBindsInput!) {
|
||||
migrateToBinds(input: $input) {
|
||||
...basicMutationReturnFields
|
||||
job {
|
||||
createdAt
|
||||
description
|
||||
error
|
||||
finishedAt
|
||||
name
|
||||
progress
|
||||
result
|
||||
status
|
||||
statusText
|
||||
uid
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,376 +0,0 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'disk_volumes.graphql.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Fragment$basicMutationReturnFields _$Fragment$basicMutationReturnFieldsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Fragment$basicMutationReturnFields(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Fragment$basicMutationReturnFieldsToJson(
|
||||
Fragment$basicMutationReturnFields instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$GetServerDiskVolumes _$Query$GetServerDiskVolumesFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$GetServerDiskVolumes(
|
||||
storage: Query$GetServerDiskVolumes$storage.fromJson(
|
||||
json['storage'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$GetServerDiskVolumesToJson(
|
||||
Query$GetServerDiskVolumes instance) =>
|
||||
<String, dynamic>{
|
||||
'storage': instance.storage.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$GetServerDiskVolumes$storage _$Query$GetServerDiskVolumes$storageFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$GetServerDiskVolumes$storage(
|
||||
volumes: (json['volumes'] as List<dynamic>)
|
||||
.map((e) => Query$GetServerDiskVolumes$storage$volumes.fromJson(
|
||||
e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$GetServerDiskVolumes$storageToJson(
|
||||
Query$GetServerDiskVolumes$storage instance) =>
|
||||
<String, dynamic>{
|
||||
'volumes': instance.volumes.map((e) => e.toJson()).toList(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$GetServerDiskVolumes$storage$volumes
|
||||
_$Query$GetServerDiskVolumes$storage$volumesFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$GetServerDiskVolumes$storage$volumes(
|
||||
freeSpace: json['freeSpace'] as String,
|
||||
model: json['model'] as String?,
|
||||
name: json['name'] as String,
|
||||
root: json['root'] as bool,
|
||||
serial: json['serial'] as String?,
|
||||
totalSpace: json['totalSpace'] as String,
|
||||
type: json['type'] as String,
|
||||
usages: (json['usages'] as List<dynamic>)
|
||||
.map((e) =>
|
||||
Query$GetServerDiskVolumes$storage$volumes$usages.fromJson(
|
||||
e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
usedSpace: json['usedSpace'] as String,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$GetServerDiskVolumes$storage$volumesToJson(
|
||||
Query$GetServerDiskVolumes$storage$volumes instance) =>
|
||||
<String, dynamic>{
|
||||
'freeSpace': instance.freeSpace,
|
||||
'model': instance.model,
|
||||
'name': instance.name,
|
||||
'root': instance.root,
|
||||
'serial': instance.serial,
|
||||
'totalSpace': instance.totalSpace,
|
||||
'type': instance.type,
|
||||
'usages': instance.usages.map((e) => e.toJson()).toList(),
|
||||
'usedSpace': instance.usedSpace,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$GetServerDiskVolumes$storage$volumes$usages
|
||||
_$Query$GetServerDiskVolumes$storage$volumes$usagesFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$GetServerDiskVolumes$storage$volumes$usages(
|
||||
title: json['title'] as String,
|
||||
usedSpace: json['usedSpace'] as String,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$GetServerDiskVolumes$storage$volumes$usagesToJson(
|
||||
Query$GetServerDiskVolumes$storage$volumes$usages instance) =>
|
||||
<String, dynamic>{
|
||||
'title': instance.title,
|
||||
'usedSpace': instance.usedSpace,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage
|
||||
_$Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsageFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage(
|
||||
title: json['title'] as String,
|
||||
usedSpace: json['usedSpace'] as String,
|
||||
$__typename: json['__typename'] as String,
|
||||
service: json['service'] == null
|
||||
? null
|
||||
: Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage$service
|
||||
.fromJson(json['service'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic>
|
||||
_$Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsageToJson(
|
||||
Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage
|
||||
instance) =>
|
||||
<String, dynamic>{
|
||||
'title': instance.title,
|
||||
'usedSpace': instance.usedSpace,
|
||||
'__typename': instance.$__typename,
|
||||
'service': instance.service?.toJson(),
|
||||
};
|
||||
|
||||
Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage$service
|
||||
_$Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage$serviceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage$service(
|
||||
id: json['id'] as String,
|
||||
isMovable: json['isMovable'] as bool,
|
||||
displayName: json['displayName'] as String,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic>
|
||||
_$Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage$serviceToJson(
|
||||
Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage$service
|
||||
instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'isMovable': instance.isMovable,
|
||||
'displayName': instance.displayName,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$MountVolume _$Variables$Mutation$MountVolumeFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$MountVolume(
|
||||
name: json['name'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$MountVolumeToJson(
|
||||
Variables$Mutation$MountVolume instance) =>
|
||||
<String, dynamic>{
|
||||
'name': instance.name,
|
||||
};
|
||||
|
||||
Mutation$MountVolume _$Mutation$MountVolumeFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$MountVolume(
|
||||
mountVolume: Mutation$MountVolume$mountVolume.fromJson(
|
||||
json['mountVolume'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$MountVolumeToJson(
|
||||
Mutation$MountVolume instance) =>
|
||||
<String, dynamic>{
|
||||
'mountVolume': instance.mountVolume.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$MountVolume$mountVolume _$Mutation$MountVolume$mountVolumeFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$MountVolume$mountVolume(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$MountVolume$mountVolumeToJson(
|
||||
Mutation$MountVolume$mountVolume instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$ResizeVolume _$Variables$Mutation$ResizeVolumeFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$ResizeVolume(
|
||||
name: json['name'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$ResizeVolumeToJson(
|
||||
Variables$Mutation$ResizeVolume instance) =>
|
||||
<String, dynamic>{
|
||||
'name': instance.name,
|
||||
};
|
||||
|
||||
Mutation$ResizeVolume _$Mutation$ResizeVolumeFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$ResizeVolume(
|
||||
resizeVolume: Mutation$ResizeVolume$resizeVolume.fromJson(
|
||||
json['resizeVolume'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$ResizeVolumeToJson(
|
||||
Mutation$ResizeVolume instance) =>
|
||||
<String, dynamic>{
|
||||
'resizeVolume': instance.resizeVolume.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$ResizeVolume$resizeVolume _$Mutation$ResizeVolume$resizeVolumeFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$ResizeVolume$resizeVolume(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$ResizeVolume$resizeVolumeToJson(
|
||||
Mutation$ResizeVolume$resizeVolume instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$UnmountVolume _$Variables$Mutation$UnmountVolumeFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$UnmountVolume(
|
||||
name: json['name'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$UnmountVolumeToJson(
|
||||
Variables$Mutation$UnmountVolume instance) =>
|
||||
<String, dynamic>{
|
||||
'name': instance.name,
|
||||
};
|
||||
|
||||
Mutation$UnmountVolume _$Mutation$UnmountVolumeFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$UnmountVolume(
|
||||
unmountVolume: Mutation$UnmountVolume$unmountVolume.fromJson(
|
||||
json['unmountVolume'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$UnmountVolumeToJson(
|
||||
Mutation$UnmountVolume instance) =>
|
||||
<String, dynamic>{
|
||||
'unmountVolume': instance.unmountVolume.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$UnmountVolume$unmountVolume
|
||||
_$Mutation$UnmountVolume$unmountVolumeFromJson(Map<String, dynamic> json) =>
|
||||
Mutation$UnmountVolume$unmountVolume(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$UnmountVolume$unmountVolumeToJson(
|
||||
Mutation$UnmountVolume$unmountVolume instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$MigrateToBinds _$Variables$Mutation$MigrateToBindsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$MigrateToBinds(
|
||||
input: Input$MigrateToBindsInput.fromJson(
|
||||
json['input'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$MigrateToBindsToJson(
|
||||
Variables$Mutation$MigrateToBinds instance) =>
|
||||
<String, dynamic>{
|
||||
'input': instance.input.toJson(),
|
||||
};
|
||||
|
||||
Mutation$MigrateToBinds _$Mutation$MigrateToBindsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$MigrateToBinds(
|
||||
migrateToBinds: Mutation$MigrateToBinds$migrateToBinds.fromJson(
|
||||
json['migrateToBinds'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$MigrateToBindsToJson(
|
||||
Mutation$MigrateToBinds instance) =>
|
||||
<String, dynamic>{
|
||||
'migrateToBinds': instance.migrateToBinds.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$MigrateToBinds$migrateToBinds
|
||||
_$Mutation$MigrateToBinds$migrateToBindsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$MigrateToBinds$migrateToBinds(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
job: json['job'] == null
|
||||
? null
|
||||
: Mutation$MigrateToBinds$migrateToBinds$job.fromJson(
|
||||
json['job'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$MigrateToBinds$migrateToBindsToJson(
|
||||
Mutation$MigrateToBinds$migrateToBinds instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
'job': instance.job?.toJson(),
|
||||
};
|
||||
|
||||
Mutation$MigrateToBinds$migrateToBinds$job
|
||||
_$Mutation$MigrateToBinds$migrateToBinds$jobFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$MigrateToBinds$migrateToBinds$job(
|
||||
createdAt: dateTimeFromJson(json['createdAt']),
|
||||
description: json['description'] as String,
|
||||
error: json['error'] as String?,
|
||||
finishedAt: _nullable$dateTimeFromJson(json['finishedAt']),
|
||||
name: json['name'] as String,
|
||||
progress: json['progress'] as int?,
|
||||
result: json['result'] as String?,
|
||||
status: json['status'] as String,
|
||||
statusText: json['statusText'] as String?,
|
||||
uid: json['uid'] as String,
|
||||
updatedAt: dateTimeFromJson(json['updatedAt']),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$MigrateToBinds$migrateToBinds$jobToJson(
|
||||
Mutation$MigrateToBinds$migrateToBinds$job instance) =>
|
||||
<String, dynamic>{
|
||||
'createdAt': dateTimeToJson(instance.createdAt),
|
||||
'description': instance.description,
|
||||
'error': instance.error,
|
||||
'finishedAt': _nullable$dateTimeToJson(instance.finishedAt),
|
||||
'name': instance.name,
|
||||
'progress': instance.progress,
|
||||
'result': instance.result,
|
||||
'status': instance.status,
|
||||
'statusText': instance.statusText,
|
||||
'uid': instance.uid,
|
||||
'updatedAt': dateTimeToJson(instance.updatedAt),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
|
@ -1,351 +0,0 @@
|
|||
type Alert {
|
||||
message: String!
|
||||
severity: Severity!
|
||||
timestamp: DateTime
|
||||
title: String!
|
||||
}
|
||||
|
||||
type Api {
|
||||
devices: [ApiDevice!]!
|
||||
recoveryKey: ApiRecoveryKeyStatus!
|
||||
version: String!
|
||||
}
|
||||
|
||||
type ApiDevice {
|
||||
creationDate: DateTime!
|
||||
isCaller: Boolean!
|
||||
name: String!
|
||||
}
|
||||
|
||||
type ApiJob {
|
||||
createdAt: DateTime!
|
||||
description: String!
|
||||
error: String
|
||||
finishedAt: DateTime
|
||||
name: String!
|
||||
progress: Int
|
||||
result: String
|
||||
status: String!
|
||||
statusText: String
|
||||
uid: String!
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
|
||||
type ApiKeyMutationReturn implements MutationReturnInterface {
|
||||
code: Int!
|
||||
key: String
|
||||
message: String!
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
type ApiRecoveryKeyStatus {
|
||||
creationDate: DateTime
|
||||
exists: Boolean!
|
||||
expirationDate: DateTime
|
||||
usesLeft: Int
|
||||
valid: Boolean!
|
||||
}
|
||||
|
||||
type AutoUpgradeOptions {
|
||||
allowReboot: Boolean!
|
||||
enable: Boolean!
|
||||
}
|
||||
|
||||
input AutoUpgradeSettingsInput {
|
||||
enableAutoUpgrade: Boolean = null
|
||||
allowReboot: Boolean = null
|
||||
}
|
||||
|
||||
type AutoUpgradeSettingsMutationReturn implements MutationReturnInterface {
|
||||
allowReboot: Boolean!
|
||||
code: Int!
|
||||
enableAutoUpgrade: Boolean!
|
||||
message: String!
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
"""Date with time (isoformat)"""
|
||||
scalar DateTime
|
||||
|
||||
type DeviceApiTokenMutationReturn implements MutationReturnInterface {
|
||||
code: Int!
|
||||
message: String!
|
||||
success: Boolean!
|
||||
token: String
|
||||
}
|
||||
|
||||
enum DnsProvider {
|
||||
CLOUDFLARE
|
||||
}
|
||||
|
||||
type DnsRecord {
|
||||
content: String!
|
||||
name: String!
|
||||
priority: Int
|
||||
recordType: String!
|
||||
ttl: Int!
|
||||
}
|
||||
|
||||
type GenericJobButationReturn implements MutationReturnInterface {
|
||||
code: Int!
|
||||
job: ApiJob
|
||||
message: String!
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
type GenericMutationReturn implements MutationReturnInterface {
|
||||
code: Int!
|
||||
message: String!
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
type Job {
|
||||
getJob(jobId: String!): ApiJob
|
||||
getJobs: [ApiJob!]!
|
||||
}
|
||||
|
||||
input MigrateToBindsInput {
|
||||
emailBlockDevice: String!
|
||||
bitwardenBlockDevice: String!
|
||||
giteaBlockDevice: String!
|
||||
nextcloudBlockDevice: String!
|
||||
pleromaBlockDevice: String!
|
||||
}
|
||||
|
||||
input MoveServiceInput {
|
||||
serviceId: String!
|
||||
location: String!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
addSshKey(sshInput: SshMutationInput!): UserMutationReturn!
|
||||
authorizeWithNewDeviceApiKey(input: UseNewDeviceKeyInput!): DeviceApiTokenMutationReturn!
|
||||
changeAutoUpgradeSettings(settings: AutoUpgradeSettingsInput!): AutoUpgradeSettingsMutationReturn!
|
||||
changeTimezone(timezone: String!): TimezoneMutationReturn!
|
||||
createUser(user: UserMutationInput!): UserMutationReturn!
|
||||
deleteDeviceApiToken(device: String!): GenericMutationReturn!
|
||||
deleteUser(username: String!): GenericMutationReturn!
|
||||
disableService(serviceId: String!): ServiceMutationReturn!
|
||||
enableService(serviceId: String!): ServiceMutationReturn!
|
||||
getNewDeviceApiKey: ApiKeyMutationReturn!
|
||||
getNewRecoveryApiKey(limits: RecoveryKeyLimitsInput = null): ApiKeyMutationReturn!
|
||||
invalidateNewDeviceApiKey: GenericMutationReturn!
|
||||
migrateToBinds(input: MigrateToBindsInput!): GenericJobButationReturn!
|
||||
mountVolume(name: String!): GenericMutationReturn!
|
||||
moveService(input: MoveServiceInput!): ServiceJobMutationReturn!
|
||||
pullRepositoryChanges: GenericMutationReturn!
|
||||
rebootSystem: GenericMutationReturn!
|
||||
refreshDeviceApiToken: DeviceApiTokenMutationReturn!
|
||||
removeJob(jobId: String!): GenericMutationReturn!
|
||||
removeSshKey(sshInput: SshMutationInput!): UserMutationReturn!
|
||||
resizeVolume(name: String!): GenericMutationReturn!
|
||||
restartService(serviceId: String!): ServiceMutationReturn!
|
||||
runSystemRebuild: GenericMutationReturn!
|
||||
runSystemRollback: GenericMutationReturn!
|
||||
runSystemUpgrade: GenericMutationReturn!
|
||||
startService(serviceId: String!): ServiceMutationReturn!
|
||||
stopService(serviceId: String!): ServiceMutationReturn!
|
||||
testMutation: GenericMutationReturn!
|
||||
unmountVolume(name: String!): GenericMutationReturn!
|
||||
updateUser(user: UserMutationInput!): UserMutationReturn!
|
||||
useRecoveryApiKey(input: UseRecoveryKeyInput!): DeviceApiTokenMutationReturn!
|
||||
}
|
||||
|
||||
interface MutationReturnInterface {
|
||||
code: Int!
|
||||
message: String!
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
type Query {
|
||||
api: Api!
|
||||
jobs: Job!
|
||||
services: Services!
|
||||
storage: Storage!
|
||||
system: System!
|
||||
users: Users!
|
||||
}
|
||||
|
||||
input RecoveryKeyLimitsInput {
|
||||
expirationDate: DateTime = null
|
||||
uses: Int = null
|
||||
}
|
||||
|
||||
enum ServerProvider {
|
||||
HETZNER
|
||||
}
|
||||
|
||||
type Service {
|
||||
description: String!
|
||||
displayName: String!
|
||||
dnsRecords: [DnsRecord!]
|
||||
id: String!
|
||||
isEnabled: Boolean!
|
||||
isMovable: Boolean!
|
||||
isRequired: Boolean!
|
||||
status: ServiceStatusEnum!
|
||||
storageUsage: ServiceStorageUsage!
|
||||
svgIcon: String!
|
||||
url: String
|
||||
}
|
||||
|
||||
type ServiceJobMutationReturn implements MutationReturnInterface {
|
||||
code: Int!
|
||||
job: ApiJob
|
||||
message: String!
|
||||
service: Service
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
type ServiceMutationReturn implements MutationReturnInterface {
|
||||
code: Int!
|
||||
message: String!
|
||||
service: Service
|
||||
success: Boolean!
|
||||
}
|
||||
|
||||
enum ServiceStatusEnum {
|
||||
ACTIVATING
|
||||
ACTIVE
|
||||
DEACTIVATING
|
||||
FAILED
|
||||
INACTIVE
|
||||
OFF
|
||||
RELOADING
|
||||
}
|
||||
|
||||
type ServiceStorageUsage implements StorageUsageInterface {
|
||||
service: Service
|
||||
title: String!
|
||||
usedSpace: String!
|
||||
volume: StorageVolume
|
||||
}
|
||||
|
||||
type Services {
|
||||
allServices: [Service!]!
|
||||
}
|
||||
|
||||
enum Severity {
|
||||
CRITICAL
|
||||
ERROR
|
||||
INFO
|
||||
SUCCESS
|
||||
WARNING
|
||||
}
|
||||
|
||||
input SshMutationInput {
|
||||
username: String!
|
||||
sshKey: String!
|
||||
}
|
||||
|
||||
type SshSettings {
|
||||
enable: Boolean!
|
||||
passwordAuthentication: Boolean!
|
||||
rootSshKeys: [String!]!
|
||||
}
|
||||
|
||||
type Storage {
|
||||
volumes: [StorageVolume!]!
|
||||
}
|
||||
|
||||
interface StorageUsageInterface {
|
||||
title: String!
|
||||
usedSpace: String!
|
||||
volume: StorageVolume
|
||||
}
|
||||
|
||||
type StorageVolume {
|
||||
freeSpace: String!
|
||||
model: String
|
||||
name: String!
|
||||
root: Boolean!
|
||||
serial: String
|
||||
totalSpace: String!
|
||||
type: String!
|
||||
usages: [StorageUsageInterface!]!
|
||||
usedSpace: String!
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
count(target: Int! = 100): Int!
|
||||
}
|
||||
|
||||
type System {
|
||||
busy: Boolean!
|
||||
domainInfo: SystemDomainInfo!
|
||||
info: SystemInfo!
|
||||
provider: SystemProviderInfo!
|
||||
settings: SystemSettings!
|
||||
status: Alert!
|
||||
workingDirectory: String!
|
||||
}
|
||||
|
||||
type SystemDomainInfo {
|
||||
domain: String!
|
||||
hostname: String!
|
||||
provider: DnsProvider!
|
||||
requiredDnsRecords: [DnsRecord!]!
|
||||
}
|
||||
|
||||
type SystemInfo {
|
||||
pythonVersion: String!
|
||||
systemVersion: String!
|
||||
usingBinds: Boolean!
|
||||
}
|
||||
|
||||
type SystemProviderInfo {
|
||||
id: String!
|
||||
provider: ServerProvider!
|
||||
}
|
||||
|
||||
type SystemSettings {
|
||||
autoUpgrade: AutoUpgradeOptions!
|
||||
ssh: SshSettings!
|
||||
timezone: String!
|
||||
}
|
||||
|
||||
type TimezoneMutationReturn implements MutationReturnInterface {
|
||||
code: Int!
|
||||
message: String!
|
||||
success: Boolean!
|
||||
timezone: String
|
||||
}
|
||||
|
||||
input UseNewDeviceKeyInput {
|
||||
key: String!
|
||||
deviceName: String!
|
||||
}
|
||||
|
||||
input UseRecoveryKeyInput {
|
||||
key: String!
|
||||
deviceName: String!
|
||||
}
|
||||
|
||||
type User {
|
||||
sshKeys: [String!]!
|
||||
userType: UserType!
|
||||
username: String!
|
||||
}
|
||||
|
||||
input UserMutationInput {
|
||||
username: String!
|
||||
password: String!
|
||||
}
|
||||
|
||||
type UserMutationReturn implements MutationReturnInterface {
|
||||
code: Int!
|
||||
message: String!
|
||||
success: Boolean!
|
||||
user: User
|
||||
}
|
||||
|
||||
enum UserType {
|
||||
NORMAL
|
||||
PRIMARY
|
||||
ROOT
|
||||
}
|
||||
|
||||
type Users {
|
||||
allUsers: [User!]!
|
||||
getUser(username: String!): User
|
||||
}
|
|
@ -1,443 +0,0 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:selfprivacy/utils/scalars.dart';
|
||||
part 'schema.graphql.g.dart';
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class Input$AutoUpgradeSettingsInput {
|
||||
Input$AutoUpgradeSettingsInput({this.enableAutoUpgrade, this.allowReboot});
|
||||
|
||||
@override
|
||||
factory Input$AutoUpgradeSettingsInput.fromJson(Map<String, dynamic> json) =>
|
||||
_$Input$AutoUpgradeSettingsInputFromJson(json);
|
||||
|
||||
final bool? enableAutoUpgrade;
|
||||
|
||||
final bool? allowReboot;
|
||||
|
||||
Map<String, dynamic> toJson() => _$Input$AutoUpgradeSettingsInputToJson(this);
|
||||
int get hashCode {
|
||||
final l$enableAutoUpgrade = enableAutoUpgrade;
|
||||
final l$allowReboot = allowReboot;
|
||||
return Object.hashAll([l$enableAutoUpgrade, l$allowReboot]);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (!(other is Input$AutoUpgradeSettingsInput) ||
|
||||
runtimeType != other.runtimeType) return false;
|
||||
final l$enableAutoUpgrade = enableAutoUpgrade;
|
||||
final lOther$enableAutoUpgrade = other.enableAutoUpgrade;
|
||||
if (l$enableAutoUpgrade != lOther$enableAutoUpgrade) return false;
|
||||
final l$allowReboot = allowReboot;
|
||||
final lOther$allowReboot = other.allowReboot;
|
||||
if (l$allowReboot != lOther$allowReboot) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Input$AutoUpgradeSettingsInput copyWith(
|
||||
{bool? Function()? enableAutoUpgrade,
|
||||
bool? Function()? allowReboot}) =>
|
||||
Input$AutoUpgradeSettingsInput(
|
||||
enableAutoUpgrade: enableAutoUpgrade == null
|
||||
? this.enableAutoUpgrade
|
||||
: enableAutoUpgrade(),
|
||||
allowReboot: allowReboot == null ? this.allowReboot : allowReboot());
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class Input$MigrateToBindsInput {
|
||||
Input$MigrateToBindsInput(
|
||||
{required this.emailBlockDevice,
|
||||
required this.bitwardenBlockDevice,
|
||||
required this.giteaBlockDevice,
|
||||
required this.nextcloudBlockDevice,
|
||||
required this.pleromaBlockDevice});
|
||||
|
||||
@override
|
||||
factory Input$MigrateToBindsInput.fromJson(Map<String, dynamic> json) =>
|
||||
_$Input$MigrateToBindsInputFromJson(json);
|
||||
|
||||
final String emailBlockDevice;
|
||||
|
||||
final String bitwardenBlockDevice;
|
||||
|
||||
final String giteaBlockDevice;
|
||||
|
||||
final String nextcloudBlockDevice;
|
||||
|
||||
final String pleromaBlockDevice;
|
||||
|
||||
Map<String, dynamic> toJson() => _$Input$MigrateToBindsInputToJson(this);
|
||||
int get hashCode {
|
||||
final l$emailBlockDevice = emailBlockDevice;
|
||||
final l$bitwardenBlockDevice = bitwardenBlockDevice;
|
||||
final l$giteaBlockDevice = giteaBlockDevice;
|
||||
final l$nextcloudBlockDevice = nextcloudBlockDevice;
|
||||
final l$pleromaBlockDevice = pleromaBlockDevice;
|
||||
return Object.hashAll([
|
||||
l$emailBlockDevice,
|
||||
l$bitwardenBlockDevice,
|
||||
l$giteaBlockDevice,
|
||||
l$nextcloudBlockDevice,
|
||||
l$pleromaBlockDevice
|
||||
]);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (!(other is Input$MigrateToBindsInput) ||
|
||||
runtimeType != other.runtimeType) return false;
|
||||
final l$emailBlockDevice = emailBlockDevice;
|
||||
final lOther$emailBlockDevice = other.emailBlockDevice;
|
||||
if (l$emailBlockDevice != lOther$emailBlockDevice) return false;
|
||||
final l$bitwardenBlockDevice = bitwardenBlockDevice;
|
||||
final lOther$bitwardenBlockDevice = other.bitwardenBlockDevice;
|
||||
if (l$bitwardenBlockDevice != lOther$bitwardenBlockDevice) return false;
|
||||
final l$giteaBlockDevice = giteaBlockDevice;
|
||||
final lOther$giteaBlockDevice = other.giteaBlockDevice;
|
||||
if (l$giteaBlockDevice != lOther$giteaBlockDevice) return false;
|
||||
final l$nextcloudBlockDevice = nextcloudBlockDevice;
|
||||
final lOther$nextcloudBlockDevice = other.nextcloudBlockDevice;
|
||||
if (l$nextcloudBlockDevice != lOther$nextcloudBlockDevice) return false;
|
||||
final l$pleromaBlockDevice = pleromaBlockDevice;
|
||||
final lOther$pleromaBlockDevice = other.pleromaBlockDevice;
|
||||
if (l$pleromaBlockDevice != lOther$pleromaBlockDevice) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Input$MigrateToBindsInput copyWith(
|
||||
{String? emailBlockDevice,
|
||||
String? bitwardenBlockDevice,
|
||||
String? giteaBlockDevice,
|
||||
String? nextcloudBlockDevice,
|
||||
String? pleromaBlockDevice}) =>
|
||||
Input$MigrateToBindsInput(
|
||||
emailBlockDevice: emailBlockDevice == null
|
||||
? this.emailBlockDevice
|
||||
: emailBlockDevice,
|
||||
bitwardenBlockDevice: bitwardenBlockDevice == null
|
||||
? this.bitwardenBlockDevice
|
||||
: bitwardenBlockDevice,
|
||||
giteaBlockDevice: giteaBlockDevice == null
|
||||
? this.giteaBlockDevice
|
||||
: giteaBlockDevice,
|
||||
nextcloudBlockDevice: nextcloudBlockDevice == null
|
||||
? this.nextcloudBlockDevice
|
||||
: nextcloudBlockDevice,
|
||||
pleromaBlockDevice: pleromaBlockDevice == null
|
||||
? this.pleromaBlockDevice
|
||||
: pleromaBlockDevice);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class Input$MoveServiceInput {
|
||||
Input$MoveServiceInput({required this.serviceId, required this.location});
|
||||
|
||||
@override
|
||||
factory Input$MoveServiceInput.fromJson(Map<String, dynamic> json) =>
|
||||
_$Input$MoveServiceInputFromJson(json);
|
||||
|
||||
final String serviceId;
|
||||
|
||||
final String location;
|
||||
|
||||
Map<String, dynamic> toJson() => _$Input$MoveServiceInputToJson(this);
|
||||
int get hashCode {
|
||||
final l$serviceId = serviceId;
|
||||
final l$location = location;
|
||||
return Object.hashAll([l$serviceId, l$location]);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (!(other is Input$MoveServiceInput) || runtimeType != other.runtimeType)
|
||||
return false;
|
||||
final l$serviceId = serviceId;
|
||||
final lOther$serviceId = other.serviceId;
|
||||
if (l$serviceId != lOther$serviceId) return false;
|
||||
final l$location = location;
|
||||
final lOther$location = other.location;
|
||||
if (l$location != lOther$location) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Input$MoveServiceInput copyWith({String? serviceId, String? location}) =>
|
||||
Input$MoveServiceInput(
|
||||
serviceId: serviceId == null ? this.serviceId : serviceId,
|
||||
location: location == null ? this.location : location);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class Input$RecoveryKeyLimitsInput {
|
||||
Input$RecoveryKeyLimitsInput({this.expirationDate, this.uses});
|
||||
|
||||
@override
|
||||
factory Input$RecoveryKeyLimitsInput.fromJson(Map<String, dynamic> json) =>
|
||||
_$Input$RecoveryKeyLimitsInputFromJson(json);
|
||||
|
||||
@JsonKey(
|
||||
fromJson: _nullable$dateTimeFromJson, toJson: _nullable$dateTimeToJson)
|
||||
final DateTime? expirationDate;
|
||||
|
||||
final int? uses;
|
||||
|
||||
Map<String, dynamic> toJson() => _$Input$RecoveryKeyLimitsInputToJson(this);
|
||||
int get hashCode {
|
||||
final l$expirationDate = expirationDate;
|
||||
final l$uses = uses;
|
||||
return Object.hashAll([l$expirationDate, l$uses]);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (!(other is Input$RecoveryKeyLimitsInput) ||
|
||||
runtimeType != other.runtimeType) return false;
|
||||
final l$expirationDate = expirationDate;
|
||||
final lOther$expirationDate = other.expirationDate;
|
||||
if (l$expirationDate != lOther$expirationDate) return false;
|
||||
final l$uses = uses;
|
||||
final lOther$uses = other.uses;
|
||||
if (l$uses != lOther$uses) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Input$RecoveryKeyLimitsInput copyWith(
|
||||
{DateTime? Function()? expirationDate, int? Function()? uses}) =>
|
||||
Input$RecoveryKeyLimitsInput(
|
||||
expirationDate:
|
||||
expirationDate == null ? this.expirationDate : expirationDate(),
|
||||
uses: uses == null ? this.uses : uses());
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class Input$SshMutationInput {
|
||||
Input$SshMutationInput({required this.username, required this.sshKey});
|
||||
|
||||
@override
|
||||
factory Input$SshMutationInput.fromJson(Map<String, dynamic> json) =>
|
||||
_$Input$SshMutationInputFromJson(json);
|
||||
|
||||
final String username;
|
||||
|
||||
final String sshKey;
|
||||
|
||||
Map<String, dynamic> toJson() => _$Input$SshMutationInputToJson(this);
|
||||
int get hashCode {
|
||||
final l$username = username;
|
||||
final l$sshKey = sshKey;
|
||||
return Object.hashAll([l$username, l$sshKey]);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (!(other is Input$SshMutationInput) || runtimeType != other.runtimeType)
|
||||
return false;
|
||||
final l$username = username;
|
||||
final lOther$username = other.username;
|
||||
if (l$username != lOther$username) return false;
|
||||
final l$sshKey = sshKey;
|
||||
final lOther$sshKey = other.sshKey;
|
||||
if (l$sshKey != lOther$sshKey) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Input$SshMutationInput copyWith({String? username, String? sshKey}) =>
|
||||
Input$SshMutationInput(
|
||||
username: username == null ? this.username : username,
|
||||
sshKey: sshKey == null ? this.sshKey : sshKey);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class Input$UseNewDeviceKeyInput {
|
||||
Input$UseNewDeviceKeyInput({required this.key, required this.deviceName});
|
||||
|
||||
@override
|
||||
factory Input$UseNewDeviceKeyInput.fromJson(Map<String, dynamic> json) =>
|
||||
_$Input$UseNewDeviceKeyInputFromJson(json);
|
||||
|
||||
final String key;
|
||||
|
||||
final String deviceName;
|
||||
|
||||
Map<String, dynamic> toJson() => _$Input$UseNewDeviceKeyInputToJson(this);
|
||||
int get hashCode {
|
||||
final l$key = key;
|
||||
final l$deviceName = deviceName;
|
||||
return Object.hashAll([l$key, l$deviceName]);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (!(other is Input$UseNewDeviceKeyInput) ||
|
||||
runtimeType != other.runtimeType) return false;
|
||||
final l$key = key;
|
||||
final lOther$key = other.key;
|
||||
if (l$key != lOther$key) return false;
|
||||
final l$deviceName = deviceName;
|
||||
final lOther$deviceName = other.deviceName;
|
||||
if (l$deviceName != lOther$deviceName) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Input$UseNewDeviceKeyInput copyWith({String? key, String? deviceName}) =>
|
||||
Input$UseNewDeviceKeyInput(
|
||||
key: key == null ? this.key : key,
|
||||
deviceName: deviceName == null ? this.deviceName : deviceName);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class Input$UseRecoveryKeyInput {
|
||||
Input$UseRecoveryKeyInput({required this.key, required this.deviceName});
|
||||
|
||||
@override
|
||||
factory Input$UseRecoveryKeyInput.fromJson(Map<String, dynamic> json) =>
|
||||
_$Input$UseRecoveryKeyInputFromJson(json);
|
||||
|
||||
final String key;
|
||||
|
||||
final String deviceName;
|
||||
|
||||
Map<String, dynamic> toJson() => _$Input$UseRecoveryKeyInputToJson(this);
|
||||
int get hashCode {
|
||||
final l$key = key;
|
||||
final l$deviceName = deviceName;
|
||||
return Object.hashAll([l$key, l$deviceName]);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (!(other is Input$UseRecoveryKeyInput) ||
|
||||
runtimeType != other.runtimeType) return false;
|
||||
final l$key = key;
|
||||
final lOther$key = other.key;
|
||||
if (l$key != lOther$key) return false;
|
||||
final l$deviceName = deviceName;
|
||||
final lOther$deviceName = other.deviceName;
|
||||
if (l$deviceName != lOther$deviceName) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Input$UseRecoveryKeyInput copyWith({String? key, String? deviceName}) =>
|
||||
Input$UseRecoveryKeyInput(
|
||||
key: key == null ? this.key : key,
|
||||
deviceName: deviceName == null ? this.deviceName : deviceName);
|
||||
}
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class Input$UserMutationInput {
|
||||
Input$UserMutationInput({required this.username, required this.password});
|
||||
|
||||
@override
|
||||
factory Input$UserMutationInput.fromJson(Map<String, dynamic> json) =>
|
||||
_$Input$UserMutationInputFromJson(json);
|
||||
|
||||
final String username;
|
||||
|
||||
final String password;
|
||||
|
||||
Map<String, dynamic> toJson() => _$Input$UserMutationInputToJson(this);
|
||||
int get hashCode {
|
||||
final l$username = username;
|
||||
final l$password = password;
|
||||
return Object.hashAll([l$username, l$password]);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (!(other is Input$UserMutationInput) || runtimeType != other.runtimeType)
|
||||
return false;
|
||||
final l$username = username;
|
||||
final lOther$username = other.username;
|
||||
if (l$username != lOther$username) return false;
|
||||
final l$password = password;
|
||||
final lOther$password = other.password;
|
||||
if (l$password != lOther$password) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Input$UserMutationInput copyWith({String? username, String? password}) =>
|
||||
Input$UserMutationInput(
|
||||
username: username == null ? this.username : username,
|
||||
password: password == null ? this.password : password);
|
||||
}
|
||||
|
||||
enum Enum$DnsProvider {
|
||||
@JsonValue('CLOUDFLARE')
|
||||
CLOUDFLARE,
|
||||
$unknown
|
||||
}
|
||||
|
||||
enum Enum$ServerProvider {
|
||||
@JsonValue('HETZNER')
|
||||
HETZNER,
|
||||
$unknown
|
||||
}
|
||||
|
||||
enum Enum$ServiceStatusEnum {
|
||||
@JsonValue('ACTIVATING')
|
||||
ACTIVATING,
|
||||
@JsonValue('ACTIVE')
|
||||
ACTIVE,
|
||||
@JsonValue('DEACTIVATING')
|
||||
DEACTIVATING,
|
||||
@JsonValue('FAILED')
|
||||
FAILED,
|
||||
@JsonValue('INACTIVE')
|
||||
INACTIVE,
|
||||
@JsonValue('OFF')
|
||||
OFF,
|
||||
@JsonValue('RELOADING')
|
||||
RELOADING,
|
||||
$unknown
|
||||
}
|
||||
|
||||
enum Enum$Severity {
|
||||
@JsonValue('CRITICAL')
|
||||
CRITICAL,
|
||||
@JsonValue('ERROR')
|
||||
ERROR,
|
||||
@JsonValue('INFO')
|
||||
INFO,
|
||||
@JsonValue('SUCCESS')
|
||||
SUCCESS,
|
||||
@JsonValue('WARNING')
|
||||
WARNING,
|
||||
$unknown
|
||||
}
|
||||
|
||||
enum Enum$UserType {
|
||||
@JsonValue('NORMAL')
|
||||
NORMAL,
|
||||
@JsonValue('PRIMARY')
|
||||
PRIMARY,
|
||||
@JsonValue('ROOT')
|
||||
ROOT,
|
||||
$unknown
|
||||
}
|
||||
|
||||
const possibleTypesMap = {
|
||||
'MutationReturnInterface': {
|
||||
'ApiKeyMutationReturn',
|
||||
'AutoUpgradeSettingsMutationReturn',
|
||||
'DeviceApiTokenMutationReturn',
|
||||
'GenericJobButationReturn',
|
||||
'GenericMutationReturn',
|
||||
'ServiceJobMutationReturn',
|
||||
'ServiceMutationReturn',
|
||||
'TimezoneMutationReturn',
|
||||
'UserMutationReturn'
|
||||
},
|
||||
'StorageUsageInterface': {'ServiceStorageUsage'}
|
||||
};
|
||||
DateTime? _nullable$dateTimeFromJson(dynamic data) =>
|
||||
data == null ? null : dateTimeFromJson(data);
|
||||
dynamic _nullable$dateTimeToJson(DateTime? data) =>
|
||||
data == null ? null : dateTimeToJson(data);
|
|
@ -1,125 +0,0 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'schema.graphql.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Input$AutoUpgradeSettingsInput _$Input$AutoUpgradeSettingsInputFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Input$AutoUpgradeSettingsInput(
|
||||
enableAutoUpgrade: json['enableAutoUpgrade'] as bool?,
|
||||
allowReboot: json['allowReboot'] as bool?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Input$AutoUpgradeSettingsInputToJson(
|
||||
Input$AutoUpgradeSettingsInput instance) =>
|
||||
<String, dynamic>{
|
||||
'enableAutoUpgrade': instance.enableAutoUpgrade,
|
||||
'allowReboot': instance.allowReboot,
|
||||
};
|
||||
|
||||
Input$MigrateToBindsInput _$Input$MigrateToBindsInputFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Input$MigrateToBindsInput(
|
||||
emailBlockDevice: json['emailBlockDevice'] as String,
|
||||
bitwardenBlockDevice: json['bitwardenBlockDevice'] as String,
|
||||
giteaBlockDevice: json['giteaBlockDevice'] as String,
|
||||
nextcloudBlockDevice: json['nextcloudBlockDevice'] as String,
|
||||
pleromaBlockDevice: json['pleromaBlockDevice'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Input$MigrateToBindsInputToJson(
|
||||
Input$MigrateToBindsInput instance) =>
|
||||
<String, dynamic>{
|
||||
'emailBlockDevice': instance.emailBlockDevice,
|
||||
'bitwardenBlockDevice': instance.bitwardenBlockDevice,
|
||||
'giteaBlockDevice': instance.giteaBlockDevice,
|
||||
'nextcloudBlockDevice': instance.nextcloudBlockDevice,
|
||||
'pleromaBlockDevice': instance.pleromaBlockDevice,
|
||||
};
|
||||
|
||||
Input$MoveServiceInput _$Input$MoveServiceInputFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Input$MoveServiceInput(
|
||||
serviceId: json['serviceId'] as String,
|
||||
location: json['location'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Input$MoveServiceInputToJson(
|
||||
Input$MoveServiceInput instance) =>
|
||||
<String, dynamic>{
|
||||
'serviceId': instance.serviceId,
|
||||
'location': instance.location,
|
||||
};
|
||||
|
||||
Input$RecoveryKeyLimitsInput _$Input$RecoveryKeyLimitsInputFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Input$RecoveryKeyLimitsInput(
|
||||
expirationDate: _nullable$dateTimeFromJson(json['expirationDate']),
|
||||
uses: json['uses'] as int?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Input$RecoveryKeyLimitsInputToJson(
|
||||
Input$RecoveryKeyLimitsInput instance) =>
|
||||
<String, dynamic>{
|
||||
'expirationDate': _nullable$dateTimeToJson(instance.expirationDate),
|
||||
'uses': instance.uses,
|
||||
};
|
||||
|
||||
Input$SshMutationInput _$Input$SshMutationInputFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Input$SshMutationInput(
|
||||
username: json['username'] as String,
|
||||
sshKey: json['sshKey'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Input$SshMutationInputToJson(
|
||||
Input$SshMutationInput instance) =>
|
||||
<String, dynamic>{
|
||||
'username': instance.username,
|
||||
'sshKey': instance.sshKey,
|
||||
};
|
||||
|
||||
Input$UseNewDeviceKeyInput _$Input$UseNewDeviceKeyInputFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Input$UseNewDeviceKeyInput(
|
||||
key: json['key'] as String,
|
||||
deviceName: json['deviceName'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Input$UseNewDeviceKeyInputToJson(
|
||||
Input$UseNewDeviceKeyInput instance) =>
|
||||
<String, dynamic>{
|
||||
'key': instance.key,
|
||||
'deviceName': instance.deviceName,
|
||||
};
|
||||
|
||||
Input$UseRecoveryKeyInput _$Input$UseRecoveryKeyInputFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Input$UseRecoveryKeyInput(
|
||||
key: json['key'] as String,
|
||||
deviceName: json['deviceName'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Input$UseRecoveryKeyInputToJson(
|
||||
Input$UseRecoveryKeyInput instance) =>
|
||||
<String, dynamic>{
|
||||
'key': instance.key,
|
||||
'deviceName': instance.deviceName,
|
||||
};
|
||||
|
||||
Input$UserMutationInput _$Input$UserMutationInputFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Input$UserMutationInput(
|
||||
username: json['username'] as String,
|
||||
password: json['password'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Input$UserMutationInputToJson(
|
||||
Input$UserMutationInput instance) =>
|
||||
<String, dynamic>{
|
||||
'username': instance.username,
|
||||
'password': instance.password,
|
||||
};
|
|
@ -1,235 +0,0 @@
|
|||
import 'package:graphql/client.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/api_map.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server_api.graphql.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/disk_volumes.graphql.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/services.graphql.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
import 'package:selfprivacy/logic/models/json/api_token.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_disk_volume.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||
|
||||
class ServerApi extends ApiMap {
|
||||
ServerApi({
|
||||
this.hasLogger = false,
|
||||
this.isWithToken = true,
|
||||
this.customToken = '',
|
||||
}) {
|
||||
final ServerDomain? serverDomain = getIt<ApiConfigModel>().serverDomain;
|
||||
rootAddress = serverDomain?.domainName ?? '';
|
||||
}
|
||||
@override
|
||||
bool hasLogger;
|
||||
@override
|
||||
bool isWithToken;
|
||||
@override
|
||||
String customToken;
|
||||
@override
|
||||
String? rootAddress;
|
||||
|
||||
Future<bool> _commonBoolRequest(final Function graphQLMethod) async {
|
||||
QueryResult response;
|
||||
bool result = false;
|
||||
|
||||
try {
|
||||
response = await graphQLMethod();
|
||||
if (response.hasException) {
|
||||
print(response.exception.toString());
|
||||
result = false;
|
||||
} else {
|
||||
result = true;
|
||||
}
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<String?> getApiVersion() async {
|
||||
QueryResult response;
|
||||
String? apiVersion;
|
||||
|
||||
try {
|
||||
final GraphQLClient client = await getClient();
|
||||
response = await client.query$GetApiVersion();
|
||||
if (response.hasException) {
|
||||
print(response.exception.toString());
|
||||
}
|
||||
apiVersion = response.data!['api']['version'];
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
return apiVersion;
|
||||
}
|
||||
|
||||
Future<List<ApiToken>> getApiTokens() async {
|
||||
QueryResult response;
|
||||
List<ApiToken> tokens = [];
|
||||
|
||||
try {
|
||||
final GraphQLClient client = await getClient();
|
||||
response = await client.query$GetApiTokens();
|
||||
if (response.hasException) {
|
||||
print(response.exception.toString());
|
||||
}
|
||||
tokens = response.data!['api']['devices']
|
||||
.map<ApiToken>((final e) => ApiToken.fromJson(e))
|
||||
.toList();
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
Future<List<ServerDiskVolume>> getServerDiskVolumes() async {
|
||||
QueryResult response;
|
||||
List<ServerDiskVolume> volumes = [];
|
||||
|
||||
try {
|
||||
final GraphQLClient client = await getClient();
|
||||
response = await client.query$GetServerDiskVolumes();
|
||||
if (response.hasException) {
|
||||
print(response.exception.toString());
|
||||
}
|
||||
volumes = response.data!['storage']['volumes']
|
||||
.map<ServerDiskVolume>((final e) => ServerDiskVolume.fromJson(e))
|
||||
.toList();
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
|
||||
return volumes;
|
||||
}
|
||||
|
||||
Future<void> mountVolume(final String volumeName) async {
|
||||
try {
|
||||
final GraphQLClient client = await getClient();
|
||||
final variables = Variables$Mutation$MountVolume(name: volumeName);
|
||||
final mountVolumeMutation =
|
||||
Options$Mutation$MountVolume(variables: variables);
|
||||
await client.mutate$MountVolume(mountVolumeMutation);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> unmountVolume(final String volumeName) async {
|
||||
try {
|
||||
final GraphQLClient client = await getClient();
|
||||
final variables = Variables$Mutation$UnmountVolume(name: volumeName);
|
||||
final unmountVolumeMutation =
|
||||
Options$Mutation$UnmountVolume(variables: variables);
|
||||
await client.mutate$UnmountVolume(unmountVolumeMutation);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> resizeVolume(final String volumeName) async {
|
||||
try {
|
||||
final GraphQLClient client = await getClient();
|
||||
final variables = Variables$Mutation$ResizeVolume(name: volumeName);
|
||||
final resizeVolumeMutation =
|
||||
Options$Mutation$ResizeVolume(variables: variables);
|
||||
await client.mutate$ResizeVolume(resizeVolumeMutation);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<ServerJob>> getServerJobs() async {
|
||||
QueryResult response;
|
||||
List<ServerJob> jobs = [];
|
||||
|
||||
try {
|
||||
final GraphQLClient client = await getClient();
|
||||
response = await client.query$GetApiJobs();
|
||||
if (response.hasException) {
|
||||
print(response.exception.toString());
|
||||
}
|
||||
jobs = response.data!['jobs']
|
||||
.map<ServerJob>((final e) => ServerJob.fromJson(e))
|
||||
.toList();
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
|
||||
return jobs;
|
||||
}
|
||||
|
||||
Future<void> removeApiJob(final String uid) async {
|
||||
try {
|
||||
final GraphQLClient client = await getClient();
|
||||
//await client.query$GetApiJobsQuery();
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> reboot() async {
|
||||
try {
|
||||
final GraphQLClient client = await getClient();
|
||||
return await _commonBoolRequest(
|
||||
() async {
|
||||
await client.mutate$RebootSystem();
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> pullConfigurationUpdate() async {
|
||||
try {
|
||||
final GraphQLClient client = await getClient();
|
||||
return await _commonBoolRequest(
|
||||
() async {
|
||||
await client.mutate$PullRepositoryChanges();
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> upgrade() async {
|
||||
try {
|
||||
final GraphQLClient client = await getClient();
|
||||
return await _commonBoolRequest(
|
||||
() async {
|
||||
await client.mutate$RunSystemUpgrade();
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> switchService(final String uid, final bool needTurnOn) async {
|
||||
try {
|
||||
final GraphQLClient client = await getClient();
|
||||
if (needTurnOn) {
|
||||
final variables = Variables$Mutation$EnableService(serviceId: uid);
|
||||
final mutation = Options$Mutation$EnableService(variables: variables);
|
||||
await client.mutate$EnableService(mutation);
|
||||
} else {
|
||||
final variables = Variables$Mutation$DisableService(serviceId: uid);
|
||||
final mutation = Options$Mutation$DisableService(variables: variables);
|
||||
await client.mutate$DisableService(mutation);
|
||||
}
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> apply() async {
|
||||
try {
|
||||
final GraphQLClient client = await getClient();
|
||||
await client.mutate$RunSystemRebuild();
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
fragment basicMutationReturnFields on MutationReturnInterface{
|
||||
code
|
||||
message
|
||||
success
|
||||
}
|
||||
|
||||
query GetApiVersion {
|
||||
api {
|
||||
version
|
||||
}
|
||||
}
|
||||
|
||||
query GetApiJobs {
|
||||
jobs {
|
||||
getJobs {
|
||||
createdAt
|
||||
description
|
||||
error
|
||||
finishedAt
|
||||
name
|
||||
progress
|
||||
result
|
||||
status
|
||||
statusText
|
||||
uid
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutation RemoveJob($jobId: String!) {
|
||||
removeJob(jobId: $jobId) {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation RunSystemRebuild {
|
||||
runSystemRebuild {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation RunSystemRollback {
|
||||
runSystemRollback {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation RunSystemUpgrade {
|
||||
runSystemUpgrade {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation PullRepositoryChanges {
|
||||
pullRepositoryChanges {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation RebootSystem {
|
||||
rebootSystem {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
query GetApiTokens {
|
||||
api {
|
||||
devices {
|
||||
creationDate
|
||||
isCaller
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query RecoveryKey {
|
||||
api {
|
||||
recoveryKey {
|
||||
creationDate
|
||||
exists
|
||||
expirationDate
|
||||
usesLeft
|
||||
valid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutation GetNewRecoveryApiKey($limits: RecoveryKeyLimitsInput) {
|
||||
getNewRecoveryApiKey(limits: $limits) {
|
||||
...basicMutationReturnFields
|
||||
key
|
||||
}
|
||||
}
|
||||
|
||||
mutation UseRecoveryApiKey($input: UseRecoveryKeyInput!) {
|
||||
useRecoveryApiKey(input: $input) {
|
||||
...basicMutationReturnFields
|
||||
token
|
||||
}
|
||||
}
|
||||
|
||||
mutation RefreshDeviceApiToken {
|
||||
refreshDeviceApiToken {
|
||||
...basicMutationReturnFields
|
||||
token
|
||||
}
|
||||
}
|
||||
|
||||
mutation DeleteDeviceApiToken($device: String!) {
|
||||
deleteDeviceApiToken(device: $device) {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation GetNewDeviceApiKey {
|
||||
getNewDeviceApiKey {
|
||||
...basicMutationReturnFields
|
||||
key
|
||||
}
|
||||
}
|
||||
|
||||
mutation InvalidateNewDeviceApiKey {
|
||||
invalidateNewDeviceApiKey {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation AuthorizeWithNewDeviceApiKey($input: UseNewDeviceKeyInput!) {
|
||||
authorizeWithNewDeviceApiKey(input: $input) {
|
||||
...basicMutationReturnFields
|
||||
token
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,745 +0,0 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'server_api.graphql.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Fragment$basicMutationReturnFields _$Fragment$basicMutationReturnFieldsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Fragment$basicMutationReturnFields(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Fragment$basicMutationReturnFieldsToJson(
|
||||
Fragment$basicMutationReturnFields instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$GetApiVersion _$Query$GetApiVersionFromJson(Map<String, dynamic> json) =>
|
||||
Query$GetApiVersion(
|
||||
api:
|
||||
Query$GetApiVersion$api.fromJson(json['api'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$GetApiVersionToJson(
|
||||
Query$GetApiVersion instance) =>
|
||||
<String, dynamic>{
|
||||
'api': instance.api.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$GetApiVersion$api _$Query$GetApiVersion$apiFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$GetApiVersion$api(
|
||||
version: json['version'] as String,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$GetApiVersion$apiToJson(
|
||||
Query$GetApiVersion$api instance) =>
|
||||
<String, dynamic>{
|
||||
'version': instance.version,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$GetApiJobs _$Query$GetApiJobsFromJson(Map<String, dynamic> json) =>
|
||||
Query$GetApiJobs(
|
||||
jobs:
|
||||
Query$GetApiJobs$jobs.fromJson(json['jobs'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$GetApiJobsToJson(Query$GetApiJobs instance) =>
|
||||
<String, dynamic>{
|
||||
'jobs': instance.jobs.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$GetApiJobs$jobs _$Query$GetApiJobs$jobsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$GetApiJobs$jobs(
|
||||
getJobs: (json['getJobs'] as List<dynamic>)
|
||||
.map((e) =>
|
||||
Query$GetApiJobs$jobs$getJobs.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$GetApiJobs$jobsToJson(
|
||||
Query$GetApiJobs$jobs instance) =>
|
||||
<String, dynamic>{
|
||||
'getJobs': instance.getJobs.map((e) => e.toJson()).toList(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$GetApiJobs$jobs$getJobs _$Query$GetApiJobs$jobs$getJobsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$GetApiJobs$jobs$getJobs(
|
||||
createdAt: dateTimeFromJson(json['createdAt']),
|
||||
description: json['description'] as String,
|
||||
error: json['error'] as String?,
|
||||
finishedAt: _nullable$dateTimeFromJson(json['finishedAt']),
|
||||
name: json['name'] as String,
|
||||
progress: json['progress'] as int?,
|
||||
result: json['result'] as String?,
|
||||
status: json['status'] as String,
|
||||
statusText: json['statusText'] as String?,
|
||||
uid: json['uid'] as String,
|
||||
updatedAt: dateTimeFromJson(json['updatedAt']),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$GetApiJobs$jobs$getJobsToJson(
|
||||
Query$GetApiJobs$jobs$getJobs instance) =>
|
||||
<String, dynamic>{
|
||||
'createdAt': dateTimeToJson(instance.createdAt),
|
||||
'description': instance.description,
|
||||
'error': instance.error,
|
||||
'finishedAt': _nullable$dateTimeToJson(instance.finishedAt),
|
||||
'name': instance.name,
|
||||
'progress': instance.progress,
|
||||
'result': instance.result,
|
||||
'status': instance.status,
|
||||
'statusText': instance.statusText,
|
||||
'uid': instance.uid,
|
||||
'updatedAt': dateTimeToJson(instance.updatedAt),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$RemoveJob _$Variables$Mutation$RemoveJobFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$RemoveJob(
|
||||
jobId: json['jobId'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$RemoveJobToJson(
|
||||
Variables$Mutation$RemoveJob instance) =>
|
||||
<String, dynamic>{
|
||||
'jobId': instance.jobId,
|
||||
};
|
||||
|
||||
Mutation$RemoveJob _$Mutation$RemoveJobFromJson(Map<String, dynamic> json) =>
|
||||
Mutation$RemoveJob(
|
||||
removeJob: Mutation$RemoveJob$removeJob.fromJson(
|
||||
json['removeJob'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RemoveJobToJson(Mutation$RemoveJob instance) =>
|
||||
<String, dynamic>{
|
||||
'removeJob': instance.removeJob.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$RemoveJob$removeJob _$Mutation$RemoveJob$removeJobFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RemoveJob$removeJob(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RemoveJob$removeJobToJson(
|
||||
Mutation$RemoveJob$removeJob instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$RunSystemRebuild _$Mutation$RunSystemRebuildFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RunSystemRebuild(
|
||||
runSystemRebuild: Mutation$RunSystemRebuild$runSystemRebuild.fromJson(
|
||||
json['runSystemRebuild'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RunSystemRebuildToJson(
|
||||
Mutation$RunSystemRebuild instance) =>
|
||||
<String, dynamic>{
|
||||
'runSystemRebuild': instance.runSystemRebuild.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$RunSystemRebuild$runSystemRebuild
|
||||
_$Mutation$RunSystemRebuild$runSystemRebuildFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RunSystemRebuild$runSystemRebuild(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RunSystemRebuild$runSystemRebuildToJson(
|
||||
Mutation$RunSystemRebuild$runSystemRebuild instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$RunSystemRollback _$Mutation$RunSystemRollbackFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RunSystemRollback(
|
||||
runSystemRollback: Mutation$RunSystemRollback$runSystemRollback.fromJson(
|
||||
json['runSystemRollback'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RunSystemRollbackToJson(
|
||||
Mutation$RunSystemRollback instance) =>
|
||||
<String, dynamic>{
|
||||
'runSystemRollback': instance.runSystemRollback.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$RunSystemRollback$runSystemRollback
|
||||
_$Mutation$RunSystemRollback$runSystemRollbackFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RunSystemRollback$runSystemRollback(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RunSystemRollback$runSystemRollbackToJson(
|
||||
Mutation$RunSystemRollback$runSystemRollback instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$RunSystemUpgrade _$Mutation$RunSystemUpgradeFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RunSystemUpgrade(
|
||||
runSystemUpgrade: Mutation$RunSystemUpgrade$runSystemUpgrade.fromJson(
|
||||
json['runSystemUpgrade'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RunSystemUpgradeToJson(
|
||||
Mutation$RunSystemUpgrade instance) =>
|
||||
<String, dynamic>{
|
||||
'runSystemUpgrade': instance.runSystemUpgrade.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$RunSystemUpgrade$runSystemUpgrade
|
||||
_$Mutation$RunSystemUpgrade$runSystemUpgradeFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RunSystemUpgrade$runSystemUpgrade(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RunSystemUpgrade$runSystemUpgradeToJson(
|
||||
Mutation$RunSystemUpgrade$runSystemUpgrade instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$PullRepositoryChanges _$Mutation$PullRepositoryChangesFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$PullRepositoryChanges(
|
||||
pullRepositoryChanges:
|
||||
Mutation$PullRepositoryChanges$pullRepositoryChanges.fromJson(
|
||||
json['pullRepositoryChanges'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$PullRepositoryChangesToJson(
|
||||
Mutation$PullRepositoryChanges instance) =>
|
||||
<String, dynamic>{
|
||||
'pullRepositoryChanges': instance.pullRepositoryChanges.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$PullRepositoryChanges$pullRepositoryChanges
|
||||
_$Mutation$PullRepositoryChanges$pullRepositoryChangesFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$PullRepositoryChanges$pullRepositoryChanges(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic>
|
||||
_$Mutation$PullRepositoryChanges$pullRepositoryChangesToJson(
|
||||
Mutation$PullRepositoryChanges$pullRepositoryChanges instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$RebootSystem _$Mutation$RebootSystemFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RebootSystem(
|
||||
rebootSystem: Mutation$RebootSystem$rebootSystem.fromJson(
|
||||
json['rebootSystem'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RebootSystemToJson(
|
||||
Mutation$RebootSystem instance) =>
|
||||
<String, dynamic>{
|
||||
'rebootSystem': instance.rebootSystem.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$RebootSystem$rebootSystem _$Mutation$RebootSystem$rebootSystemFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RebootSystem$rebootSystem(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RebootSystem$rebootSystemToJson(
|
||||
Mutation$RebootSystem$rebootSystem instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$GetApiTokens _$Query$GetApiTokensFromJson(Map<String, dynamic> json) =>
|
||||
Query$GetApiTokens(
|
||||
api: Query$GetApiTokens$api.fromJson(json['api'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$GetApiTokensToJson(Query$GetApiTokens instance) =>
|
||||
<String, dynamic>{
|
||||
'api': instance.api.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$GetApiTokens$api _$Query$GetApiTokens$apiFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$GetApiTokens$api(
|
||||
devices: (json['devices'] as List<dynamic>)
|
||||
.map((e) => Query$GetApiTokens$api$devices.fromJson(
|
||||
e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$GetApiTokens$apiToJson(
|
||||
Query$GetApiTokens$api instance) =>
|
||||
<String, dynamic>{
|
||||
'devices': instance.devices.map((e) => e.toJson()).toList(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$GetApiTokens$api$devices _$Query$GetApiTokens$api$devicesFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$GetApiTokens$api$devices(
|
||||
creationDate: dateTimeFromJson(json['creationDate']),
|
||||
isCaller: json['isCaller'] as bool,
|
||||
name: json['name'] as String,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$GetApiTokens$api$devicesToJson(
|
||||
Query$GetApiTokens$api$devices instance) =>
|
||||
<String, dynamic>{
|
||||
'creationDate': dateTimeToJson(instance.creationDate),
|
||||
'isCaller': instance.isCaller,
|
||||
'name': instance.name,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$RecoveryKey _$Query$RecoveryKeyFromJson(Map<String, dynamic> json) =>
|
||||
Query$RecoveryKey(
|
||||
api: Query$RecoveryKey$api.fromJson(json['api'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$RecoveryKeyToJson(Query$RecoveryKey instance) =>
|
||||
<String, dynamic>{
|
||||
'api': instance.api.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$RecoveryKey$api _$Query$RecoveryKey$apiFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$RecoveryKey$api(
|
||||
recoveryKey: Query$RecoveryKey$api$recoveryKey.fromJson(
|
||||
json['recoveryKey'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$RecoveryKey$apiToJson(
|
||||
Query$RecoveryKey$api instance) =>
|
||||
<String, dynamic>{
|
||||
'recoveryKey': instance.recoveryKey.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$RecoveryKey$api$recoveryKey _$Query$RecoveryKey$api$recoveryKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$RecoveryKey$api$recoveryKey(
|
||||
creationDate: _nullable$dateTimeFromJson(json['creationDate']),
|
||||
exists: json['exists'] as bool,
|
||||
expirationDate: _nullable$dateTimeFromJson(json['expirationDate']),
|
||||
usesLeft: json['usesLeft'] as int?,
|
||||
valid: json['valid'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$RecoveryKey$api$recoveryKeyToJson(
|
||||
Query$RecoveryKey$api$recoveryKey instance) =>
|
||||
<String, dynamic>{
|
||||
'creationDate': _nullable$dateTimeToJson(instance.creationDate),
|
||||
'exists': instance.exists,
|
||||
'expirationDate': _nullable$dateTimeToJson(instance.expirationDate),
|
||||
'usesLeft': instance.usesLeft,
|
||||
'valid': instance.valid,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$GetNewRecoveryApiKey
|
||||
_$Variables$Mutation$GetNewRecoveryApiKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$GetNewRecoveryApiKey(
|
||||
limits: json['limits'] == null
|
||||
? null
|
||||
: Input$RecoveryKeyLimitsInput.fromJson(
|
||||
json['limits'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$GetNewRecoveryApiKeyToJson(
|
||||
Variables$Mutation$GetNewRecoveryApiKey instance) =>
|
||||
<String, dynamic>{
|
||||
'limits': instance.limits?.toJson(),
|
||||
};
|
||||
|
||||
Mutation$GetNewRecoveryApiKey _$Mutation$GetNewRecoveryApiKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$GetNewRecoveryApiKey(
|
||||
getNewRecoveryApiKey:
|
||||
Mutation$GetNewRecoveryApiKey$getNewRecoveryApiKey.fromJson(
|
||||
json['getNewRecoveryApiKey'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$GetNewRecoveryApiKeyToJson(
|
||||
Mutation$GetNewRecoveryApiKey instance) =>
|
||||
<String, dynamic>{
|
||||
'getNewRecoveryApiKey': instance.getNewRecoveryApiKey.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$GetNewRecoveryApiKey$getNewRecoveryApiKey
|
||||
_$Mutation$GetNewRecoveryApiKey$getNewRecoveryApiKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$GetNewRecoveryApiKey$getNewRecoveryApiKey(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
key: json['key'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$GetNewRecoveryApiKey$getNewRecoveryApiKeyToJson(
|
||||
Mutation$GetNewRecoveryApiKey$getNewRecoveryApiKey instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
'key': instance.key,
|
||||
};
|
||||
|
||||
Variables$Mutation$UseRecoveryApiKey
|
||||
_$Variables$Mutation$UseRecoveryApiKeyFromJson(Map<String, dynamic> json) =>
|
||||
Variables$Mutation$UseRecoveryApiKey(
|
||||
input: Input$UseRecoveryKeyInput.fromJson(
|
||||
json['input'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$UseRecoveryApiKeyToJson(
|
||||
Variables$Mutation$UseRecoveryApiKey instance) =>
|
||||
<String, dynamic>{
|
||||
'input': instance.input.toJson(),
|
||||
};
|
||||
|
||||
Mutation$UseRecoveryApiKey _$Mutation$UseRecoveryApiKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$UseRecoveryApiKey(
|
||||
useRecoveryApiKey: Mutation$UseRecoveryApiKey$useRecoveryApiKey.fromJson(
|
||||
json['useRecoveryApiKey'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$UseRecoveryApiKeyToJson(
|
||||
Mutation$UseRecoveryApiKey instance) =>
|
||||
<String, dynamic>{
|
||||
'useRecoveryApiKey': instance.useRecoveryApiKey.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$UseRecoveryApiKey$useRecoveryApiKey
|
||||
_$Mutation$UseRecoveryApiKey$useRecoveryApiKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$UseRecoveryApiKey$useRecoveryApiKey(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
token: json['token'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$UseRecoveryApiKey$useRecoveryApiKeyToJson(
|
||||
Mutation$UseRecoveryApiKey$useRecoveryApiKey instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
'token': instance.token,
|
||||
};
|
||||
|
||||
Mutation$RefreshDeviceApiToken _$Mutation$RefreshDeviceApiTokenFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RefreshDeviceApiToken(
|
||||
refreshDeviceApiToken:
|
||||
Mutation$RefreshDeviceApiToken$refreshDeviceApiToken.fromJson(
|
||||
json['refreshDeviceApiToken'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RefreshDeviceApiTokenToJson(
|
||||
Mutation$RefreshDeviceApiToken instance) =>
|
||||
<String, dynamic>{
|
||||
'refreshDeviceApiToken': instance.refreshDeviceApiToken.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$RefreshDeviceApiToken$refreshDeviceApiToken
|
||||
_$Mutation$RefreshDeviceApiToken$refreshDeviceApiTokenFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RefreshDeviceApiToken$refreshDeviceApiToken(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
token: json['token'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic>
|
||||
_$Mutation$RefreshDeviceApiToken$refreshDeviceApiTokenToJson(
|
||||
Mutation$RefreshDeviceApiToken$refreshDeviceApiToken instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
'token': instance.token,
|
||||
};
|
||||
|
||||
Variables$Mutation$DeleteDeviceApiToken
|
||||
_$Variables$Mutation$DeleteDeviceApiTokenFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$DeleteDeviceApiToken(
|
||||
device: json['device'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$DeleteDeviceApiTokenToJson(
|
||||
Variables$Mutation$DeleteDeviceApiToken instance) =>
|
||||
<String, dynamic>{
|
||||
'device': instance.device,
|
||||
};
|
||||
|
||||
Mutation$DeleteDeviceApiToken _$Mutation$DeleteDeviceApiTokenFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$DeleteDeviceApiToken(
|
||||
deleteDeviceApiToken:
|
||||
Mutation$DeleteDeviceApiToken$deleteDeviceApiToken.fromJson(
|
||||
json['deleteDeviceApiToken'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$DeleteDeviceApiTokenToJson(
|
||||
Mutation$DeleteDeviceApiToken instance) =>
|
||||
<String, dynamic>{
|
||||
'deleteDeviceApiToken': instance.deleteDeviceApiToken.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$DeleteDeviceApiToken$deleteDeviceApiToken
|
||||
_$Mutation$DeleteDeviceApiToken$deleteDeviceApiTokenFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$DeleteDeviceApiToken$deleteDeviceApiToken(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$DeleteDeviceApiToken$deleteDeviceApiTokenToJson(
|
||||
Mutation$DeleteDeviceApiToken$deleteDeviceApiToken instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$GetNewDeviceApiKey _$Mutation$GetNewDeviceApiKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$GetNewDeviceApiKey(
|
||||
getNewDeviceApiKey:
|
||||
Mutation$GetNewDeviceApiKey$getNewDeviceApiKey.fromJson(
|
||||
json['getNewDeviceApiKey'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$GetNewDeviceApiKeyToJson(
|
||||
Mutation$GetNewDeviceApiKey instance) =>
|
||||
<String, dynamic>{
|
||||
'getNewDeviceApiKey': instance.getNewDeviceApiKey.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$GetNewDeviceApiKey$getNewDeviceApiKey
|
||||
_$Mutation$GetNewDeviceApiKey$getNewDeviceApiKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$GetNewDeviceApiKey$getNewDeviceApiKey(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
key: json['key'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$GetNewDeviceApiKey$getNewDeviceApiKeyToJson(
|
||||
Mutation$GetNewDeviceApiKey$getNewDeviceApiKey instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
'key': instance.key,
|
||||
};
|
||||
|
||||
Mutation$InvalidateNewDeviceApiKey _$Mutation$InvalidateNewDeviceApiKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$InvalidateNewDeviceApiKey(
|
||||
invalidateNewDeviceApiKey:
|
||||
Mutation$InvalidateNewDeviceApiKey$invalidateNewDeviceApiKey.fromJson(
|
||||
json['invalidateNewDeviceApiKey'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$InvalidateNewDeviceApiKeyToJson(
|
||||
Mutation$InvalidateNewDeviceApiKey instance) =>
|
||||
<String, dynamic>{
|
||||
'invalidateNewDeviceApiKey': instance.invalidateNewDeviceApiKey.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$InvalidateNewDeviceApiKey$invalidateNewDeviceApiKey
|
||||
_$Mutation$InvalidateNewDeviceApiKey$invalidateNewDeviceApiKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$InvalidateNewDeviceApiKey$invalidateNewDeviceApiKey(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic>
|
||||
_$Mutation$InvalidateNewDeviceApiKey$invalidateNewDeviceApiKeyToJson(
|
||||
Mutation$InvalidateNewDeviceApiKey$invalidateNewDeviceApiKey
|
||||
instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$AuthorizeWithNewDeviceApiKey
|
||||
_$Variables$Mutation$AuthorizeWithNewDeviceApiKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$AuthorizeWithNewDeviceApiKey(
|
||||
input: Input$UseNewDeviceKeyInput.fromJson(
|
||||
json['input'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$AuthorizeWithNewDeviceApiKeyToJson(
|
||||
Variables$Mutation$AuthorizeWithNewDeviceApiKey instance) =>
|
||||
<String, dynamic>{
|
||||
'input': instance.input.toJson(),
|
||||
};
|
||||
|
||||
Mutation$AuthorizeWithNewDeviceApiKey
|
||||
_$Mutation$AuthorizeWithNewDeviceApiKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$AuthorizeWithNewDeviceApiKey(
|
||||
authorizeWithNewDeviceApiKey:
|
||||
Mutation$AuthorizeWithNewDeviceApiKey$authorizeWithNewDeviceApiKey
|
||||
.fromJson(json['authorizeWithNewDeviceApiKey']
|
||||
as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$AuthorizeWithNewDeviceApiKeyToJson(
|
||||
Mutation$AuthorizeWithNewDeviceApiKey instance) =>
|
||||
<String, dynamic>{
|
||||
'authorizeWithNewDeviceApiKey':
|
||||
instance.authorizeWithNewDeviceApiKey.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$AuthorizeWithNewDeviceApiKey$authorizeWithNewDeviceApiKey
|
||||
_$Mutation$AuthorizeWithNewDeviceApiKey$authorizeWithNewDeviceApiKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$AuthorizeWithNewDeviceApiKey$authorizeWithNewDeviceApiKey(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
token: json['token'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic>
|
||||
_$Mutation$AuthorizeWithNewDeviceApiKey$authorizeWithNewDeviceApiKeyToJson(
|
||||
Mutation$AuthorizeWithNewDeviceApiKey$authorizeWithNewDeviceApiKey
|
||||
instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
'token': instance.token,
|
||||
};
|
|
@ -1,54 +0,0 @@
|
|||
fragment basicMutationReturnFields on MutationReturnInterface{
|
||||
code
|
||||
message
|
||||
success
|
||||
}
|
||||
|
||||
query SystemSettings {
|
||||
system {
|
||||
settings {
|
||||
autoUpgrade {
|
||||
allowReboot
|
||||
enable
|
||||
}
|
||||
ssh {
|
||||
enable
|
||||
passwordAuthentication
|
||||
rootSshKeys
|
||||
}
|
||||
timezone
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query DomainInfo {
|
||||
system {
|
||||
domainInfo {
|
||||
domain
|
||||
hostname
|
||||
provider
|
||||
requiredDnsRecords {
|
||||
content
|
||||
name
|
||||
priority
|
||||
recordType
|
||||
ttl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutation ChangeTimezone($timezone: String!) {
|
||||
changeTimezone(timezone: $timezone) {
|
||||
...basicMutationReturnFields
|
||||
timezone
|
||||
}
|
||||
}
|
||||
|
||||
mutation ChangeAutoUpgradeSettings($settings: AutoUpgradeSettingsInput!) {
|
||||
changeAutoUpgradeSettings(settings: $settings) {
|
||||
...basicMutationReturnFields
|
||||
allowReboot
|
||||
enableAutoUpgrade
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,300 +0,0 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'server_settings.graphql.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Fragment$basicMutationReturnFields _$Fragment$basicMutationReturnFieldsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Fragment$basicMutationReturnFields(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Fragment$basicMutationReturnFieldsToJson(
|
||||
Fragment$basicMutationReturnFields instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$SystemSettings _$Query$SystemSettingsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$SystemSettings(
|
||||
system: Query$SystemSettings$system.fromJson(
|
||||
json['system'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$SystemSettingsToJson(
|
||||
Query$SystemSettings instance) =>
|
||||
<String, dynamic>{
|
||||
'system': instance.system.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$SystemSettings$system _$Query$SystemSettings$systemFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$SystemSettings$system(
|
||||
settings: Query$SystemSettings$system$settings.fromJson(
|
||||
json['settings'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$SystemSettings$systemToJson(
|
||||
Query$SystemSettings$system instance) =>
|
||||
<String, dynamic>{
|
||||
'settings': instance.settings.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$SystemSettings$system$settings
|
||||
_$Query$SystemSettings$system$settingsFromJson(Map<String, dynamic> json) =>
|
||||
Query$SystemSettings$system$settings(
|
||||
autoUpgrade:
|
||||
Query$SystemSettings$system$settings$autoUpgrade.fromJson(
|
||||
json['autoUpgrade'] as Map<String, dynamic>),
|
||||
ssh: Query$SystemSettings$system$settings$ssh.fromJson(
|
||||
json['ssh'] as Map<String, dynamic>),
|
||||
timezone: json['timezone'] as String,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$SystemSettings$system$settingsToJson(
|
||||
Query$SystemSettings$system$settings instance) =>
|
||||
<String, dynamic>{
|
||||
'autoUpgrade': instance.autoUpgrade.toJson(),
|
||||
'ssh': instance.ssh.toJson(),
|
||||
'timezone': instance.timezone,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$SystemSettings$system$settings$autoUpgrade
|
||||
_$Query$SystemSettings$system$settings$autoUpgradeFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$SystemSettings$system$settings$autoUpgrade(
|
||||
allowReboot: json['allowReboot'] as bool,
|
||||
enable: json['enable'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$SystemSettings$system$settings$autoUpgradeToJson(
|
||||
Query$SystemSettings$system$settings$autoUpgrade instance) =>
|
||||
<String, dynamic>{
|
||||
'allowReboot': instance.allowReboot,
|
||||
'enable': instance.enable,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$SystemSettings$system$settings$ssh
|
||||
_$Query$SystemSettings$system$settings$sshFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$SystemSettings$system$settings$ssh(
|
||||
enable: json['enable'] as bool,
|
||||
passwordAuthentication: json['passwordAuthentication'] as bool,
|
||||
rootSshKeys: (json['rootSshKeys'] as List<dynamic>)
|
||||
.map((e) => e as String)
|
||||
.toList(),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$SystemSettings$system$settings$sshToJson(
|
||||
Query$SystemSettings$system$settings$ssh instance) =>
|
||||
<String, dynamic>{
|
||||
'enable': instance.enable,
|
||||
'passwordAuthentication': instance.passwordAuthentication,
|
||||
'rootSshKeys': instance.rootSshKeys,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$DomainInfo _$Query$DomainInfoFromJson(Map<String, dynamic> json) =>
|
||||
Query$DomainInfo(
|
||||
system: Query$DomainInfo$system.fromJson(
|
||||
json['system'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$DomainInfoToJson(Query$DomainInfo instance) =>
|
||||
<String, dynamic>{
|
||||
'system': instance.system.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$DomainInfo$system _$Query$DomainInfo$systemFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$DomainInfo$system(
|
||||
domainInfo: Query$DomainInfo$system$domainInfo.fromJson(
|
||||
json['domainInfo'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$DomainInfo$systemToJson(
|
||||
Query$DomainInfo$system instance) =>
|
||||
<String, dynamic>{
|
||||
'domainInfo': instance.domainInfo.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$DomainInfo$system$domainInfo _$Query$DomainInfo$system$domainInfoFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$DomainInfo$system$domainInfo(
|
||||
domain: json['domain'] as String,
|
||||
hostname: json['hostname'] as String,
|
||||
provider: $enumDecode(_$Enum$DnsProviderEnumMap, json['provider'],
|
||||
unknownValue: Enum$DnsProvider.$unknown),
|
||||
requiredDnsRecords: (json['requiredDnsRecords'] as List<dynamic>)
|
||||
.map((e) =>
|
||||
Query$DomainInfo$system$domainInfo$requiredDnsRecords.fromJson(
|
||||
e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$DomainInfo$system$domainInfoToJson(
|
||||
Query$DomainInfo$system$domainInfo instance) =>
|
||||
<String, dynamic>{
|
||||
'domain': instance.domain,
|
||||
'hostname': instance.hostname,
|
||||
'provider': _$Enum$DnsProviderEnumMap[instance.provider],
|
||||
'requiredDnsRecords':
|
||||
instance.requiredDnsRecords.map((e) => e.toJson()).toList(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
const _$Enum$DnsProviderEnumMap = {
|
||||
Enum$DnsProvider.CLOUDFLARE: 'CLOUDFLARE',
|
||||
Enum$DnsProvider.$unknown: r'$unknown',
|
||||
};
|
||||
|
||||
Query$DomainInfo$system$domainInfo$requiredDnsRecords
|
||||
_$Query$DomainInfo$system$domainInfo$requiredDnsRecordsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$DomainInfo$system$domainInfo$requiredDnsRecords(
|
||||
content: json['content'] as String,
|
||||
name: json['name'] as String,
|
||||
priority: json['priority'] as int?,
|
||||
recordType: json['recordType'] as String,
|
||||
ttl: json['ttl'] as int,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic>
|
||||
_$Query$DomainInfo$system$domainInfo$requiredDnsRecordsToJson(
|
||||
Query$DomainInfo$system$domainInfo$requiredDnsRecords instance) =>
|
||||
<String, dynamic>{
|
||||
'content': instance.content,
|
||||
'name': instance.name,
|
||||
'priority': instance.priority,
|
||||
'recordType': instance.recordType,
|
||||
'ttl': instance.ttl,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$ChangeTimezone _$Variables$Mutation$ChangeTimezoneFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$ChangeTimezone(
|
||||
timezone: json['timezone'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$ChangeTimezoneToJson(
|
||||
Variables$Mutation$ChangeTimezone instance) =>
|
||||
<String, dynamic>{
|
||||
'timezone': instance.timezone,
|
||||
};
|
||||
|
||||
Mutation$ChangeTimezone _$Mutation$ChangeTimezoneFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$ChangeTimezone(
|
||||
changeTimezone: Mutation$ChangeTimezone$changeTimezone.fromJson(
|
||||
json['changeTimezone'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$ChangeTimezoneToJson(
|
||||
Mutation$ChangeTimezone instance) =>
|
||||
<String, dynamic>{
|
||||
'changeTimezone': instance.changeTimezone.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$ChangeTimezone$changeTimezone
|
||||
_$Mutation$ChangeTimezone$changeTimezoneFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$ChangeTimezone$changeTimezone(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
timezone: json['timezone'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$ChangeTimezone$changeTimezoneToJson(
|
||||
Mutation$ChangeTimezone$changeTimezone instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
'timezone': instance.timezone,
|
||||
};
|
||||
|
||||
Variables$Mutation$ChangeAutoUpgradeSettings
|
||||
_$Variables$Mutation$ChangeAutoUpgradeSettingsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$ChangeAutoUpgradeSettings(
|
||||
settings: Input$AutoUpgradeSettingsInput.fromJson(
|
||||
json['settings'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$ChangeAutoUpgradeSettingsToJson(
|
||||
Variables$Mutation$ChangeAutoUpgradeSettings instance) =>
|
||||
<String, dynamic>{
|
||||
'settings': instance.settings.toJson(),
|
||||
};
|
||||
|
||||
Mutation$ChangeAutoUpgradeSettings _$Mutation$ChangeAutoUpgradeSettingsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$ChangeAutoUpgradeSettings(
|
||||
changeAutoUpgradeSettings:
|
||||
Mutation$ChangeAutoUpgradeSettings$changeAutoUpgradeSettings.fromJson(
|
||||
json['changeAutoUpgradeSettings'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$ChangeAutoUpgradeSettingsToJson(
|
||||
Mutation$ChangeAutoUpgradeSettings instance) =>
|
||||
<String, dynamic>{
|
||||
'changeAutoUpgradeSettings': instance.changeAutoUpgradeSettings.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$ChangeAutoUpgradeSettings$changeAutoUpgradeSettings
|
||||
_$Mutation$ChangeAutoUpgradeSettings$changeAutoUpgradeSettingsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$ChangeAutoUpgradeSettings$changeAutoUpgradeSettings(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
allowReboot: json['allowReboot'] as bool,
|
||||
enableAutoUpgrade: json['enableAutoUpgrade'] as bool,
|
||||
);
|
||||
|
||||
Map<String, dynamic>
|
||||
_$Mutation$ChangeAutoUpgradeSettings$changeAutoUpgradeSettingsToJson(
|
||||
Mutation$ChangeAutoUpgradeSettings$changeAutoUpgradeSettings
|
||||
instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
'allowReboot': instance.allowReboot,
|
||||
'enableAutoUpgrade': instance.enableAutoUpgrade,
|
||||
};
|
|
@ -1,84 +0,0 @@
|
|||
fragment basicMutationReturnFields on MutationReturnInterface{
|
||||
code
|
||||
message
|
||||
success
|
||||
}
|
||||
|
||||
query AllServices {
|
||||
services {
|
||||
allServices {
|
||||
description
|
||||
displayName
|
||||
dnsRecords {
|
||||
content
|
||||
name
|
||||
priority
|
||||
recordType
|
||||
ttl
|
||||
}
|
||||
id
|
||||
isEnabled
|
||||
isMovable
|
||||
isRequired
|
||||
status
|
||||
storageUsage {
|
||||
title
|
||||
usedSpace
|
||||
volume {
|
||||
name
|
||||
}
|
||||
}
|
||||
svgIcon
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutation EnableService($serviceId: String!) {
|
||||
enableService(serviceId: $serviceId) {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation DisableService($serviceId: String!) {
|
||||
disableService(serviceId: $serviceId) {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation StopService($serviceId: String!) {
|
||||
stopService(serviceId: $serviceId) {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation StartService($serviceId: String!) {
|
||||
startService(serviceId: $serviceId) {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation RestartService($serviceId: String!) {
|
||||
restartService(serviceId: $serviceId) {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation MoveService($input: MoveServiceInput!) {
|
||||
moveService(input: $input) {
|
||||
...basicMutationReturnFields
|
||||
job {
|
||||
createdAt
|
||||
description
|
||||
error
|
||||
finishedAt
|
||||
name
|
||||
progress
|
||||
result
|
||||
status
|
||||
statusText
|
||||
uid
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,482 +0,0 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'services.graphql.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Fragment$basicMutationReturnFields _$Fragment$basicMutationReturnFieldsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Fragment$basicMutationReturnFields(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Fragment$basicMutationReturnFieldsToJson(
|
||||
Fragment$basicMutationReturnFields instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$AllServices _$Query$AllServicesFromJson(Map<String, dynamic> json) =>
|
||||
Query$AllServices(
|
||||
services: Query$AllServices$services.fromJson(
|
||||
json['services'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$AllServicesToJson(Query$AllServices instance) =>
|
||||
<String, dynamic>{
|
||||
'services': instance.services.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$AllServices$services _$Query$AllServices$servicesFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$AllServices$services(
|
||||
allServices: (json['allServices'] as List<dynamic>)
|
||||
.map((e) => Query$AllServices$services$allServices.fromJson(
|
||||
e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$AllServices$servicesToJson(
|
||||
Query$AllServices$services instance) =>
|
||||
<String, dynamic>{
|
||||
'allServices': instance.allServices.map((e) => e.toJson()).toList(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$AllServices$services$allServices
|
||||
_$Query$AllServices$services$allServicesFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$AllServices$services$allServices(
|
||||
description: json['description'] as String,
|
||||
displayName: json['displayName'] as String,
|
||||
dnsRecords: (json['dnsRecords'] as List<dynamic>?)
|
||||
?.map((e) =>
|
||||
Query$AllServices$services$allServices$dnsRecords.fromJson(
|
||||
e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
id: json['id'] as String,
|
||||
isEnabled: json['isEnabled'] as bool,
|
||||
isMovable: json['isMovable'] as bool,
|
||||
isRequired: json['isRequired'] as bool,
|
||||
status: $enumDecode(_$Enum$ServiceStatusEnumEnumMap, json['status'],
|
||||
unknownValue: Enum$ServiceStatusEnum.$unknown),
|
||||
storageUsage:
|
||||
Query$AllServices$services$allServices$storageUsage.fromJson(
|
||||
json['storageUsage'] as Map<String, dynamic>),
|
||||
svgIcon: json['svgIcon'] as String,
|
||||
url: json['url'] as String?,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$AllServices$services$allServicesToJson(
|
||||
Query$AllServices$services$allServices instance) =>
|
||||
<String, dynamic>{
|
||||
'description': instance.description,
|
||||
'displayName': instance.displayName,
|
||||
'dnsRecords': instance.dnsRecords?.map((e) => e.toJson()).toList(),
|
||||
'id': instance.id,
|
||||
'isEnabled': instance.isEnabled,
|
||||
'isMovable': instance.isMovable,
|
||||
'isRequired': instance.isRequired,
|
||||
'status': _$Enum$ServiceStatusEnumEnumMap[instance.status],
|
||||
'storageUsage': instance.storageUsage.toJson(),
|
||||
'svgIcon': instance.svgIcon,
|
||||
'url': instance.url,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
const _$Enum$ServiceStatusEnumEnumMap = {
|
||||
Enum$ServiceStatusEnum.ACTIVATING: 'ACTIVATING',
|
||||
Enum$ServiceStatusEnum.ACTIVE: 'ACTIVE',
|
||||
Enum$ServiceStatusEnum.DEACTIVATING: 'DEACTIVATING',
|
||||
Enum$ServiceStatusEnum.FAILED: 'FAILED',
|
||||
Enum$ServiceStatusEnum.INACTIVE: 'INACTIVE',
|
||||
Enum$ServiceStatusEnum.OFF: 'OFF',
|
||||
Enum$ServiceStatusEnum.RELOADING: 'RELOADING',
|
||||
Enum$ServiceStatusEnum.$unknown: r'$unknown',
|
||||
};
|
||||
|
||||
Query$AllServices$services$allServices$dnsRecords
|
||||
_$Query$AllServices$services$allServices$dnsRecordsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$AllServices$services$allServices$dnsRecords(
|
||||
content: json['content'] as String,
|
||||
name: json['name'] as String,
|
||||
priority: json['priority'] as int?,
|
||||
recordType: json['recordType'] as String,
|
||||
ttl: json['ttl'] as int,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$AllServices$services$allServices$dnsRecordsToJson(
|
||||
Query$AllServices$services$allServices$dnsRecords instance) =>
|
||||
<String, dynamic>{
|
||||
'content': instance.content,
|
||||
'name': instance.name,
|
||||
'priority': instance.priority,
|
||||
'recordType': instance.recordType,
|
||||
'ttl': instance.ttl,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$AllServices$services$allServices$storageUsage
|
||||
_$Query$AllServices$services$allServices$storageUsageFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$AllServices$services$allServices$storageUsage(
|
||||
title: json['title'] as String,
|
||||
usedSpace: json['usedSpace'] as String,
|
||||
volume: json['volume'] == null
|
||||
? null
|
||||
: Query$AllServices$services$allServices$storageUsage$volume
|
||||
.fromJson(json['volume'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic>
|
||||
_$Query$AllServices$services$allServices$storageUsageToJson(
|
||||
Query$AllServices$services$allServices$storageUsage instance) =>
|
||||
<String, dynamic>{
|
||||
'title': instance.title,
|
||||
'usedSpace': instance.usedSpace,
|
||||
'volume': instance.volume?.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$AllServices$services$allServices$storageUsage$volume
|
||||
_$Query$AllServices$services$allServices$storageUsage$volumeFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$AllServices$services$allServices$storageUsage$volume(
|
||||
name: json['name'] as String,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String,
|
||||
dynamic> _$Query$AllServices$services$allServices$storageUsage$volumeToJson(
|
||||
Query$AllServices$services$allServices$storageUsage$volume instance) =>
|
||||
<String, dynamic>{
|
||||
'name': instance.name,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$EnableService _$Variables$Mutation$EnableServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$EnableService(
|
||||
serviceId: json['serviceId'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$EnableServiceToJson(
|
||||
Variables$Mutation$EnableService instance) =>
|
||||
<String, dynamic>{
|
||||
'serviceId': instance.serviceId,
|
||||
};
|
||||
|
||||
Mutation$EnableService _$Mutation$EnableServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$EnableService(
|
||||
enableService: Mutation$EnableService$enableService.fromJson(
|
||||
json['enableService'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$EnableServiceToJson(
|
||||
Mutation$EnableService instance) =>
|
||||
<String, dynamic>{
|
||||
'enableService': instance.enableService.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$EnableService$enableService
|
||||
_$Mutation$EnableService$enableServiceFromJson(Map<String, dynamic> json) =>
|
||||
Mutation$EnableService$enableService(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$EnableService$enableServiceToJson(
|
||||
Mutation$EnableService$enableService instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$DisableService _$Variables$Mutation$DisableServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$DisableService(
|
||||
serviceId: json['serviceId'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$DisableServiceToJson(
|
||||
Variables$Mutation$DisableService instance) =>
|
||||
<String, dynamic>{
|
||||
'serviceId': instance.serviceId,
|
||||
};
|
||||
|
||||
Mutation$DisableService _$Mutation$DisableServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$DisableService(
|
||||
disableService: Mutation$DisableService$disableService.fromJson(
|
||||
json['disableService'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$DisableServiceToJson(
|
||||
Mutation$DisableService instance) =>
|
||||
<String, dynamic>{
|
||||
'disableService': instance.disableService.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$DisableService$disableService
|
||||
_$Mutation$DisableService$disableServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$DisableService$disableService(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$DisableService$disableServiceToJson(
|
||||
Mutation$DisableService$disableService instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$StopService _$Variables$Mutation$StopServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$StopService(
|
||||
serviceId: json['serviceId'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$StopServiceToJson(
|
||||
Variables$Mutation$StopService instance) =>
|
||||
<String, dynamic>{
|
||||
'serviceId': instance.serviceId,
|
||||
};
|
||||
|
||||
Mutation$StopService _$Mutation$StopServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$StopService(
|
||||
stopService: Mutation$StopService$stopService.fromJson(
|
||||
json['stopService'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$StopServiceToJson(
|
||||
Mutation$StopService instance) =>
|
||||
<String, dynamic>{
|
||||
'stopService': instance.stopService.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$StopService$stopService _$Mutation$StopService$stopServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$StopService$stopService(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$StopService$stopServiceToJson(
|
||||
Mutation$StopService$stopService instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$StartService _$Variables$Mutation$StartServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$StartService(
|
||||
serviceId: json['serviceId'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$StartServiceToJson(
|
||||
Variables$Mutation$StartService instance) =>
|
||||
<String, dynamic>{
|
||||
'serviceId': instance.serviceId,
|
||||
};
|
||||
|
||||
Mutation$StartService _$Mutation$StartServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$StartService(
|
||||
startService: Mutation$StartService$startService.fromJson(
|
||||
json['startService'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$StartServiceToJson(
|
||||
Mutation$StartService instance) =>
|
||||
<String, dynamic>{
|
||||
'startService': instance.startService.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$StartService$startService _$Mutation$StartService$startServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$StartService$startService(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$StartService$startServiceToJson(
|
||||
Mutation$StartService$startService instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$RestartService _$Variables$Mutation$RestartServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$RestartService(
|
||||
serviceId: json['serviceId'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$RestartServiceToJson(
|
||||
Variables$Mutation$RestartService instance) =>
|
||||
<String, dynamic>{
|
||||
'serviceId': instance.serviceId,
|
||||
};
|
||||
|
||||
Mutation$RestartService _$Mutation$RestartServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RestartService(
|
||||
restartService: Mutation$RestartService$restartService.fromJson(
|
||||
json['restartService'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RestartServiceToJson(
|
||||
Mutation$RestartService instance) =>
|
||||
<String, dynamic>{
|
||||
'restartService': instance.restartService.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$RestartService$restartService
|
||||
_$Mutation$RestartService$restartServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RestartService$restartService(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RestartService$restartServiceToJson(
|
||||
Mutation$RestartService$restartService instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$MoveService _$Variables$Mutation$MoveServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$MoveService(
|
||||
input: Input$MoveServiceInput.fromJson(
|
||||
json['input'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$MoveServiceToJson(
|
||||
Variables$Mutation$MoveService instance) =>
|
||||
<String, dynamic>{
|
||||
'input': instance.input.toJson(),
|
||||
};
|
||||
|
||||
Mutation$MoveService _$Mutation$MoveServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$MoveService(
|
||||
moveService: Mutation$MoveService$moveService.fromJson(
|
||||
json['moveService'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$MoveServiceToJson(
|
||||
Mutation$MoveService instance) =>
|
||||
<String, dynamic>{
|
||||
'moveService': instance.moveService.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$MoveService$moveService _$Mutation$MoveService$moveServiceFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$MoveService$moveService(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
job: json['job'] == null
|
||||
? null
|
||||
: Mutation$MoveService$moveService$job.fromJson(
|
||||
json['job'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$MoveService$moveServiceToJson(
|
||||
Mutation$MoveService$moveService instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
'job': instance.job?.toJson(),
|
||||
};
|
||||
|
||||
Mutation$MoveService$moveService$job
|
||||
_$Mutation$MoveService$moveService$jobFromJson(Map<String, dynamic> json) =>
|
||||
Mutation$MoveService$moveService$job(
|
||||
createdAt: dateTimeFromJson(json['createdAt']),
|
||||
description: json['description'] as String,
|
||||
error: json['error'] as String?,
|
||||
finishedAt: _nullable$dateTimeFromJson(json['finishedAt']),
|
||||
name: json['name'] as String,
|
||||
progress: json['progress'] as int?,
|
||||
result: json['result'] as String?,
|
||||
status: json['status'] as String,
|
||||
statusText: json['statusText'] as String?,
|
||||
uid: json['uid'] as String,
|
||||
updatedAt: dateTimeFromJson(json['updatedAt']),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$MoveService$moveService$jobToJson(
|
||||
Mutation$MoveService$moveService$job instance) =>
|
||||
<String, dynamic>{
|
||||
'createdAt': dateTimeToJson(instance.createdAt),
|
||||
'description': instance.description,
|
||||
'error': instance.error,
|
||||
'finishedAt': _nullable$dateTimeToJson(instance.finishedAt),
|
||||
'name': instance.name,
|
||||
'progress': instance.progress,
|
||||
'result': instance.result,
|
||||
'status': instance.status,
|
||||
'statusText': instance.statusText,
|
||||
'uid': instance.uid,
|
||||
'updatedAt': dateTimeToJson(instance.updatedAt),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
|
@ -1,76 +0,0 @@
|
|||
fragment basicMutationReturnFields on MutationReturnInterface{
|
||||
code
|
||||
message
|
||||
success
|
||||
}
|
||||
|
||||
|
||||
mutation CreateUser($user: UserMutationInput!) {
|
||||
createUser(user: $user) {
|
||||
...basicMutationReturnFields
|
||||
user {
|
||||
username
|
||||
userType
|
||||
sshKeys
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query AllUsers {
|
||||
users {
|
||||
allUsers {
|
||||
userType
|
||||
username
|
||||
sshKeys
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutation AddSshKey($sshInput: SshMutationInput!) {
|
||||
addSshKey(sshInput: $sshInput) {
|
||||
...basicMutationReturnFields
|
||||
user {
|
||||
sshKeys
|
||||
userType
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query GetUser($username: String!) {
|
||||
users {
|
||||
getUser(username: $username) {
|
||||
sshKeys
|
||||
userType
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutation RemoveSshKey($sshInput: SshMutationInput!) {
|
||||
removeSshKey(sshInput: $sshInput) {
|
||||
...basicMutationReturnFields
|
||||
user {
|
||||
sshKeys
|
||||
userType
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutation DeleteUser($username: String!) {
|
||||
deleteUser(username: $username) {
|
||||
...basicMutationReturnFields
|
||||
}
|
||||
}
|
||||
|
||||
mutation UpdateUser($user: UserMutationInput!) {
|
||||
updateUser(user: $user) {
|
||||
...basicMutationReturnFields
|
||||
user {
|
||||
sshKeys
|
||||
userType
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,471 +0,0 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'users.graphql.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Fragment$basicMutationReturnFields _$Fragment$basicMutationReturnFieldsFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Fragment$basicMutationReturnFields(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Fragment$basicMutationReturnFieldsToJson(
|
||||
Fragment$basicMutationReturnFields instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$CreateUser _$Variables$Mutation$CreateUserFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$CreateUser(
|
||||
user: Input$UserMutationInput.fromJson(
|
||||
json['user'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$CreateUserToJson(
|
||||
Variables$Mutation$CreateUser instance) =>
|
||||
<String, dynamic>{
|
||||
'user': instance.user.toJson(),
|
||||
};
|
||||
|
||||
Mutation$CreateUser _$Mutation$CreateUserFromJson(Map<String, dynamic> json) =>
|
||||
Mutation$CreateUser(
|
||||
createUser: Mutation$CreateUser$createUser.fromJson(
|
||||
json['createUser'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$CreateUserToJson(
|
||||
Mutation$CreateUser instance) =>
|
||||
<String, dynamic>{
|
||||
'createUser': instance.createUser.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$CreateUser$createUser _$Mutation$CreateUser$createUserFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$CreateUser$createUser(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: Mutation$CreateUser$createUser$user.fromJson(
|
||||
json['user'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$CreateUser$createUserToJson(
|
||||
Mutation$CreateUser$createUser instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
'user': instance.user?.toJson(),
|
||||
};
|
||||
|
||||
Mutation$CreateUser$createUser$user
|
||||
_$Mutation$CreateUser$createUser$userFromJson(Map<String, dynamic> json) =>
|
||||
Mutation$CreateUser$createUser$user(
|
||||
username: json['username'] as String,
|
||||
userType: $enumDecode(_$Enum$UserTypeEnumMap, json['userType'],
|
||||
unknownValue: Enum$UserType.$unknown),
|
||||
sshKeys: (json['sshKeys'] as List<dynamic>)
|
||||
.map((e) => e as String)
|
||||
.toList(),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$CreateUser$createUser$userToJson(
|
||||
Mutation$CreateUser$createUser$user instance) =>
|
||||
<String, dynamic>{
|
||||
'username': instance.username,
|
||||
'userType': _$Enum$UserTypeEnumMap[instance.userType],
|
||||
'sshKeys': instance.sshKeys,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
const _$Enum$UserTypeEnumMap = {
|
||||
Enum$UserType.NORMAL: 'NORMAL',
|
||||
Enum$UserType.PRIMARY: 'PRIMARY',
|
||||
Enum$UserType.ROOT: 'ROOT',
|
||||
Enum$UserType.$unknown: r'$unknown',
|
||||
};
|
||||
|
||||
Query$AllUsers _$Query$AllUsersFromJson(Map<String, dynamic> json) =>
|
||||
Query$AllUsers(
|
||||
users:
|
||||
Query$AllUsers$users.fromJson(json['users'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$AllUsersToJson(Query$AllUsers instance) =>
|
||||
<String, dynamic>{
|
||||
'users': instance.users.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$AllUsers$users _$Query$AllUsers$usersFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$AllUsers$users(
|
||||
allUsers: (json['allUsers'] as List<dynamic>)
|
||||
.map((e) =>
|
||||
Query$AllUsers$users$allUsers.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$AllUsers$usersToJson(
|
||||
Query$AllUsers$users instance) =>
|
||||
<String, dynamic>{
|
||||
'allUsers': instance.allUsers.map((e) => e.toJson()).toList(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$AllUsers$users$allUsers _$Query$AllUsers$users$allUsersFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$AllUsers$users$allUsers(
|
||||
userType: $enumDecode(_$Enum$UserTypeEnumMap, json['userType'],
|
||||
unknownValue: Enum$UserType.$unknown),
|
||||
username: json['username'] as String,
|
||||
sshKeys:
|
||||
(json['sshKeys'] as List<dynamic>).map((e) => e as String).toList(),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$AllUsers$users$allUsersToJson(
|
||||
Query$AllUsers$users$allUsers instance) =>
|
||||
<String, dynamic>{
|
||||
'userType': _$Enum$UserTypeEnumMap[instance.userType],
|
||||
'username': instance.username,
|
||||
'sshKeys': instance.sshKeys,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$AddSshKey _$Variables$Mutation$AddSshKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$AddSshKey(
|
||||
sshInput: Input$SshMutationInput.fromJson(
|
||||
json['sshInput'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$AddSshKeyToJson(
|
||||
Variables$Mutation$AddSshKey instance) =>
|
||||
<String, dynamic>{
|
||||
'sshInput': instance.sshInput.toJson(),
|
||||
};
|
||||
|
||||
Mutation$AddSshKey _$Mutation$AddSshKeyFromJson(Map<String, dynamic> json) =>
|
||||
Mutation$AddSshKey(
|
||||
addSshKey: Mutation$AddSshKey$addSshKey.fromJson(
|
||||
json['addSshKey'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$AddSshKeyToJson(Mutation$AddSshKey instance) =>
|
||||
<String, dynamic>{
|
||||
'addSshKey': instance.addSshKey.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$AddSshKey$addSshKey _$Mutation$AddSshKey$addSshKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$AddSshKey$addSshKey(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: Mutation$AddSshKey$addSshKey$user.fromJson(
|
||||
json['user'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$AddSshKey$addSshKeyToJson(
|
||||
Mutation$AddSshKey$addSshKey instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
'user': instance.user?.toJson(),
|
||||
};
|
||||
|
||||
Mutation$AddSshKey$addSshKey$user _$Mutation$AddSshKey$addSshKey$userFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$AddSshKey$addSshKey$user(
|
||||
sshKeys:
|
||||
(json['sshKeys'] as List<dynamic>).map((e) => e as String).toList(),
|
||||
userType: $enumDecode(_$Enum$UserTypeEnumMap, json['userType'],
|
||||
unknownValue: Enum$UserType.$unknown),
|
||||
username: json['username'] as String,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$AddSshKey$addSshKey$userToJson(
|
||||
Mutation$AddSshKey$addSshKey$user instance) =>
|
||||
<String, dynamic>{
|
||||
'sshKeys': instance.sshKeys,
|
||||
'userType': _$Enum$UserTypeEnumMap[instance.userType],
|
||||
'username': instance.username,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Query$GetUser _$Variables$Query$GetUserFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Query$GetUser(
|
||||
username: json['username'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Query$GetUserToJson(
|
||||
Variables$Query$GetUser instance) =>
|
||||
<String, dynamic>{
|
||||
'username': instance.username,
|
||||
};
|
||||
|
||||
Query$GetUser _$Query$GetUserFromJson(Map<String, dynamic> json) =>
|
||||
Query$GetUser(
|
||||
users:
|
||||
Query$GetUser$users.fromJson(json['users'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$GetUserToJson(Query$GetUser instance) =>
|
||||
<String, dynamic>{
|
||||
'users': instance.users.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$GetUser$users _$Query$GetUser$usersFromJson(Map<String, dynamic> json) =>
|
||||
Query$GetUser$users(
|
||||
getUser: json['getUser'] == null
|
||||
? null
|
||||
: Query$GetUser$users$getUser.fromJson(
|
||||
json['getUser'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$GetUser$usersToJson(
|
||||
Query$GetUser$users instance) =>
|
||||
<String, dynamic>{
|
||||
'getUser': instance.getUser?.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Query$GetUser$users$getUser _$Query$GetUser$users$getUserFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Query$GetUser$users$getUser(
|
||||
sshKeys:
|
||||
(json['sshKeys'] as List<dynamic>).map((e) => e as String).toList(),
|
||||
userType: $enumDecode(_$Enum$UserTypeEnumMap, json['userType'],
|
||||
unknownValue: Enum$UserType.$unknown),
|
||||
username: json['username'] as String,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Query$GetUser$users$getUserToJson(
|
||||
Query$GetUser$users$getUser instance) =>
|
||||
<String, dynamic>{
|
||||
'sshKeys': instance.sshKeys,
|
||||
'userType': _$Enum$UserTypeEnumMap[instance.userType],
|
||||
'username': instance.username,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$RemoveSshKey _$Variables$Mutation$RemoveSshKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$RemoveSshKey(
|
||||
sshInput: Input$SshMutationInput.fromJson(
|
||||
json['sshInput'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$RemoveSshKeyToJson(
|
||||
Variables$Mutation$RemoveSshKey instance) =>
|
||||
<String, dynamic>{
|
||||
'sshInput': instance.sshInput.toJson(),
|
||||
};
|
||||
|
||||
Mutation$RemoveSshKey _$Mutation$RemoveSshKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RemoveSshKey(
|
||||
removeSshKey: Mutation$RemoveSshKey$removeSshKey.fromJson(
|
||||
json['removeSshKey'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RemoveSshKeyToJson(
|
||||
Mutation$RemoveSshKey instance) =>
|
||||
<String, dynamic>{
|
||||
'removeSshKey': instance.removeSshKey.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$RemoveSshKey$removeSshKey _$Mutation$RemoveSshKey$removeSshKeyFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RemoveSshKey$removeSshKey(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: Mutation$RemoveSshKey$removeSshKey$user.fromJson(
|
||||
json['user'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RemoveSshKey$removeSshKeyToJson(
|
||||
Mutation$RemoveSshKey$removeSshKey instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
'user': instance.user?.toJson(),
|
||||
};
|
||||
|
||||
Mutation$RemoveSshKey$removeSshKey$user
|
||||
_$Mutation$RemoveSshKey$removeSshKey$userFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$RemoveSshKey$removeSshKey$user(
|
||||
sshKeys: (json['sshKeys'] as List<dynamic>)
|
||||
.map((e) => e as String)
|
||||
.toList(),
|
||||
userType: $enumDecode(_$Enum$UserTypeEnumMap, json['userType'],
|
||||
unknownValue: Enum$UserType.$unknown),
|
||||
username: json['username'] as String,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$RemoveSshKey$removeSshKey$userToJson(
|
||||
Mutation$RemoveSshKey$removeSshKey$user instance) =>
|
||||
<String, dynamic>{
|
||||
'sshKeys': instance.sshKeys,
|
||||
'userType': _$Enum$UserTypeEnumMap[instance.userType],
|
||||
'username': instance.username,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$DeleteUser _$Variables$Mutation$DeleteUserFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$DeleteUser(
|
||||
username: json['username'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$DeleteUserToJson(
|
||||
Variables$Mutation$DeleteUser instance) =>
|
||||
<String, dynamic>{
|
||||
'username': instance.username,
|
||||
};
|
||||
|
||||
Mutation$DeleteUser _$Mutation$DeleteUserFromJson(Map<String, dynamic> json) =>
|
||||
Mutation$DeleteUser(
|
||||
deleteUser: Mutation$DeleteUser$deleteUser.fromJson(
|
||||
json['deleteUser'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$DeleteUserToJson(
|
||||
Mutation$DeleteUser instance) =>
|
||||
<String, dynamic>{
|
||||
'deleteUser': instance.deleteUser.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$DeleteUser$deleteUser _$Mutation$DeleteUser$deleteUserFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$DeleteUser$deleteUser(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$DeleteUser$deleteUserToJson(
|
||||
Mutation$DeleteUser$deleteUser instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Variables$Mutation$UpdateUser _$Variables$Mutation$UpdateUserFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Variables$Mutation$UpdateUser(
|
||||
user: Input$UserMutationInput.fromJson(
|
||||
json['user'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Variables$Mutation$UpdateUserToJson(
|
||||
Variables$Mutation$UpdateUser instance) =>
|
||||
<String, dynamic>{
|
||||
'user': instance.user.toJson(),
|
||||
};
|
||||
|
||||
Mutation$UpdateUser _$Mutation$UpdateUserFromJson(Map<String, dynamic> json) =>
|
||||
Mutation$UpdateUser(
|
||||
updateUser: Mutation$UpdateUser$updateUser.fromJson(
|
||||
json['updateUser'] as Map<String, dynamic>),
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$UpdateUserToJson(
|
||||
Mutation$UpdateUser instance) =>
|
||||
<String, dynamic>{
|
||||
'updateUser': instance.updateUser.toJson(),
|
||||
'__typename': instance.$__typename,
|
||||
};
|
||||
|
||||
Mutation$UpdateUser$updateUser _$Mutation$UpdateUser$updateUserFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
Mutation$UpdateUser$updateUser(
|
||||
code: json['code'] as int,
|
||||
message: json['message'] as String,
|
||||
success: json['success'] as bool,
|
||||
$__typename: json['__typename'] as String,
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: Mutation$UpdateUser$updateUser$user.fromJson(
|
||||
json['user'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$UpdateUser$updateUserToJson(
|
||||
Mutation$UpdateUser$updateUser instance) =>
|
||||
<String, dynamic>{
|
||||
'code': instance.code,
|
||||
'message': instance.message,
|
||||
'success': instance.success,
|
||||
'__typename': instance.$__typename,
|
||||
'user': instance.user?.toJson(),
|
||||
};
|
||||
|
||||
Mutation$UpdateUser$updateUser$user
|
||||
_$Mutation$UpdateUser$updateUser$userFromJson(Map<String, dynamic> json) =>
|
||||
Mutation$UpdateUser$updateUser$user(
|
||||
sshKeys: (json['sshKeys'] as List<dynamic>)
|
||||
.map((e) => e as String)
|
||||
.toList(),
|
||||
userType: $enumDecode(_$Enum$UserTypeEnumMap, json['userType'],
|
||||
unknownValue: Enum$UserType.$unknown),
|
||||
username: json['username'] as String,
|
||||
$__typename: json['__typename'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$Mutation$UpdateUser$updateUser$userToJson(
|
||||
Mutation$UpdateUser$updateUser$user instance) =>
|
||||
<String, dynamic>{
|
||||
'sshKeys': instance.sshKeys,
|
||||
'userType': _$Enum$UserTypeEnumMap[instance.userType],
|
||||
'username': instance.username,
|
||||
'__typename': instance.$__typename,
|
||||
};
|
|
@ -0,0 +1,277 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/api_map.dart';
|
||||
import 'package:selfprivacy/logic/models/json/hetzner_server_info.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
import 'package:selfprivacy/utils/password_generator.dart';
|
||||
|
||||
class HetznerApi extends ApiMap {
|
||||
HetznerApi({this.hasLogger = false, this.isWithToken = true});
|
||||
@override
|
||||
bool hasLogger;
|
||||
@override
|
||||
bool isWithToken;
|
||||
|
||||
@override
|
||||
BaseOptions get options {
|
||||
final BaseOptions options = BaseOptions(baseUrl: rootAddress);
|
||||
if (isWithToken) {
|
||||
final String? token = getIt<ApiConfigModel>().hetznerKey;
|
||||
assert(token != null);
|
||||
options.headers = {'Authorization': 'Bearer $token'};
|
||||
}
|
||||
|
||||
if (validateStatus != null) {
|
||||
options.validateStatus = validateStatus!;
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@override
|
||||
String rootAddress = 'https://api.hetzner.cloud/v1';
|
||||
|
||||
Future<bool> isValid(final String token) async {
|
||||
validateStatus = (final int? status) =>
|
||||
status == HttpStatus.ok || status == HttpStatus.unauthorized;
|
||||
final Dio client = await getClient();
|
||||
final Response response = await client.get(
|
||||
'/servers',
|
||||
options: Options(
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
),
|
||||
);
|
||||
close(client);
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
return true;
|
||||
} else if (response.statusCode == HttpStatus.unauthorized) {
|
||||
return false;
|
||||
} else {
|
||||
throw Exception('code: ${response.statusCode}');
|
||||
}
|
||||
}
|
||||
|
||||
Future<ServerVolume> createVolume() async {
|
||||
final Dio client = await getClient();
|
||||
final Response dbCreateResponse = await client.post(
|
||||
'/volumes',
|
||||
data: {
|
||||
'size': 10,
|
||||
'name': StringGenerators.dbStorageName(),
|
||||
'labels': {'labelkey': 'value'},
|
||||
'location': 'fsn1',
|
||||
'automount': false,
|
||||
'format': 'ext4'
|
||||
},
|
||||
);
|
||||
final dbId = dbCreateResponse.data['volume']['id'];
|
||||
return ServerVolume(
|
||||
id: dbId,
|
||||
name: dbCreateResponse.data['volume']['name'],
|
||||
);
|
||||
}
|
||||
|
||||
Future<ServerHostingDetails?> createServer({
|
||||
required final String cloudFlareKey,
|
||||
required final User rootUser,
|
||||
required final String domainName,
|
||||
required final ServerVolume dataBase,
|
||||
}) async {
|
||||
final Dio client = await getClient();
|
||||
|
||||
final String dbPassword = StringGenerators.dbPassword();
|
||||
final int dbId = dataBase.id;
|
||||
|
||||
final String apiToken = StringGenerators.apiToken();
|
||||
|
||||
final String hostname = getHostnameFromDomain(domainName);
|
||||
|
||||
final String base64Password =
|
||||
base64.encode(utf8.encode(rootUser.password ?? 'PASS'));
|
||||
|
||||
print('hostname: $hostname');
|
||||
|
||||
/// add ssh key when you need it: e.g. "ssh_keys":["kherel"]
|
||||
/// check the branch name, it could be "development" or "master".
|
||||
///
|
||||
final String userdataString =
|
||||
"#cloud-config\nruncmd:\n- curl https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nixos-infect/raw/branch/master/nixos-infect | PROVIDER=hetzner NIX_CHANNEL=nixos-21.05 DOMAIN='$domainName' LUSER='${rootUser.login}' ENCODED_PASSWORD='$base64Password' CF_TOKEN=$cloudFlareKey DB_PASSWORD=$dbPassword API_TOKEN=$apiToken HOSTNAME=$hostname bash 2>&1 | tee /tmp/infect.log";
|
||||
print(userdataString);
|
||||
|
||||
final Map<String, Object> data = {
|
||||
'name': hostname,
|
||||
'server_type': 'cx11',
|
||||
'start_after_create': false,
|
||||
'image': 'ubuntu-20.04',
|
||||
'volumes': [dbId],
|
||||
'networks': [],
|
||||
'user_data': userdataString,
|
||||
'labels': {},
|
||||
'automount': true,
|
||||
'location': 'fsn1'
|
||||
};
|
||||
print('Decoded data: $data');
|
||||
|
||||
ServerHostingDetails? serverDetails;
|
||||
|
||||
try {
|
||||
final Response serverCreateResponse = await client.post(
|
||||
'/servers',
|
||||
data: data,
|
||||
);
|
||||
print(serverCreateResponse.data);
|
||||
serverDetails = ServerHostingDetails(
|
||||
id: serverCreateResponse.data['server']['id'],
|
||||
ip4: serverCreateResponse.data['server']['public_net']['ipv4']['ip'],
|
||||
createTime: DateTime.now(),
|
||||
volume: dataBase,
|
||||
apiToken: apiToken,
|
||||
provider: ServerProvider.hetzner,
|
||||
);
|
||||
} on DioError catch (e) {
|
||||
print(e);
|
||||
rethrow;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
|
||||
return serverDetails;
|
||||
}
|
||||
|
||||
static String getHostnameFromDomain(final String domain) {
|
||||
// Replace all non-alphanumeric characters with an underscore
|
||||
String hostname =
|
||||
domain.split('.')[0].replaceAll(RegExp(r'[^a-zA-Z0-9]'), '-');
|
||||
if (hostname.endsWith('-')) {
|
||||
hostname = hostname.substring(0, hostname.length - 1);
|
||||
}
|
||||
if (hostname.startsWith('-')) {
|
||||
hostname = hostname.substring(1);
|
||||
}
|
||||
if (hostname.isEmpty) {
|
||||
hostname = 'selfprivacy-server';
|
||||
}
|
||||
|
||||
return hostname;
|
||||
}
|
||||
|
||||
Future<void> deleteSelfprivacyServerAndAllVolumes({
|
||||
required final String domainName,
|
||||
}) async {
|
||||
final Dio client = await getClient();
|
||||
|
||||
final String hostname = getHostnameFromDomain(domainName);
|
||||
|
||||
final Response serversReponse = await client.get('/servers');
|
||||
final List servers = serversReponse.data['servers'];
|
||||
final Map server = servers.firstWhere((final el) => el['name'] == hostname);
|
||||
final List volumes = server['volumes'];
|
||||
final List<Future> laterFutures = <Future>[];
|
||||
|
||||
for (final volumeId in volumes) {
|
||||
await client.post('/volumes/$volumeId/actions/detach');
|
||||
}
|
||||
await Future.delayed(const Duration(seconds: 10));
|
||||
|
||||
for (final volumeId in volumes) {
|
||||
laterFutures.add(client.delete('/volumes/$volumeId'));
|
||||
}
|
||||
laterFutures.add(client.delete('/servers/${server['id']}'));
|
||||
|
||||
await Future.wait(laterFutures);
|
||||
close(client);
|
||||
}
|
||||
|
||||
Future<ServerHostingDetails> reset() async {
|
||||
final ServerHostingDetails server = getIt<ApiConfigModel>().serverDetails!;
|
||||
|
||||
final Dio client = await getClient();
|
||||
await client.post('/servers/${server.id}/actions/reset');
|
||||
close(client);
|
||||
|
||||
return server.copyWith(startTime: DateTime.now());
|
||||
}
|
||||
|
||||
Future<ServerHostingDetails> powerOn() async {
|
||||
final ServerHostingDetails server = getIt<ApiConfigModel>().serverDetails!;
|
||||
|
||||
final Dio client = await getClient();
|
||||
await client.post('/servers/${server.id}/actions/poweron');
|
||||
close(client);
|
||||
|
||||
return server.copyWith(startTime: DateTime.now());
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> getMetrics(
|
||||
final DateTime start,
|
||||
final DateTime end,
|
||||
final String type,
|
||||
) async {
|
||||
final ServerHostingDetails? hetznerServer =
|
||||
getIt<ApiConfigModel>().serverDetails;
|
||||
final Dio client = await getClient();
|
||||
|
||||
final Map<String, dynamic> queryParameters = {
|
||||
'start': start.toUtc().toIso8601String(),
|
||||
'end': end.toUtc().toIso8601String(),
|
||||
'type': type
|
||||
};
|
||||
final Response res = await client.get(
|
||||
'/servers/${hetznerServer!.id}/metrics',
|
||||
queryParameters: queryParameters,
|
||||
);
|
||||
close(client);
|
||||
return res.data;
|
||||
}
|
||||
|
||||
Future<HetznerServerInfo> getInfo() async {
|
||||
final ServerHostingDetails? hetznerServer =
|
||||
getIt<ApiConfigModel>().serverDetails;
|
||||
final Dio client = await getClient();
|
||||
final Response response = await client.get('/servers/${hetznerServer!.id}');
|
||||
close(client);
|
||||
|
||||
return HetznerServerInfo.fromJson(response.data!['server']);
|
||||
}
|
||||
|
||||
Future<List<HetznerServerInfo>> getServers() async {
|
||||
final Dio client = await getClient();
|
||||
final Response response = await client.get('/servers');
|
||||
close(client);
|
||||
|
||||
return (response.data!['servers'] as List)
|
||||
// ignore: unnecessary_lambdas
|
||||
.map((final e) => HetznerServerInfo.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<void> createReverseDns({
|
||||
required final String ip4,
|
||||
required final String domainName,
|
||||
}) async {
|
||||
final ServerHostingDetails? hetznerServer =
|
||||
getIt<ApiConfigModel>().serverDetails;
|
||||
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
await client.post(
|
||||
'/servers/${hetznerServer!.id}/actions/change_dns_ptr',
|
||||
data: {
|
||||
'ip': ip4,
|
||||
'dns_ptr': domainName,
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
close(client);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare_factory.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/dns_provider_factory.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/hetzner/hetzner_factory.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/server_provider_factory.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
|
||||
class UnknownApiProviderException implements Exception {
|
||||
UnknownApiProviderException(this.message);
|
||||
final String message;
|
||||
}
|
||||
|
||||
class ApiFactoryCreator {
|
||||
static ServerProviderApiFactory createServerProviderApiFactory(
|
||||
final ServerProvider provider,
|
||||
) {
|
||||
switch (provider) {
|
||||
case ServerProvider.hetzner:
|
||||
return HetznerApiFactory();
|
||||
case ServerProvider.unknown:
|
||||
throw UnknownApiProviderException('Unknown server provider');
|
||||
}
|
||||
}
|
||||
|
||||
static DnsProviderApiFactory createDnsProviderApiFactory(
|
||||
final DnsProvider provider,
|
||||
) {
|
||||
switch (provider) {
|
||||
case DnsProvider.cloudflare:
|
||||
return CloudflareApiFactory();
|
||||
case DnsProvider.unknown:
|
||||
throw UnknownApiProviderException('Unknown DNS provider');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VolumeApiFactoryCreator {
|
||||
static VolumeProviderApiFactory createVolumeProviderApiFactory(
|
||||
final ServerProvider provider,
|
||||
) {
|
||||
switch (provider) {
|
||||
case ServerProvider.hetzner:
|
||||
return HetznerApiFactory();
|
||||
case ServerProvider.unknown:
|
||||
throw UnknownApiProviderException('Unknown volume provider');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/cloudflare/cloudflare.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/dns_provider.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/dns_provider_factory.dart';
|
||||
|
||||
class CloudflareApiFactory extends DnsProviderApiFactory {
|
||||
@override
|
||||
DnsProviderApi getDnsProvider({
|
||||
final DnsProviderApiSettings settings = const DnsProviderApiSettings(),
|
||||
}) =>
|
||||
CloudflareApi(
|
||||
hasLogger: settings.hasLogger,
|
||||
isWithToken: settings.isWithToken,
|
||||
customToken: settings.customToken,
|
||||
);
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
||||
|
||||
class DomainNotFoundException implements Exception {
|
||||
DomainNotFoundException(this.message);
|
||||
final String message;
|
||||
}
|
||||
|
||||
abstract class DnsProviderApi extends ApiMap {
|
||||
Future<List<DnsRecord>> getDnsRecords({
|
||||
required final ServerDomain domain,
|
||||
});
|
||||
Future<void> removeSimilarRecords({
|
||||
required final ServerDomain domain,
|
||||
final String? ip4,
|
||||
});
|
||||
Future<void> createMultipleDnsRecords({
|
||||
required final ServerDomain domain,
|
||||
final String? ip4,
|
||||
});
|
||||
Future<void> setDkim(
|
||||
final String dkimRecordString,
|
||||
final ServerDomain domain,
|
||||
);
|
||||
Future<String> getZoneId(final String domain);
|
||||
Future<List<String>> domainList();
|
||||
|
||||
Future<bool> isApiTokenValid(final String token);
|
||||
RegExp getApiTokenValidation();
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/dns_provider.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/provider_api_settings.dart';
|
||||
|
||||
class DnsProviderApiSettings extends ProviderApiSettings {
|
||||
const DnsProviderApiSettings({
|
||||
final super.hasLogger = false,
|
||||
final super.isWithToken = true,
|
||||
final this.customToken,
|
||||
});
|
||||
final String? customToken;
|
||||
}
|
||||
|
||||
abstract class DnsProviderApiFactory {
|
||||
DnsProviderApi getDnsProvider({
|
||||
final DnsProviderApiSettings settings = const DnsProviderApiSettings(),
|
||||
});
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
class ProviderApiSettings {
|
||||
const ProviderApiSettings({this.hasLogger = false, this.isWithToken = true});
|
||||
final bool hasLogger;
|
||||
final bool isWithToken;
|
||||
}
|
|
@ -1,546 +0,0 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/volume_provider.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/server_provider.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
import 'package:selfprivacy/logic/models/json/hetzner_server_info.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
||||
import 'package:selfprivacy/utils/password_generator.dart';
|
||||
|
||||
class HetznerApi extends ServerProviderApi with VolumeProviderApi {
|
||||
HetznerApi({final this.hasLogger = false, final this.isWithToken = true});
|
||||
@override
|
||||
bool hasLogger;
|
||||
@override
|
||||
bool isWithToken;
|
||||
|
||||
@override
|
||||
BaseOptions get options {
|
||||
final BaseOptions options = BaseOptions(baseUrl: rootAddress);
|
||||
if (isWithToken) {
|
||||
final String? token = getIt<ApiConfigModel>().hetznerKey;
|
||||
assert(token != null);
|
||||
options.headers = {'Authorization': 'Bearer $token'};
|
||||
}
|
||||
|
||||
if (validateStatus != null) {
|
||||
options.validateStatus = validateStatus!;
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@override
|
||||
String rootAddress = 'https://api.hetzner.cloud/v1';
|
||||
|
||||
@override
|
||||
Future<bool> isApiTokenValid(final String token) async {
|
||||
bool isValid = false;
|
||||
Response? response;
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
response = await client.get(
|
||||
'/servers',
|
||||
options: Options(
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
isValid = false;
|
||||
} finally {
|
||||
close(client);
|
||||
}
|
||||
|
||||
if (response != null) {
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
isValid = true;
|
||||
} else if (response.statusCode == HttpStatus.unauthorized) {
|
||||
isValid = false;
|
||||
} else {
|
||||
throw Exception('code: ${response.statusCode}');
|
||||
}
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
@override
|
||||
RegExp getApiTokenValidation() =>
|
||||
RegExp(r'\s+|[-!$%^&*()@+|~=`{}\[\]:<>?,.\/]');
|
||||
|
||||
@override
|
||||
Future<double?> getPricePerGb() async {
|
||||
double? price;
|
||||
|
||||
final Response dbGetResponse;
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
dbGetResponse = await client.get('/pricing');
|
||||
|
||||
final volume = dbGetResponse.data['pricing']['volume'];
|
||||
final volumePrice = volume['price_per_gb_month']['gross'];
|
||||
price = double.parse(volumePrice);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
|
||||
return price;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ServerVolume?> createVolume() async {
|
||||
ServerVolume? volume;
|
||||
|
||||
final Response dbCreateResponse;
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
dbCreateResponse = await client.post(
|
||||
'/volumes',
|
||||
data: {
|
||||
'size': 10,
|
||||
'name': StringGenerators.dbStorageName(),
|
||||
'labels': {'labelkey': 'value'},
|
||||
'location': 'fsn1',
|
||||
'automount': false,
|
||||
'format': 'ext4'
|
||||
},
|
||||
);
|
||||
final dbId = dbCreateResponse.data['volume']['id'];
|
||||
final dbSize = dbCreateResponse.data['volume']['size'];
|
||||
final dbServer = dbCreateResponse.data['volume']['server'];
|
||||
final dbName = dbCreateResponse.data['volume']['name'];
|
||||
final dbDevice = dbCreateResponse.data['volume']['linux_device'];
|
||||
volume = ServerVolume(
|
||||
id: dbId,
|
||||
name: dbName,
|
||||
sizeByte: dbSize,
|
||||
serverId: dbServer,
|
||||
linuxDevice: dbDevice,
|
||||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<ServerVolume>> getVolumes({final String? status}) async {
|
||||
final List<ServerVolume> volumes = [];
|
||||
|
||||
final Response dbGetResponse;
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
dbGetResponse = await client.get(
|
||||
'/volumes',
|
||||
queryParameters: {
|
||||
'status': status,
|
||||
},
|
||||
);
|
||||
final List<dynamic> rawVolumes = dbGetResponse.data['volumes'];
|
||||
for (final rawVolume in rawVolumes) {
|
||||
final int dbId = rawVolume['id'];
|
||||
final int dbSize = rawVolume['size'];
|
||||
final dbServer = rawVolume['server'];
|
||||
final String dbName = rawVolume['name'];
|
||||
final dbDevice = rawVolume['linux_device'];
|
||||
final volume = ServerVolume(
|
||||
id: dbId,
|
||||
name: dbName,
|
||||
sizeByte: dbSize,
|
||||
serverId: dbServer,
|
||||
linuxDevice: dbDevice,
|
||||
);
|
||||
volumes.add(volume);
|
||||
}
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
|
||||
return volumes;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ServerVolume?> getVolume(final int id) async {
|
||||
ServerVolume? volume;
|
||||
|
||||
final Response dbGetResponse;
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
dbGetResponse = await client.get('/volumes/$id');
|
||||
final int dbId = dbGetResponse.data['volume']['id'];
|
||||
final int dbSize = dbGetResponse.data['volume']['size'];
|
||||
final int dbServer = dbGetResponse.data['volume']['server'];
|
||||
final String dbName = dbGetResponse.data['volume']['name'];
|
||||
final dbDevice = dbGetResponse.data['volume']['linux_device'];
|
||||
volume = ServerVolume(
|
||||
id: dbId,
|
||||
name: dbName,
|
||||
sizeByte: dbSize,
|
||||
serverId: dbServer,
|
||||
linuxDevice: dbDevice,
|
||||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
|
||||
return volume;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteVolume(final int id) async {
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
await client.delete('/volumes/$id');
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> attachVolume(final int volumeId, final int serverId) async {
|
||||
bool success = false;
|
||||
|
||||
final Response dbPostResponse;
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
dbPostResponse = await client.post(
|
||||
'/volumes/$volumeId/actions/attach',
|
||||
data: {
|
||||
'automount': true,
|
||||
'server': serverId,
|
||||
},
|
||||
);
|
||||
success = dbPostResponse.data['action']['status'].toString() != 'error';
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> detachVolume(final int volumeId) async {
|
||||
bool success = false;
|
||||
|
||||
final Response dbPostResponse;
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
dbPostResponse = await client.post('/volumes/$volumeId/actions/detach');
|
||||
success = dbPostResponse.data['action']['status'].toString() != 'error';
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> resizeVolume(final int volumeId, final int sizeGb) async {
|
||||
bool success = false;
|
||||
|
||||
final Response dbPostResponse;
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
dbPostResponse = await client.post(
|
||||
'/volumes/$volumeId/actions/resize',
|
||||
data: {
|
||||
'size': sizeGb,
|
||||
},
|
||||
);
|
||||
success = dbPostResponse.data['action']['status'].toString() != 'error';
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ServerHostingDetails?> createServer({
|
||||
required final String dnsApiToken,
|
||||
required final User rootUser,
|
||||
required final String domainName,
|
||||
}) async {
|
||||
ServerHostingDetails? details;
|
||||
|
||||
final ServerVolume? newVolume = await createVolume();
|
||||
if (newVolume == null) {
|
||||
return details;
|
||||
}
|
||||
|
||||
details = await createServerWithVolume(
|
||||
dnsApiToken: dnsApiToken,
|
||||
rootUser: rootUser,
|
||||
domainName: domainName,
|
||||
dataBase: newVolume,
|
||||
);
|
||||
|
||||
return details;
|
||||
}
|
||||
|
||||
Future<ServerHostingDetails?> createServerWithVolume({
|
||||
required final String dnsApiToken,
|
||||
required final User rootUser,
|
||||
required final String domainName,
|
||||
required final ServerVolume dataBase,
|
||||
}) async {
|
||||
final Dio client = await getClient();
|
||||
|
||||
final String dbPassword = StringGenerators.dbPassword();
|
||||
final int dbId = dataBase.id;
|
||||
|
||||
final String apiToken = StringGenerators.apiToken();
|
||||
|
||||
final String hostname = getHostnameFromDomain(domainName);
|
||||
|
||||
final String base64Password =
|
||||
base64.encode(utf8.encode(rootUser.password ?? 'PASS'));
|
||||
|
||||
print('hostname: $hostname');
|
||||
|
||||
/// add ssh key when you need it: e.g. "ssh_keys":["kherel"]
|
||||
/// check the branch name, it could be "development" or "master".
|
||||
///
|
||||
final String userdataString =
|
||||
"#cloud-config\nruncmd:\n- curl https://git.selfprivacy.org/SelfPrivacy/selfprivacy-nixos-infect/raw/branch/master/nixos-infect | PROVIDER=hetzner NIX_CHANNEL=nixos-21.05 DOMAIN='$domainName' LUSER='${rootUser.login}' ENCODED_PASSWORD='$base64Password' CF_TOKEN=$dnsApiToken DB_PASSWORD=$dbPassword API_TOKEN=$apiToken HOSTNAME=$hostname bash 2>&1 | tee /tmp/infect.log";
|
||||
print(userdataString);
|
||||
|
||||
final Map<String, Object> data = {
|
||||
'name': hostname,
|
||||
'server_type': 'cx11',
|
||||
'start_after_create': false,
|
||||
'image': 'ubuntu-20.04',
|
||||
'volumes': [dbId],
|
||||
'networks': [],
|
||||
'user_data': userdataString,
|
||||
'labels': {},
|
||||
'automount': true,
|
||||
'location': 'fsn1'
|
||||
};
|
||||
print('Decoded data: $data');
|
||||
|
||||
ServerHostingDetails? serverDetails;
|
||||
DioError? hetznerError;
|
||||
bool success = false;
|
||||
|
||||
try {
|
||||
final Response serverCreateResponse = await client.post(
|
||||
'/servers',
|
||||
data: data,
|
||||
);
|
||||
print(serverCreateResponse.data);
|
||||
serverDetails = ServerHostingDetails(
|
||||
id: serverCreateResponse.data['server']['id'],
|
||||
ip4: serverCreateResponse.data['server']['public_net']['ipv4']['ip'],
|
||||
createTime: DateTime.now(),
|
||||
volume: dataBase,
|
||||
apiToken: apiToken,
|
||||
provider: ServerProvider.hetzner,
|
||||
);
|
||||
success = true;
|
||||
} on DioError catch (e) {
|
||||
print(e);
|
||||
hetznerError = e;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
await Future.delayed(const Duration(seconds: 10));
|
||||
await deleteVolume(dbId);
|
||||
}
|
||||
|
||||
if (hetznerError != null) {
|
||||
throw hetznerError;
|
||||
}
|
||||
|
||||
return serverDetails;
|
||||
}
|
||||
|
||||
static String getHostnameFromDomain(final String domain) {
|
||||
// Replace all non-alphanumeric characters with an underscore
|
||||
String hostname =
|
||||
domain.split('.')[0].replaceAll(RegExp(r'[^a-zA-Z0-9]'), '-');
|
||||
if (hostname.endsWith('-')) {
|
||||
hostname = hostname.substring(0, hostname.length - 1);
|
||||
}
|
||||
if (hostname.startsWith('-')) {
|
||||
hostname = hostname.substring(1);
|
||||
}
|
||||
if (hostname.isEmpty) {
|
||||
hostname = 'selfprivacy-server';
|
||||
}
|
||||
|
||||
return hostname;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteServer({
|
||||
required final String domainName,
|
||||
}) async {
|
||||
final Dio client = await getClient();
|
||||
|
||||
final String hostname = getHostnameFromDomain(domainName);
|
||||
|
||||
final Response serversReponse = await client.get('/servers');
|
||||
final List servers = serversReponse.data['servers'];
|
||||
final Map server = servers.firstWhere((final el) => el['name'] == hostname);
|
||||
final List volumes = server['volumes'];
|
||||
final List<Future> laterFutures = <Future>[];
|
||||
|
||||
for (final volumeId in volumes) {
|
||||
await client.post('/volumes/$volumeId/actions/detach');
|
||||
}
|
||||
await Future.delayed(const Duration(seconds: 10));
|
||||
|
||||
for (final volumeId in volumes) {
|
||||
laterFutures.add(client.delete('/volumes/$volumeId'));
|
||||
}
|
||||
laterFutures.add(client.delete('/servers/${server['id']}'));
|
||||
|
||||
await Future.wait(laterFutures);
|
||||
close(client);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ServerHostingDetails> restart() async {
|
||||
final ServerHostingDetails server = getIt<ApiConfigModel>().serverDetails!;
|
||||
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
await client.post('/servers/${server.id}/actions/reset');
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
close(client);
|
||||
}
|
||||
|
||||
return server.copyWith(startTime: DateTime.now());
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ServerHostingDetails> powerOn() async {
|
||||
final ServerHostingDetails server = getIt<ApiConfigModel>().serverDetails!;
|
||||
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
await client.post('/servers/${server.id}/actions/poweron');
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
close(client);
|
||||
}
|
||||
|
||||
return server.copyWith(startTime: DateTime.now());
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> getMetrics(
|
||||
final DateTime start,
|
||||
final DateTime end,
|
||||
final String type,
|
||||
) async {
|
||||
final ServerHostingDetails? hetznerServer =
|
||||
getIt<ApiConfigModel>().serverDetails;
|
||||
final Dio client = await getClient();
|
||||
|
||||
final Map<String, dynamic> queryParameters = {
|
||||
'start': start.toUtc().toIso8601String(),
|
||||
'end': end.toUtc().toIso8601String(),
|
||||
'type': type
|
||||
};
|
||||
final Response res = await client.get(
|
||||
'/servers/${hetznerServer!.id}/metrics',
|
||||
queryParameters: queryParameters,
|
||||
);
|
||||
close(client);
|
||||
return res.data;
|
||||
}
|
||||
|
||||
Future<HetznerServerInfo> getInfo() async {
|
||||
final ServerHostingDetails? hetznerServer =
|
||||
getIt<ApiConfigModel>().serverDetails;
|
||||
final Dio client = await getClient();
|
||||
final Response response = await client.get('/servers/${hetznerServer!.id}');
|
||||
close(client);
|
||||
|
||||
return HetznerServerInfo.fromJson(response.data!['server']);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<ServerBasicInfo>> getServers() async {
|
||||
List<ServerBasicInfo> servers = [];
|
||||
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
final Response response = await client.get('/servers');
|
||||
servers = (response.data!['servers'] as List)
|
||||
.map(
|
||||
(final e) => HetznerServerInfo.fromJson(e),
|
||||
)
|
||||
.toList()
|
||||
.map(
|
||||
(final HetznerServerInfo server) => ServerBasicInfo(
|
||||
id: server.id,
|
||||
name: server.name,
|
||||
ip: server.publicNet.ipv4.ip,
|
||||
reverseDns: server.publicNet.ipv4.reverseDns,
|
||||
created: server.created,
|
||||
volumeId: server.volumes.isNotEmpty ? server.volumes[0] : 0,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
close(client);
|
||||
}
|
||||
|
||||
return servers;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> createReverseDns({
|
||||
required final ServerHostingDetails serverDetails,
|
||||
required final ServerDomain domain,
|
||||
}) async {
|
||||
final Dio client = await getClient();
|
||||
try {
|
||||
await client.post(
|
||||
'/servers/${serverDetails.id}/actions/change_dns_ptr',
|
||||
data: {
|
||||
'ip': serverDetails.ip4,
|
||||
'dns_ptr': domain.domainName,
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} finally {
|
||||
close(client);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
import 'package:selfprivacy/logic/api_maps/rest_maps/provider_api_settings.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/hetzner/hetzner.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/server_provider.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/server_provider_factory.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/volume_provider.dart';
|
||||
|
||||
class HetznerApiFactory extends ServerProviderApiFactory
|
||||
with VolumeProviderApiFactory {
|
||||
@override
|
||||
ServerProviderApi getServerProvider({
|
||||
final ProviderApiSettings settings = const ProviderApiSettings(),
|
||||
}) =>
|
||||
HetznerApi(
|
||||
hasLogger: settings.hasLogger,
|
||||
isWithToken: settings.isWithToken,
|
||||
);
|
||||
|
||||
@override
|
||||
VolumeProviderApi getVolumeProvider({
|
||||
final ProviderApiSettings settings = const ProviderApiSettings(),
|
||||
}) =>
|
||||
HetznerApi(
|
||||
hasLogger: settings.hasLogger,
|
||||
isWithToken: settings.isWithToken,
|
||||
);
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
||||
|
||||
abstract class ServerProviderApi extends ApiMap {
|
||||
Future<List<ServerBasicInfo>> getServers();
|
||||
|
||||
Future<ServerHostingDetails> restart();
|
||||
Future<ServerHostingDetails> powerOn();
|
||||
|
||||
Future<void> deleteServer({required final String domainName});
|
||||
Future<ServerHostingDetails?> createServer({
|
||||
required final String dnsApiToken,
|
||||
required final User rootUser,
|
||||
required final String domainName,
|
||||
});
|
||||
Future<void> createReverseDns({
|
||||
required final ServerHostingDetails serverDetails,
|
||||
required final ServerDomain domain,
|
||||
});
|
||||
|
||||
Future<bool> isApiTokenValid(final String token);
|
||||
RegExp getApiTokenValidation();
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
import 'package:selfprivacy/logic/api_maps/rest_maps/provider_api_settings.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/server_provider.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/volume_provider.dart';
|
||||
|
||||
abstract class ServerProviderApiFactory {
|
||||
ServerProviderApi getServerProvider({
|
||||
final ProviderApiSettings settings = const ProviderApiSettings(),
|
||||
});
|
||||
}
|
||||
|
||||
mixin VolumeProviderApiFactory {
|
||||
VolumeProviderApi getVolumeProvider({
|
||||
final ProviderApiSettings settings = const ProviderApiSettings(),
|
||||
});
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
|
||||
mixin VolumeProviderApi on ApiMap {
|
||||
Future<ServerVolume?> createVolume();
|
||||
Future<List<ServerVolume>> getVolumes({final String? status});
|
||||
Future<ServerVolume?> getVolume(final int id);
|
||||
Future<bool> attachVolume(final int volumeId, final int serverId);
|
||||
Future<bool> detachVolume(final int volumeId);
|
||||
Future<bool> resizeVolume(final int volumeId, final int sizeGb);
|
||||
Future<void> deleteVolume(final int id);
|
||||
Future<double?> getPricePerGb();
|
||||
}
|
|
@ -15,7 +15,7 @@ import 'package:selfprivacy/logic/models/json/device_token.dart';
|
|||
import 'package:selfprivacy/logic/models/json/recovery_token_status.dart';
|
||||
import 'package:selfprivacy/logic/models/timezone_settings.dart';
|
||||
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_map.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/api_map.dart';
|
||||
|
||||
class ApiResponse<D> {
|
||||
ApiResponse({
|
||||
|
@ -46,20 +46,16 @@ class ServerApi extends ApiMap {
|
|||
|
||||
@override
|
||||
BaseOptions get options {
|
||||
BaseOptions options = BaseOptions(
|
||||
connectTimeout: 10000,
|
||||
receiveTimeout: 10000,
|
||||
);
|
||||
BaseOptions options = BaseOptions();
|
||||
|
||||
if (isWithToken) {
|
||||
final ServerDomain? serverDomain = getIt<ApiConfigModel>().serverDomain;
|
||||
final String domainName = serverDomain!.domainName;
|
||||
final ServerDomain? cloudFlareDomain =
|
||||
getIt<ApiConfigModel>().serverDomain;
|
||||
final String domainName = cloudFlareDomain!.domainName;
|
||||
final String? apiToken = getIt<ApiConfigModel>().serverDetails?.apiToken;
|
||||
|
||||
options = BaseOptions(
|
||||
baseUrl: 'https://api.$domainName',
|
||||
connectTimeout: 10000,
|
||||
receiveTimeout: 10000,
|
||||
headers: {
|
||||
'Authorization': 'Bearer $apiToken',
|
||||
},
|
||||
|
@ -69,8 +65,6 @@ class ServerApi extends ApiMap {
|
|||
if (overrideDomain != null) {
|
||||
options = BaseOptions(
|
||||
baseUrl: 'https://api.$overrideDomain',
|
||||
connectTimeout: 10000,
|
||||
receiveTimeout: 10000,
|
||||
headers: customToken != null
|
||||
? {'Authorization': 'Bearer $customToken'}
|
||||
: null,
|
||||
|
@ -105,8 +99,8 @@ class ServerApi extends ApiMap {
|
|||
try {
|
||||
response = await client.get('/services/status');
|
||||
res = response.statusCode == HttpStatus.ok;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
} on DioError catch (e) {
|
||||
print(e.message);
|
||||
} finally {
|
||||
close(client);
|
||||
}
|
||||
|
@ -625,7 +619,7 @@ class ServerApi extends ApiMap {
|
|||
}
|
||||
}
|
||||
|
||||
Future<String> getDkim() async {
|
||||
Future<String?> getDkim() async {
|
||||
Response response;
|
||||
|
||||
final Dio client = await getClient();
|
||||
|
@ -633,13 +627,13 @@ class ServerApi extends ApiMap {
|
|||
response = await client.get('/services/mailserver/dkim');
|
||||
} on DioError catch (e) {
|
||||
print(e.message);
|
||||
throw Exception('No DKIM key found');
|
||||
return null;
|
||||
} finally {
|
||||
close(client);
|
||||
}
|
||||
|
||||
if (response.statusCode == null) {
|
||||
throw Exception('No DKIM key found');
|
||||
return null;
|
||||
}
|
||||
|
||||
if (response.statusCode == HttpStatus.notFound || response.data == null) {
|
||||
|
@ -647,7 +641,7 @@ class ServerApi extends ApiMap {
|
|||
}
|
||||
|
||||
if (response.statusCode != HttpStatus.ok) {
|
||||
throw Exception('No DKIM key found');
|
||||
return '';
|
||||
}
|
||||
|
||||
final Codec<String, String> base64toString = utf8.fuse(base64);
|
|
@ -2,8 +2,8 @@ import 'dart:async';
|
|||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/backblaze.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/backblaze.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backblaze_bucket.dart';
|
||||
import 'package:selfprivacy/logic/models/json/backup.dart';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/json/api_token.dart';
|
||||
|
@ -16,16 +16,17 @@ class ApiDevicesCubit
|
|||
@override
|
||||
void load() async {
|
||||
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||
_refetch();
|
||||
final List<ApiToken>? devices = await _getApiTokens();
|
||||
if (devices != null) {
|
||||
emit(ApiDevicesState(devices, LoadingStatus.success));
|
||||
} else {
|
||||
emit(const ApiDevicesState([], LoadingStatus.error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> refresh() async {
|
||||
emit(const ApiDevicesState([], LoadingStatus.refreshing));
|
||||
_refetch();
|
||||
}
|
||||
|
||||
void _refetch() async {
|
||||
final List<ApiToken>? devices = await _getApiTokens();
|
||||
if (devices != null) {
|
||||
emit(ApiDevicesState(devices, LoadingStatus.success));
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_factory_creator.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/dns_provider.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/dns_provider_factory.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
||||
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/cloudflare.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||
|
||||
part 'dns_records_state.dart';
|
||||
|
||||
|
@ -18,12 +16,8 @@ class DnsRecordsCubit
|
|||
const DnsRecordsState(dnsState: DnsRecordsStatus.refreshing),
|
||||
);
|
||||
|
||||
DnsProviderApiFactory? dnsProviderApiFactory =
|
||||
ApiFactoryCreator.createDnsProviderApiFactory(
|
||||
DnsProvider.cloudflare, // TODO: HARDCODE FOR NOW!!!
|
||||
); // TODO: Remove when provider selection is implemented.
|
||||
|
||||
final ServerApi api = ServerApi();
|
||||
final CloudflareApi cloudflare = CloudflareApi();
|
||||
|
||||
@override
|
||||
Future<void> load() async {
|
||||
|
@ -37,15 +31,14 @@ class DnsRecordsCubit
|
|||
),
|
||||
),
|
||||
);
|
||||
|
||||
print('Loading DNS status');
|
||||
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||
final ServerDomain? domain = serverInstallationCubit.state.serverDomain;
|
||||
final String? ipAddress =
|
||||
serverInstallationCubit.state.serverDetails?.ip4;
|
||||
if (domain != null && ipAddress != null) {
|
||||
final List<DnsRecord> records = await dnsProviderApiFactory!
|
||||
.getDnsProvider()
|
||||
.getDnsRecords(domain: domain);
|
||||
final List<DnsRecord> records =
|
||||
await cloudflare.getDnsRecords(cloudFlareDomain: domain);
|
||||
final String? dkimPublicKey = await api.getDkim();
|
||||
final List<DesiredDnsRecord> desiredRecords =
|
||||
_getDesiredDnsRecords(domain.domainName, ipAddress, dkimPublicKey);
|
||||
|
@ -123,14 +116,12 @@ class DnsRecordsCubit
|
|||
final ServerDomain? domain = serverInstallationCubit.state.serverDomain;
|
||||
final String? ipAddress = serverInstallationCubit.state.serverDetails?.ip4;
|
||||
final String? dkimPublicKey = await api.getDkim();
|
||||
final DnsProviderApi dnsProviderApi =
|
||||
dnsProviderApiFactory!.getDnsProvider();
|
||||
await dnsProviderApi.removeSimilarRecords(domain: domain!);
|
||||
await dnsProviderApi.createMultipleDnsRecords(
|
||||
domain: domain,
|
||||
await cloudflare.removeSimilarRecords(cloudFlareDomain: domain!);
|
||||
await cloudflare.createMultipleDnsRecords(
|
||||
cloudFlareDomain: domain,
|
||||
ip4: ipAddress,
|
||||
);
|
||||
await dnsProviderApi.setDkim(dkimPublicKey ?? '', domain);
|
||||
await cloudflare.setDkim(dkimPublicKey ?? '', domain);
|
||||
await load();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import 'dart:async';
|
||||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/backblaze.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/backblaze.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backblaze_credential.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
|
@ -55,11 +55,10 @@ class BackblazeFormCubit extends FormCubit {
|
|||
}
|
||||
|
||||
if (!isKeyValid) {
|
||||
keyId.setError('initializing.backblaze_bad_key_error'.tr());
|
||||
applicationKey.setError('initializing.backblaze_bad_key_error'.tr());
|
||||
keyId.setError('bad key');
|
||||
applicationKey.setError('bad key');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,13 @@ import 'dart:async';
|
|||
|
||||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/cloudflare.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/validations/validations.dart';
|
||||
|
||||
class DnsProviderFormCubit extends FormCubit {
|
||||
DnsProviderFormCubit(this.initializingCubit) {
|
||||
final RegExp regExp = initializingCubit.getDnsProviderApiTokenValidation();
|
||||
class CloudFlareFormCubit extends FormCubit {
|
||||
CloudFlareFormCubit(this.initializingCubit) {
|
||||
final RegExp regExp = RegExp(r'\s+|[!$%^&*()@+|~=`{}\[\]:<>?,.\/]');
|
||||
apiKey = FieldCubit(
|
||||
initalValue: '',
|
||||
validations: [
|
||||
|
@ -29,25 +30,24 @@ class DnsProviderFormCubit extends FormCubit {
|
|||
}
|
||||
|
||||
final ServerInstallationCubit initializingCubit;
|
||||
|
||||
late final FieldCubit<String> apiKey;
|
||||
|
||||
@override
|
||||
FutureOr<bool> asyncValidation() async {
|
||||
late bool isKeyValid;
|
||||
final CloudflareApi apiClient = CloudflareApi(isWithToken: false);
|
||||
|
||||
try {
|
||||
isKeyValid = await initializingCubit
|
||||
.isDnsProviderApiTokenValid(apiKey.state.value);
|
||||
isKeyValid = await apiClient.isValid(apiKey.state.value);
|
||||
} catch (e) {
|
||||
addError(e);
|
||||
isKeyValid = false;
|
||||
}
|
||||
|
||||
if (!isKeyValid) {
|
||||
apiKey.setError('initializing.cloudflare_bad_key_error'.tr());
|
||||
apiKey.setError('bad key');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/cloudflare.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
|
||||
|
@ -9,10 +10,9 @@ class DomainSetupCubit extends Cubit<DomainSetupState> {
|
|||
|
||||
Future<void> load() async {
|
||||
emit(Loading(LoadingTypes.loadingDomain));
|
||||
final List<String> list = await serverInstallationCubit
|
||||
.repository.dnsProviderApiFactory!
|
||||
.getDnsProvider()
|
||||
.domainList();
|
||||
final CloudflareApi api = CloudflareApi();
|
||||
|
||||
final List<String> list = await api.domainList();
|
||||
if (list.isEmpty) {
|
||||
emit(Empty());
|
||||
} else if (list.length == 1) {
|
||||
|
@ -28,13 +28,11 @@ class DomainSetupCubit extends Cubit<DomainSetupState> {
|
|||
Future<void> saveDomain() async {
|
||||
assert(state is Loaded, 'wrong state');
|
||||
final String domainName = (state as Loaded).domain;
|
||||
final CloudflareApi api = CloudflareApi();
|
||||
|
||||
emit(Loading(LoadingTypes.saving));
|
||||
|
||||
final String zoneId = await serverInstallationCubit
|
||||
.repository.dnsProviderApiFactory!
|
||||
.getDnsProvider()
|
||||
.getZoneId(domainName);
|
||||
final String zoneId = await api.getZoneId(domainName);
|
||||
|
||||
final ServerDomain domain = ServerDomain(
|
||||
domainName: domainName,
|
|
@ -2,13 +2,13 @@ import 'dart:async';
|
|||
|
||||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/hetzner.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/validations/validations.dart';
|
||||
|
||||
class ProviderFormCubit extends FormCubit {
|
||||
ProviderFormCubit(this.serverInstallationCubit) {
|
||||
final RegExp regExp =
|
||||
serverInstallationCubit.getServerProviderApiTokenValidation();
|
||||
class HetznerFormCubit extends FormCubit {
|
||||
HetznerFormCubit(this.serverInstallationCubit) {
|
||||
final RegExp regExp = RegExp(r'\s+|[-!$%^&*()@+|~=`{}\[\]:<>?,.\/]');
|
||||
apiKey = FieldCubit(
|
||||
initalValue: '',
|
||||
validations: [
|
||||
|
@ -30,25 +30,24 @@ class ProviderFormCubit extends FormCubit {
|
|||
}
|
||||
|
||||
final ServerInstallationCubit serverInstallationCubit;
|
||||
|
||||
late final FieldCubit<String> apiKey;
|
||||
|
||||
@override
|
||||
FutureOr<bool> asyncValidation() async {
|
||||
late bool isKeyValid;
|
||||
final HetznerApi apiClient = HetznerApi(isWithToken: false);
|
||||
|
||||
try {
|
||||
isKeyValid = await serverInstallationCubit
|
||||
.isServerProviderApiTokenValid(apiKey.state.value);
|
||||
isKeyValid = await apiClient.isValid(apiKey.state.value);
|
||||
} catch (e) {
|
||||
addError(e);
|
||||
isKeyValid = false;
|
||||
}
|
||||
|
||||
if (!isKeyValid) {
|
||||
apiKey.setError('initializing.hetzner_bad_key_error'.tr());
|
||||
apiKey.setError('bad key');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ import 'dart:async';
|
|||
|
||||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
|
||||
|
||||
|
@ -18,9 +18,8 @@ class RecoveryDomainFormCubit extends FormCubit {
|
|||
|
||||
@override
|
||||
FutureOr<void> onSubmit() async {
|
||||
initializingCubit.submitDomainForAccessRecovery(
|
||||
serverDomainField.state.value.toLowerCase(),
|
||||
);
|
||||
initializingCubit
|
||||
.submitDomainForAccessRecovery(serverDomainField.state.value);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -41,8 +41,7 @@ class SshFormCubit extends FormCubit {
|
|||
@override
|
||||
FutureOr<void> onSubmit() {
|
||||
print(key.state.isValid);
|
||||
jobsCubit
|
||||
.addJob(CreateSSHKeyJob(user: user, publicKey: key.state.value.trim()));
|
||||
jobsCubit.addJob(CreateSSHKeyJob(user: user, publicKey: key.state.value));
|
||||
}
|
||||
|
||||
late FieldCubit<String> key;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/hetzner/hetzner.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/hetzner.dart';
|
||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||
import 'package:selfprivacy/logic/models/hetzner_metrics.dart';
|
||||
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/job.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||
|
||||
export 'package:provider/provider.dart';
|
||||
|
||||
|
@ -18,21 +15,20 @@ class JobsCubit extends Cubit<JobsState> {
|
|||
JobsCubit({
|
||||
required this.usersCubit,
|
||||
required this.servicesCubit,
|
||||
}) : super(const JobsStateEmpty([]));
|
||||
}) : super(JobsStateEmpty());
|
||||
|
||||
final ServerApi api = ServerApi();
|
||||
final UsersCubit usersCubit;
|
||||
final ServicesCubit servicesCubit;
|
||||
|
||||
void addJob(final ClientJob job) {
|
||||
final List<ClientJob> newJobsList = [];
|
||||
void addJob(final Job job) {
|
||||
final List<Job> newJobsList = <Job>[];
|
||||
if (state is JobsStateWithJobs) {
|
||||
final JobsStateWithJobs jobsState = state as JobsStateWithJobs;
|
||||
newJobsList.addAll(jobsState.clientJobList);
|
||||
newJobsList.addAll((state as JobsStateWithJobs).jobList);
|
||||
}
|
||||
newJobsList.add(job);
|
||||
getIt<NavigationService>().showSnackBar('jobs.jobAdded'.tr());
|
||||
emit(JobsStateWithJobs(newJobsList, state.serverJobList));
|
||||
emit(JobsStateWithJobs(newJobsList));
|
||||
}
|
||||
|
||||
void removeJob(final String id) {
|
||||
|
@ -41,51 +37,51 @@ class JobsCubit extends Cubit<JobsState> {
|
|||
}
|
||||
|
||||
void createOrRemoveServiceToggleJob(final ToggleJob job) {
|
||||
final List<ClientJob> newJobsList = <ClientJob>[];
|
||||
final List<Job> newJobsList = <Job>[];
|
||||
if (state is JobsStateWithJobs) {
|
||||
newJobsList.addAll((state as JobsStateWithJobs).clientJobList);
|
||||
newJobsList.addAll((state as JobsStateWithJobs).jobList);
|
||||
}
|
||||
final bool needToRemoveJob = newJobsList
|
||||
.any((final el) => el is ServiceToggleJob && el.type == job.type);
|
||||
if (needToRemoveJob) {
|
||||
final ClientJob removingJob = newJobsList.firstWhere(
|
||||
final Job removingJob = newJobsList.firstWhere(
|
||||
(final el) => el is ServiceToggleJob && el.type == job.type,
|
||||
);
|
||||
removeJob(removingJob.id);
|
||||
} else {
|
||||
newJobsList.add(job);
|
||||
getIt<NavigationService>().showSnackBar('jobs.jobAdded'.tr());
|
||||
emit(JobsStateWithJobs(newJobsList, state.serverJobList));
|
||||
emit(JobsStateWithJobs(newJobsList));
|
||||
}
|
||||
}
|
||||
|
||||
void createShhJobIfNotExist(final CreateSSHKeyJob job) {
|
||||
final List<ClientJob> newJobsList = <ClientJob>[];
|
||||
final List<Job> newJobsList = <Job>[];
|
||||
if (state is JobsStateWithJobs) {
|
||||
newJobsList.addAll((state as JobsStateWithJobs).clientJobList);
|
||||
newJobsList.addAll((state as JobsStateWithJobs).jobList);
|
||||
}
|
||||
final bool isExistInJobList =
|
||||
newJobsList.any((final el) => el is CreateSSHKeyJob);
|
||||
if (!isExistInJobList) {
|
||||
newJobsList.add(job);
|
||||
getIt<NavigationService>().showSnackBar('jobs.jobAdded'.tr());
|
||||
emit(JobsStateWithJobs(newJobsList, state.serverJobList));
|
||||
emit(JobsStateWithJobs(newJobsList));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> rebootServer() async {
|
||||
emit(JobsStateLoading(state.serverJobList));
|
||||
emit(JobsStateLoading());
|
||||
final bool isSuccessful = await api.reboot();
|
||||
if (isSuccessful) {
|
||||
getIt<NavigationService>().showSnackBar('jobs.rebootSuccess'.tr());
|
||||
} else {
|
||||
getIt<NavigationService>().showSnackBar('jobs.rebootFailed'.tr());
|
||||
}
|
||||
emit(JobsStateEmpty(state.serverJobList));
|
||||
emit(JobsStateEmpty());
|
||||
}
|
||||
|
||||
Future<void> upgradeServer() async {
|
||||
emit(JobsStateLoading(state.serverJobList));
|
||||
emit(JobsStateLoading());
|
||||
final bool isPullSuccessful = await api.pullConfigurationUpdate();
|
||||
final bool isSuccessful = await api.upgrade();
|
||||
if (isSuccessful) {
|
||||
|
@ -97,15 +93,15 @@ class JobsCubit extends Cubit<JobsState> {
|
|||
} else {
|
||||
getIt<NavigationService>().showSnackBar('jobs.upgradeFailed'.tr());
|
||||
}
|
||||
emit(JobsStateEmpty(state.serverJobList));
|
||||
emit(JobsStateEmpty());
|
||||
}
|
||||
|
||||
Future<void> applyAll() async {
|
||||
if (state is JobsStateWithJobs) {
|
||||
final List<ClientJob> jobs = (state as JobsStateWithJobs).clientJobList;
|
||||
emit(JobsStateLoading(state.serverJobList));
|
||||
final List<Job> jobs = (state as JobsStateWithJobs).jobList;
|
||||
emit(JobsStateLoading());
|
||||
bool hasServiceJobs = false;
|
||||
for (final ClientJob job in jobs) {
|
||||
for (final Job job in jobs) {
|
||||
if (job is CreateUserJob) {
|
||||
await usersCubit.createUser(job.user);
|
||||
}
|
||||
|
@ -126,45 +122,11 @@ class JobsCubit extends Cubit<JobsState> {
|
|||
|
||||
await api.pullConfigurationUpdate();
|
||||
await api.apply();
|
||||
|
||||
if (hasServiceJobs) {
|
||||
await servicesCubit.load();
|
||||
}
|
||||
|
||||
emit(JobsStateEmpty(state.serverJobList));
|
||||
emit(JobsStateEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> resetRequestsTimer() async {
|
||||
const duration = Duration(seconds: 1);
|
||||
Timer.periodic(
|
||||
duration,
|
||||
(final timer) async {
|
||||
if (timer.tick >= 10) {
|
||||
final List<ServerJob> serverJobs = await api.getServerJobs();
|
||||
final List<ServerJob> newServerJobs = [];
|
||||
for (final ServerJob job in serverJobs) {
|
||||
if (job.status == 'FINISHED') {
|
||||
await api.removeApiJob(job.uid);
|
||||
} else {
|
||||
newServerJobs.add(job);
|
||||
}
|
||||
}
|
||||
|
||||
if (state is JobsStateWithJobs) {
|
||||
emit(
|
||||
JobsStateWithJobs(
|
||||
(state as JobsStateWithJobs).clientJobList,
|
||||
newServerJobs,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
emit(
|
||||
JobsStateEmpty(newServerJobs),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,28 @@
|
|||
part of 'jobs_cubit.dart';
|
||||
|
||||
abstract class JobsState extends Equatable {
|
||||
const JobsState(this.serverJobList);
|
||||
final List<ServerJob> serverJobList;
|
||||
@override
|
||||
List<Object?> get props => [serverJobList];
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
class JobsStateLoading extends JobsState {
|
||||
const JobsStateLoading(super.serverJobList);
|
||||
}
|
||||
class JobsStateLoading extends JobsState {}
|
||||
|
||||
class JobsStateEmpty extends JobsState {
|
||||
const JobsStateEmpty(super.serverJobList);
|
||||
}
|
||||
class JobsStateEmpty extends JobsState {}
|
||||
|
||||
class JobsStateWithJobs extends JobsState {
|
||||
const JobsStateWithJobs(this.clientJobList, super.serverJobList);
|
||||
final List<ClientJob> clientJobList;
|
||||
JobsStateWithJobs(this.jobList);
|
||||
final List<Job> jobList;
|
||||
|
||||
JobsState removeById(final String id) {
|
||||
final List<ClientJob> newJobsList =
|
||||
clientJobList.where((final element) => element.id != id).toList();
|
||||
final List<Job> newJobsList =
|
||||
jobList.where((final element) => element.id != id).toList();
|
||||
|
||||
if (newJobsList.isEmpty) {
|
||||
return JobsStateEmpty(serverJobList);
|
||||
return JobsStateEmpty();
|
||||
}
|
||||
return JobsStateWithJobs(newJobsList, serverJobList);
|
||||
return JobsStateWithJobs(newJobsList);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [...super.props, clientJobList];
|
||||
List<Object?> get props => jobList;
|
||||
}
|
||||
|
|
|
@ -1,114 +0,0 @@
|
|||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_factory_creator.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/server_provider_factory.dart';
|
||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_storage/disk_status.dart';
|
||||
|
||||
part 'provider_volume_state.dart';
|
||||
|
||||
class ApiProviderVolumeCubit
|
||||
extends ServerInstallationDependendCubit<ApiProviderVolumeState> {
|
||||
ApiProviderVolumeCubit(final ServerInstallationCubit serverInstallationCubit)
|
||||
: super(serverInstallationCubit, const ApiProviderVolumeState.initial()) {
|
||||
final serverDetails = getIt<ApiConfigModel>().serverDetails;
|
||||
providerApi = serverDetails == null
|
||||
? null
|
||||
: VolumeApiFactoryCreator.createVolumeProviderApiFactory(
|
||||
getIt<ApiConfigModel>().serverDetails!.provider,
|
||||
);
|
||||
}
|
||||
|
||||
VolumeProviderApiFactory? providerApi;
|
||||
|
||||
@override
|
||||
Future<void> load() async {
|
||||
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||
_refetch();
|
||||
}
|
||||
}
|
||||
|
||||
Future<double?> getPricePerGb() async =>
|
||||
providerApi!.getVolumeProvider().getPricePerGb();
|
||||
|
||||
Future<void> refresh() async {
|
||||
emit(const ApiProviderVolumeState([], LoadingStatus.refreshing));
|
||||
_refetch();
|
||||
}
|
||||
|
||||
Future<void> _refetch() async {
|
||||
if (providerApi == null) {
|
||||
return emit(const ApiProviderVolumeState([], LoadingStatus.error));
|
||||
}
|
||||
|
||||
final List<ServerVolume> volumes =
|
||||
await providerApi!.getVolumeProvider().getVolumes();
|
||||
|
||||
if (volumes.isEmpty) {
|
||||
return emit(const ApiProviderVolumeState([], LoadingStatus.error));
|
||||
}
|
||||
|
||||
emit(ApiProviderVolumeState(volumes, LoadingStatus.success));
|
||||
}
|
||||
|
||||
Future<void> attachVolume(final DiskVolume volume) async {
|
||||
final ServerHostingDetails server = getIt<ApiConfigModel>().serverDetails!;
|
||||
await providerApi!
|
||||
.getVolumeProvider()
|
||||
.attachVolume(volume.providerVolume!.id, server.id);
|
||||
refresh();
|
||||
}
|
||||
|
||||
Future<void> detachVolume(final DiskVolume volume) async {
|
||||
await providerApi!
|
||||
.getVolumeProvider()
|
||||
.detachVolume(volume.providerVolume!.id);
|
||||
refresh();
|
||||
}
|
||||
|
||||
Future<bool> resizeVolume(
|
||||
final DiskVolume volume,
|
||||
final int newSizeGb,
|
||||
) async {
|
||||
final bool resized = await providerApi!.getVolumeProvider().resizeVolume(
|
||||
volume.providerVolume!.id,
|
||||
newSizeGb,
|
||||
);
|
||||
|
||||
if (!resized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await ServerApi().resizeVolume(volume.name);
|
||||
refresh();
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<void> createVolume() async {
|
||||
final ServerVolume? volume =
|
||||
await providerApi!.getVolumeProvider().createVolume();
|
||||
|
||||
final diskVolume = DiskVolume();
|
||||
diskVolume.providerVolume = volume;
|
||||
await attachVolume(diskVolume);
|
||||
|
||||
await Future.delayed(const Duration(seconds: 10));
|
||||
|
||||
await ServerApi().mountVolume(volume!.name);
|
||||
refresh();
|
||||
}
|
||||
|
||||
Future<void> deleteVolume(final DiskVolume volume) async {
|
||||
await providerApi!
|
||||
.getVolumeProvider()
|
||||
.deleteVolume(volume.providerVolume!.id);
|
||||
refresh();
|
||||
}
|
||||
|
||||
@override
|
||||
void clear() {
|
||||
emit(const ApiProviderVolumeState.initial());
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
part of 'provider_volume_cubit.dart';
|
||||
|
||||
class ApiProviderVolumeState extends ServerInstallationDependendState {
|
||||
const ApiProviderVolumeState(this._volumes, this.status);
|
||||
|
||||
const ApiProviderVolumeState.initial()
|
||||
: this(const [], LoadingStatus.uninitialized);
|
||||
final List<ServerVolume> _volumes;
|
||||
final LoadingStatus status;
|
||||
|
||||
List<ServerVolume> get volumes => _volumes;
|
||||
|
||||
ApiProviderVolumeState copyWith({
|
||||
final List<ServerVolume>? volumes,
|
||||
final LoadingStatus? status,
|
||||
}) =>
|
||||
ApiProviderVolumeState(
|
||||
volumes ?? _volumes,
|
||||
status ?? this.status,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [_volumes];
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/json/recovery_token_status.dart';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/hetzner/hetzner.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/hetzner.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/models/json/auto_upgrade_settings.dart';
|
||||
import 'package:selfprivacy/logic/models/json/hetzner_server_info.dart';
|
||||
import 'package:selfprivacy/logic/models/timezone_settings.dart';
|
||||
|
|
|
@ -4,14 +4,10 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/dns_provider_factory.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/provider_api_settings.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backblaze_credential.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_disk_volume.dart';
|
||||
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
||||
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_repository.dart';
|
||||
|
@ -53,40 +49,13 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
}
|
||||
}
|
||||
|
||||
RegExp getServerProviderApiTokenValidation() =>
|
||||
repository.serverProviderApiFactory!
|
||||
.getServerProvider()
|
||||
.getApiTokenValidation();
|
||||
|
||||
RegExp getDnsProviderApiTokenValidation() => repository.dnsProviderApiFactory!
|
||||
.getDnsProvider()
|
||||
.getApiTokenValidation();
|
||||
|
||||
Future<bool> isServerProviderApiTokenValid(
|
||||
final String providerToken,
|
||||
) async =>
|
||||
repository.serverProviderApiFactory!
|
||||
.getServerProvider(
|
||||
settings: const ProviderApiSettings(isWithToken: false),
|
||||
)
|
||||
.isApiTokenValid(providerToken);
|
||||
|
||||
Future<bool> isDnsProviderApiTokenValid(
|
||||
final String providerToken,
|
||||
) async =>
|
||||
repository.dnsProviderApiFactory!
|
||||
.getDnsProvider(
|
||||
settings: const DnsProviderApiSettings(isWithToken: false),
|
||||
)
|
||||
.isApiTokenValid(providerToken);
|
||||
|
||||
void setHetznerKey(final String hetznerKey) async {
|
||||
await repository.saveHetznerKey(hetznerKey);
|
||||
|
||||
if (state is ServerInstallationRecovery) {
|
||||
emit(
|
||||
(state as ServerInstallationRecovery).copyWith(
|
||||
providerApiToken: hetznerKey,
|
||||
hetznerKey: hetznerKey,
|
||||
currentStep: RecoveryStep.serverSelection,
|
||||
),
|
||||
);
|
||||
|
@ -94,9 +63,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
}
|
||||
|
||||
emit(
|
||||
(state as ServerInstallationNotFinished).copyWith(
|
||||
providerApiToken: hetznerKey,
|
||||
),
|
||||
(state as ServerInstallationNotFinished).copyWith(hetznerKey: hetznerKey),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -150,7 +117,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
|
||||
Future<void> onSuccess(final ServerHostingDetails serverDetails) async {
|
||||
await repository.createDnsRecords(
|
||||
serverDetails,
|
||||
serverDetails.ip4,
|
||||
state.serverDomain!,
|
||||
onCancel: onCancel,
|
||||
);
|
||||
|
@ -200,7 +167,6 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
final ServerHostingDetails server = await repository.startServer(
|
||||
dataState.serverDetails!,
|
||||
);
|
||||
|
||||
await repository.saveServerDetails(server);
|
||||
await repository.saveIsServerStarted(true);
|
||||
|
||||
|
@ -326,22 +292,10 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
final bool isServerWorking = await repository.isHttpServerWorking();
|
||||
|
||||
if (isServerWorking) {
|
||||
bool dkimCreated = true;
|
||||
try {
|
||||
await repository.createDkimRecord(dataState.serverDomain!);
|
||||
} catch (e) {
|
||||
dkimCreated = false;
|
||||
}
|
||||
if (dkimCreated) {
|
||||
await repository.saveHasFinalChecked(true);
|
||||
emit(dataState.finish());
|
||||
} else {
|
||||
runDelayed(
|
||||
finishCheckIfServerIsOkay,
|
||||
const Duration(seconds: 60),
|
||||
dataState,
|
||||
);
|
||||
}
|
||||
await repository.createDkimRecord(dataState.serverDomain!);
|
||||
await repository.saveHasFinalChecked(true);
|
||||
|
||||
emit(dataState.finish());
|
||||
} else {
|
||||
runDelayed(
|
||||
finishCheckIfServerIsOkay,
|
||||
|
@ -463,11 +417,11 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
),
|
||||
);
|
||||
break;
|
||||
case RecoveryStep.cloudflareToken:
|
||||
repository.deleteServerDetails();
|
||||
case RecoveryStep.serverSelection:
|
||||
repository.deleteHetznerKey();
|
||||
emit(
|
||||
dataState.copyWith(
|
||||
currentStep: RecoveryStep.serverSelection,
|
||||
currentStep: RecoveryStep.hetznerToken,
|
||||
),
|
||||
);
|
||||
break;
|
||||
|
@ -510,7 +464,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
final ServerInstallationRecovery dataState =
|
||||
state as ServerInstallationRecovery;
|
||||
final List<ServerBasicInfo> servers =
|
||||
await repository.getServersOnProviderAccount();
|
||||
await repository.getServersOnHetznerAccount();
|
||||
final Iterable<ServerBasicInfoWithValidators> validated = servers.map(
|
||||
(final ServerBasicInfo server) =>
|
||||
ServerBasicInfoWithValidators.fromServerBasicInfo(
|
||||
|
@ -537,9 +491,6 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
volume: ServerVolume(
|
||||
id: server.volumeId,
|
||||
name: 'recovered_volume',
|
||||
sizeByte: 0,
|
||||
serverId: server.id,
|
||||
linuxDevice: '',
|
||||
),
|
||||
apiToken: dataState.serverDetails!.apiToken,
|
||||
provider: ServerProvider.hetzner,
|
||||
|
@ -613,7 +564,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
print('================================');
|
||||
print('ServerInstallationState changed!');
|
||||
print('Current type: ${change.nextState.runtimeType}');
|
||||
print('Hetzner key: ${change.nextState.providerApiToken}');
|
||||
print('Hetzner key: ${change.nextState.hetznerKey}');
|
||||
print('Cloudflare key: ${change.nextState.cloudFlareKey}');
|
||||
print('Domain: ${change.nextState.serverDomain}');
|
||||
print('BackblazeCredential: ${change.nextState.backblazeCredential}');
|
||||
|
@ -646,7 +597,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
await repository.deleteServerRelatedRecords();
|
||||
emit(
|
||||
ServerInstallationNotFinished(
|
||||
providerApiToken: state.providerApiToken,
|
||||
hetznerKey: state.hetznerKey,
|
||||
serverDomain: state.serverDomain,
|
||||
cloudFlareKey: state.cloudFlareKey,
|
||||
backblazeCredential: state.backblazeCredential,
|
||||
|
|
|
@ -9,18 +9,16 @@ import 'package:hive/hive.dart';
|
|||
import 'package:pub_semver/pub_semver.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/config/hive_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/api_factory_creator.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/dns_provider.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/dns_provider_factory.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/server_provider.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server_providers/server_provider_factory.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/cloudflare.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/hetzner.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backblaze_credential.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
import 'package:selfprivacy/logic/models/json/device_token.dart';
|
||||
import 'package:selfprivacy/logic/models/json/hetzner_server_info.dart';
|
||||
import 'package:selfprivacy/logic/models/message.dart';
|
||||
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
||||
import 'package:selfprivacy/ui/components/action_button/action_button.dart';
|
||||
|
@ -41,17 +39,9 @@ class ServerAuthorizationException implements Exception {
|
|||
class ServerInstallationRepository {
|
||||
Box box = Hive.box(BNames.serverInstallationBox);
|
||||
Box<User> usersBox = Hive.box(BNames.usersBox);
|
||||
ServerProviderApiFactory? serverProviderApiFactory =
|
||||
ApiFactoryCreator.createServerProviderApiFactory(
|
||||
ServerProvider.hetzner, // TODO: HARDCODE FOR NOW!!!
|
||||
); // TODO: Remove when provider selection is implemented.
|
||||
DnsProviderApiFactory? dnsProviderApiFactory =
|
||||
ApiFactoryCreator.createDnsProviderApiFactory(
|
||||
DnsProvider.cloudflare, // TODO: HARDCODE FOR NOW!!!
|
||||
);
|
||||
|
||||
Future<ServerInstallationState> load() async {
|
||||
final String? providerApiToken = getIt<ApiConfigModel>().hetznerKey;
|
||||
final String? hetznerToken = getIt<ApiConfigModel>().hetznerKey;
|
||||
final String? cloudflareToken = getIt<ApiConfigModel>().cloudFlareKey;
|
||||
final ServerDomain? serverDomain = getIt<ApiConfigModel>().serverDomain;
|
||||
final BackblazeCredential? backblazeCredential =
|
||||
|
@ -59,23 +49,9 @@ class ServerInstallationRepository {
|
|||
final ServerHostingDetails? serverDetails =
|
||||
getIt<ApiConfigModel>().serverDetails;
|
||||
|
||||
if (serverDetails != null &&
|
||||
serverDetails.provider != ServerProvider.unknown) {
|
||||
serverProviderApiFactory =
|
||||
ApiFactoryCreator.createServerProviderApiFactory(
|
||||
serverDetails.provider,
|
||||
);
|
||||
}
|
||||
|
||||
if (serverDomain != null && serverDomain.provider != DnsProvider.unknown) {
|
||||
dnsProviderApiFactory = ApiFactoryCreator.createDnsProviderApiFactory(
|
||||
serverDomain.provider,
|
||||
);
|
||||
}
|
||||
|
||||
if (box.get(BNames.hasFinalChecked, defaultValue: false)) {
|
||||
return ServerInstallationFinished(
|
||||
providerApiToken: providerApiToken!,
|
||||
hetznerKey: hetznerToken!,
|
||||
cloudFlareKey: cloudflareToken!,
|
||||
serverDomain: serverDomain!,
|
||||
backblazeCredential: backblazeCredential!,
|
||||
|
@ -92,14 +68,14 @@ class ServerInstallationRepository {
|
|||
if (box.get(BNames.isRecoveringServer, defaultValue: false) &&
|
||||
serverDomain != null) {
|
||||
return ServerInstallationRecovery(
|
||||
providerApiToken: providerApiToken,
|
||||
hetznerKey: hetznerToken,
|
||||
cloudFlareKey: cloudflareToken,
|
||||
serverDomain: serverDomain,
|
||||
backblazeCredential: backblazeCredential,
|
||||
serverDetails: serverDetails,
|
||||
rootUser: box.get(BNames.rootUser),
|
||||
currentStep: _getCurrentRecoveryStep(
|
||||
providerApiToken,
|
||||
hetznerToken,
|
||||
cloudflareToken,
|
||||
serverDomain,
|
||||
serverDetails,
|
||||
|
@ -109,7 +85,7 @@ class ServerInstallationRepository {
|
|||
}
|
||||
|
||||
return ServerInstallationNotFinished(
|
||||
providerApiToken: providerApiToken,
|
||||
hetznerKey: hetznerToken,
|
||||
cloudFlareKey: cloudflareToken,
|
||||
serverDomain: serverDomain,
|
||||
backblazeCredential: backblazeCredential,
|
||||
|
@ -154,24 +130,20 @@ class ServerInstallationRepository {
|
|||
Future<ServerHostingDetails> startServer(
|
||||
final ServerHostingDetails hetznerServer,
|
||||
) async {
|
||||
ServerHostingDetails serverDetails;
|
||||
|
||||
final ServerProviderApi api = serverProviderApiFactory!.getServerProvider();
|
||||
serverDetails = await api.powerOn();
|
||||
final HetznerApi hetznerApi = HetznerApi();
|
||||
final ServerHostingDetails serverDetails = await hetznerApi.powerOn();
|
||||
|
||||
return serverDetails;
|
||||
}
|
||||
|
||||
Future<String?> getDomainId(final String token, final String domain) async {
|
||||
final DnsProviderApi dnsProviderApi = dnsProviderApiFactory!.getDnsProvider(
|
||||
settings: DnsProviderApiSettings(
|
||||
isWithToken: false,
|
||||
customToken: token,
|
||||
),
|
||||
final CloudflareApi cloudflareApi = CloudflareApi(
|
||||
isWithToken: false,
|
||||
customToken: token,
|
||||
);
|
||||
|
||||
try {
|
||||
final String domainId = await dnsProviderApi.getZoneId(domain);
|
||||
final String domainId = await cloudflareApi.getZoneId(domain);
|
||||
return domainId;
|
||||
} on DomainNotFoundException {
|
||||
return null;
|
||||
|
@ -236,14 +208,18 @@ class ServerInstallationRepository {
|
|||
required final Future<void> Function(ServerHostingDetails serverDetails)
|
||||
onSuccess,
|
||||
}) async {
|
||||
final ServerProviderApi api = serverProviderApiFactory!.getServerProvider();
|
||||
final HetznerApi hetznerApi = HetznerApi();
|
||||
late ServerVolume dataBase;
|
||||
|
||||
try {
|
||||
final ServerHostingDetails? serverDetails = await api.createServer(
|
||||
dnsApiToken: cloudFlareKey,
|
||||
dataBase = await hetznerApi.createVolume();
|
||||
|
||||
final ServerHostingDetails? serverDetails = await hetznerApi.createServer(
|
||||
cloudFlareKey: cloudFlareKey,
|
||||
rootUser: rootUser,
|
||||
domainName: domainName,
|
||||
dataBase: dataBase,
|
||||
);
|
||||
|
||||
if (serverDetails == null) {
|
||||
print('Server is not initialized!');
|
||||
return;
|
||||
|
@ -262,58 +238,17 @@ class ServerInstallationRepository {
|
|||
text: 'basis.delete'.tr(),
|
||||
isRed: true,
|
||||
onPressed: () async {
|
||||
await api.deleteServer(
|
||||
await hetznerApi.deleteSelfprivacyServerAndAllVolumes(
|
||||
domainName: domainName,
|
||||
);
|
||||
|
||||
ServerHostingDetails? serverDetails;
|
||||
try {
|
||||
serverDetails = await api.createServer(
|
||||
dnsApiToken: cloudFlareKey,
|
||||
rootUser: rootUser,
|
||||
domainName: domainName,
|
||||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
|
||||
if (serverDetails == null) {
|
||||
print('Server is not initialized!');
|
||||
return;
|
||||
}
|
||||
await saveServerDetails(serverDetails);
|
||||
onSuccess(serverDetails);
|
||||
},
|
||||
),
|
||||
ActionButton(
|
||||
text: 'basis.cancel'.tr(),
|
||||
onPressed: onCancel,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else if (e.response!.data['error']['code'] == 'resource_unavailable') {
|
||||
final NavigationService nav = getIt.get<NavigationService>();
|
||||
nav.showPopUpDialog(
|
||||
BrandAlert(
|
||||
title: 'modals.1_1'.tr(),
|
||||
contentText: 'modals.2_2'.tr(),
|
||||
actions: [
|
||||
ActionButton(
|
||||
text: 'modals.7'.tr(),
|
||||
isRed: true,
|
||||
onPressed: () async {
|
||||
ServerHostingDetails? serverDetails;
|
||||
try {
|
||||
serverDetails = await api.createServer(
|
||||
dnsApiToken: cloudFlareKey,
|
||||
rootUser: rootUser,
|
||||
domainName: domainName,
|
||||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
|
||||
final ServerHostingDetails? serverDetails =
|
||||
await hetznerApi.createServer(
|
||||
cloudFlareKey: cloudFlareKey,
|
||||
rootUser: rootUser,
|
||||
domainName: domainName,
|
||||
dataBase: dataBase,
|
||||
);
|
||||
if (serverDetails == null) {
|
||||
print('Server is not initialized!');
|
||||
return;
|
||||
|
@ -333,27 +268,25 @@ class ServerInstallationRepository {
|
|||
}
|
||||
}
|
||||
|
||||
Future<bool> createDnsRecords(
|
||||
final ServerHostingDetails serverDetails,
|
||||
final ServerDomain domain, {
|
||||
Future<void> createDnsRecords(
|
||||
final String ip4,
|
||||
final ServerDomain cloudFlareDomain, {
|
||||
required final void Function() onCancel,
|
||||
}) async {
|
||||
final DnsProviderApi dnsProviderApi =
|
||||
dnsProviderApiFactory!.getDnsProvider();
|
||||
final ServerProviderApi serverApi =
|
||||
serverProviderApiFactory!.getServerProvider();
|
||||
final CloudflareApi cloudflareApi = CloudflareApi();
|
||||
|
||||
await dnsProviderApi.removeSimilarRecords(
|
||||
ip4: serverDetails.ip4,
|
||||
domain: domain,
|
||||
await cloudflareApi.removeSimilarRecords(
|
||||
ip4: ip4,
|
||||
cloudFlareDomain: cloudFlareDomain,
|
||||
);
|
||||
|
||||
try {
|
||||
await dnsProviderApi.createMultipleDnsRecords(
|
||||
ip4: serverDetails.ip4,
|
||||
domain: domain,
|
||||
await cloudflareApi.createMultipleDnsRecords(
|
||||
ip4: ip4,
|
||||
cloudFlareDomain: cloudFlareDomain,
|
||||
);
|
||||
} on DioError catch (e) {
|
||||
final HetznerApi hetznerApi = HetznerApi();
|
||||
final NavigationService nav = getIt.get<NavigationService>();
|
||||
nav.showPopUpDialog(
|
||||
BrandAlert(
|
||||
|
@ -366,8 +299,8 @@ class ServerInstallationRepository {
|
|||
text: 'basis.delete'.tr(),
|
||||
isRed: true,
|
||||
onPressed: () async {
|
||||
await serverApi.deleteServer(
|
||||
domainName: domain.domainName,
|
||||
await hetznerApi.deleteSelfprivacyServerAndAllVolumes(
|
||||
domainName: cloudFlareDomain.domainName,
|
||||
);
|
||||
|
||||
onCancel();
|
||||
|
@ -380,46 +313,42 @@ class ServerInstallationRepository {
|
|||
],
|
||||
),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
await serverApi.createReverseDns(
|
||||
serverDetails: serverDetails,
|
||||
domain: domain,
|
||||
await HetznerApi().createReverseDns(
|
||||
ip4: ip4,
|
||||
domainName: cloudFlareDomain.domainName,
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<void> createDkimRecord(final ServerDomain cloudFlareDomain) async {
|
||||
final DnsProviderApi dnsProviderApi =
|
||||
dnsProviderApiFactory!.getDnsProvider();
|
||||
final CloudflareApi cloudflareApi = CloudflareApi();
|
||||
final ServerApi api = ServerApi();
|
||||
|
||||
String dkimRecordString = '';
|
||||
try {
|
||||
dkimRecordString = await api.getDkim();
|
||||
} catch (e) {
|
||||
print(e);
|
||||
rethrow;
|
||||
}
|
||||
final String? dkimRecordString = await api.getDkim();
|
||||
|
||||
await dnsProviderApi.setDkim(dkimRecordString, cloudFlareDomain);
|
||||
await cloudflareApi.setDkim(dkimRecordString ?? '', cloudFlareDomain);
|
||||
}
|
||||
|
||||
Future<bool> isHttpServerWorking() async {
|
||||
final ServerApi api = ServerApi();
|
||||
return api.isHttpServerWorking();
|
||||
final bool isHttpServerWorking = await api.isHttpServerWorking();
|
||||
try {
|
||||
await api.getDkim();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return isHttpServerWorking;
|
||||
}
|
||||
|
||||
Future<ServerHostingDetails> restart() async {
|
||||
final ServerProviderApi api = serverProviderApiFactory!.getServerProvider();
|
||||
return api.restart();
|
||||
final HetznerApi hetznerApi = HetznerApi();
|
||||
return hetznerApi.reset();
|
||||
}
|
||||
|
||||
Future<ServerHostingDetails> powerOn() async {
|
||||
final ServerProviderApi api = serverProviderApiFactory!.getServerProvider();
|
||||
return api.powerOn();
|
||||
final HetznerApi hetznerApi = HetznerApi();
|
||||
return hetznerApi.powerOn();
|
||||
}
|
||||
|
||||
Future<ServerRecoveryCapabilities> getRecoveryCapabilities(
|
||||
|
@ -510,9 +439,6 @@ class ServerInstallationRepository {
|
|||
volume: ServerVolume(
|
||||
id: 0,
|
||||
name: '',
|
||||
sizeByte: 0,
|
||||
serverId: 0,
|
||||
linuxDevice: '',
|
||||
),
|
||||
provider: ServerProvider.unknown,
|
||||
id: 0,
|
||||
|
@ -547,9 +473,6 @@ class ServerInstallationRepository {
|
|||
volume: ServerVolume(
|
||||
id: 0,
|
||||
name: '',
|
||||
sizeByte: 0,
|
||||
serverId: 0,
|
||||
linuxDevice: '',
|
||||
),
|
||||
provider: ServerProvider.unknown,
|
||||
id: 0,
|
||||
|
@ -584,9 +507,6 @@ class ServerInstallationRepository {
|
|||
volume: ServerVolume(
|
||||
id: 0,
|
||||
name: '',
|
||||
serverId: 0,
|
||||
sizeByte: 0,
|
||||
linuxDevice: '',
|
||||
),
|
||||
provider: ServerProvider.unknown,
|
||||
id: 0,
|
||||
|
@ -612,9 +532,6 @@ class ServerInstallationRepository {
|
|||
volume: ServerVolume(
|
||||
id: 0,
|
||||
name: '',
|
||||
sizeByte: 0,
|
||||
serverId: 0,
|
||||
linuxDevice: '',
|
||||
),
|
||||
provider: ServerProvider.unknown,
|
||||
id: 0,
|
||||
|
@ -658,9 +575,21 @@ class ServerInstallationRepository {
|
|||
}
|
||||
}
|
||||
|
||||
Future<List<ServerBasicInfo>> getServersOnProviderAccount() async {
|
||||
final ServerProviderApi api = serverProviderApiFactory!.getServerProvider();
|
||||
return api.getServers();
|
||||
Future<List<ServerBasicInfo>> getServersOnHetznerAccount() async {
|
||||
final HetznerApi hetznerApi = HetznerApi();
|
||||
final List<HetznerServerInfo> servers = await hetznerApi.getServers();
|
||||
return servers
|
||||
.map(
|
||||
(final HetznerServerInfo server) => ServerBasicInfo(
|
||||
id: server.id,
|
||||
name: server.name,
|
||||
ip: server.publicNet.ipv4.ip,
|
||||
reverseDns: server.publicNet.ipv4.reverseDns,
|
||||
created: server.created,
|
||||
volumeId: server.volumes.isNotEmpty ? server.volumes[0] : 0,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<void> saveServerDetails(
|
||||
|
@ -669,11 +598,6 @@ class ServerInstallationRepository {
|
|||
await getIt<ApiConfigModel>().storeServerDetails(serverDetails);
|
||||
}
|
||||
|
||||
Future<void> deleteServerDetails() async {
|
||||
await box.delete(BNames.serverDetails);
|
||||
getIt<ApiConfigModel>().init();
|
||||
}
|
||||
|
||||
Future<void> saveHetznerKey(final String key) async {
|
||||
print('saved');
|
||||
await getIt<ApiConfigModel>().storeHetznerKey(key);
|
||||
|
@ -690,20 +614,10 @@ class ServerInstallationRepository {
|
|||
await getIt<ApiConfigModel>().storeBackblazeCredential(backblazeCredential);
|
||||
}
|
||||
|
||||
Future<void> deleteBackblazeKey() async {
|
||||
await box.delete(BNames.backblazeCredential);
|
||||
getIt<ApiConfigModel>().init();
|
||||
}
|
||||
|
||||
Future<void> saveCloudFlareKey(final String key) async {
|
||||
await getIt<ApiConfigModel>().storeCloudFlareKey(key);
|
||||
}
|
||||
|
||||
Future<void> deleteCloudFlareKey() async {
|
||||
await box.delete(BNames.cloudFlareKey);
|
||||
getIt<ApiConfigModel>().init();
|
||||
}
|
||||
|
||||
Future<void> saveDomain(final ServerDomain serverDomain) async {
|
||||
await getIt<ApiConfigModel>().storeServerDomain(serverDomain);
|
||||
}
|
||||
|
@ -738,11 +652,10 @@ class ServerInstallationRepository {
|
|||
}
|
||||
|
||||
Future<void> deleteServer(final ServerDomain serverDomain) async {
|
||||
final ServerProviderApi api = serverProviderApiFactory!.getServerProvider();
|
||||
final DnsProviderApi dnsProviderApi =
|
||||
dnsProviderApiFactory!.getDnsProvider();
|
||||
final HetznerApi hetznerApi = HetznerApi();
|
||||
final CloudflareApi cloudFlare = CloudflareApi();
|
||||
|
||||
await api.deleteServer(
|
||||
await hetznerApi.deleteSelfprivacyServerAndAllVolumes(
|
||||
domainName: serverDomain.domainName,
|
||||
);
|
||||
|
||||
|
@ -753,7 +666,7 @@ class ServerInstallationRepository {
|
|||
await box.put(BNames.isLoading, false);
|
||||
await box.put(BNames.serverDetails, null);
|
||||
|
||||
await dnsProviderApi.removeSimilarRecords(domain: serverDomain);
|
||||
await cloudFlare.removeSimilarRecords(cloudFlareDomain: serverDomain);
|
||||
}
|
||||
|
||||
Future<void> deleteServerRelatedRecords() async {
|
||||
|
|
|
@ -2,7 +2,7 @@ part of '../server_installation/server_installation_cubit.dart';
|
|||
|
||||
abstract class ServerInstallationState extends Equatable {
|
||||
const ServerInstallationState({
|
||||
required this.providerApiToken,
|
||||
required this.hetznerKey,
|
||||
required this.cloudFlareKey,
|
||||
required this.backblazeCredential,
|
||||
required this.serverDomain,
|
||||
|
@ -15,7 +15,7 @@ abstract class ServerInstallationState extends Equatable {
|
|||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
providerApiToken,
|
||||
hetznerKey,
|
||||
cloudFlareKey,
|
||||
backblazeCredential,
|
||||
serverDomain,
|
||||
|
@ -25,7 +25,7 @@ abstract class ServerInstallationState extends Equatable {
|
|||
isServerResetedFirstTime,
|
||||
];
|
||||
|
||||
final String? providerApiToken;
|
||||
final String? hetznerKey;
|
||||
final String? cloudFlareKey;
|
||||
final BackblazeCredential? backblazeCredential;
|
||||
final ServerDomain? serverDomain;
|
||||
|
@ -35,11 +35,11 @@ abstract class ServerInstallationState extends Equatable {
|
|||
final bool isServerResetedFirstTime;
|
||||
final bool isServerResetedSecondTime;
|
||||
|
||||
bool get isServerProviderFilled => providerApiToken != null;
|
||||
bool get isDnsProviderFilled => cloudFlareKey != null;
|
||||
bool get isBackupsProviderFilled => backblazeCredential != null;
|
||||
bool get isDomainSelected => serverDomain != null;
|
||||
bool get isPrimaryUserFilled => rootUser != null;
|
||||
bool get isHetznerFilled => hetznerKey != null;
|
||||
bool get isCloudFlareFilled => cloudFlareKey != null;
|
||||
bool get isBackblazeFilled => backblazeCredential != null;
|
||||
bool get isDomainFilled => serverDomain != null;
|
||||
bool get isUserFilled => rootUser != null;
|
||||
bool get isServerCreated => serverDetails != null;
|
||||
|
||||
bool get isFullyInitilized => _fulfilementList.every((final el) => el!);
|
||||
|
@ -58,11 +58,11 @@ abstract class ServerInstallationState extends Equatable {
|
|||
|
||||
List<bool?> get _fulfilementList {
|
||||
final List<bool> res = [
|
||||
isServerProviderFilled,
|
||||
isDnsProviderFilled,
|
||||
isBackupsProviderFilled,
|
||||
isDomainSelected,
|
||||
isPrimaryUserFilled,
|
||||
isHetznerFilled,
|
||||
isCloudFlareFilled,
|
||||
isBackblazeFilled,
|
||||
isDomainFilled,
|
||||
isUserFilled,
|
||||
isServerCreated,
|
||||
isServerStarted,
|
||||
isServerResetedFirstTime,
|
||||
|
@ -80,7 +80,7 @@ class TimerState extends ServerInstallationNotFinished {
|
|||
this.timerStart,
|
||||
this.duration,
|
||||
}) : super(
|
||||
providerApiToken: dataState.providerApiToken,
|
||||
hetznerKey: dataState.hetznerKey,
|
||||
cloudFlareKey: dataState.cloudFlareKey,
|
||||
backblazeCredential: dataState.backblazeCredential,
|
||||
serverDomain: dataState.serverDomain,
|
||||
|
@ -124,7 +124,7 @@ class ServerInstallationNotFinished extends ServerInstallationState {
|
|||
required final super.isServerResetedSecondTime,
|
||||
required final this.isLoading,
|
||||
required this.dnsMatches,
|
||||
final super.providerApiToken,
|
||||
final super.hetznerKey,
|
||||
final super.cloudFlareKey,
|
||||
final super.backblazeCredential,
|
||||
final super.serverDomain,
|
||||
|
@ -136,7 +136,7 @@ class ServerInstallationNotFinished extends ServerInstallationState {
|
|||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
providerApiToken,
|
||||
hetznerKey,
|
||||
cloudFlareKey,
|
||||
backblazeCredential,
|
||||
serverDomain,
|
||||
|
@ -149,7 +149,7 @@ class ServerInstallationNotFinished extends ServerInstallationState {
|
|||
];
|
||||
|
||||
ServerInstallationNotFinished copyWith({
|
||||
final String? providerApiToken,
|
||||
final String? hetznerKey,
|
||||
final String? cloudFlareKey,
|
||||
final BackblazeCredential? backblazeCredential,
|
||||
final ServerDomain? serverDomain,
|
||||
|
@ -162,7 +162,7 @@ class ServerInstallationNotFinished extends ServerInstallationState {
|
|||
final Map<String, bool>? dnsMatches,
|
||||
}) =>
|
||||
ServerInstallationNotFinished(
|
||||
providerApiToken: providerApiToken ?? this.providerApiToken,
|
||||
hetznerKey: hetznerKey ?? this.hetznerKey,
|
||||
cloudFlareKey: cloudFlareKey ?? this.cloudFlareKey,
|
||||
backblazeCredential: backblazeCredential ?? this.backblazeCredential,
|
||||
serverDomain: serverDomain ?? this.serverDomain,
|
||||
|
@ -178,7 +178,7 @@ class ServerInstallationNotFinished extends ServerInstallationState {
|
|||
);
|
||||
|
||||
ServerInstallationFinished finish() => ServerInstallationFinished(
|
||||
providerApiToken: providerApiToken!,
|
||||
hetznerKey: hetznerKey!,
|
||||
cloudFlareKey: cloudFlareKey!,
|
||||
backblazeCredential: backblazeCredential!,
|
||||
serverDomain: serverDomain!,
|
||||
|
@ -193,7 +193,7 @@ class ServerInstallationNotFinished extends ServerInstallationState {
|
|||
class ServerInstallationEmpty extends ServerInstallationNotFinished {
|
||||
const ServerInstallationEmpty()
|
||||
: super(
|
||||
providerApiToken: null,
|
||||
hetznerKey: null,
|
||||
cloudFlareKey: null,
|
||||
backblazeCredential: null,
|
||||
serverDomain: null,
|
||||
|
@ -209,7 +209,7 @@ class ServerInstallationEmpty extends ServerInstallationNotFinished {
|
|||
|
||||
class ServerInstallationFinished extends ServerInstallationState {
|
||||
const ServerInstallationFinished({
|
||||
required final String super.providerApiToken,
|
||||
required final String super.hetznerKey,
|
||||
required final String super.cloudFlareKey,
|
||||
required final BackblazeCredential super.backblazeCredential,
|
||||
required final ServerDomain super.serverDomain,
|
||||
|
@ -222,7 +222,7 @@ class ServerInstallationFinished extends ServerInstallationState {
|
|||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
providerApiToken,
|
||||
hetznerKey,
|
||||
cloudFlareKey,
|
||||
backblazeCredential,
|
||||
serverDomain,
|
||||
|
@ -260,7 +260,7 @@ class ServerInstallationRecovery extends ServerInstallationState {
|
|||
const ServerInstallationRecovery({
|
||||
required this.currentStep,
|
||||
required this.recoveryCapabilities,
|
||||
final super.providerApiToken,
|
||||
final super.hetznerKey,
|
||||
final super.cloudFlareKey,
|
||||
final super.backblazeCredential,
|
||||
final super.serverDomain,
|
||||
|
@ -276,7 +276,7 @@ class ServerInstallationRecovery extends ServerInstallationState {
|
|||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
providerApiToken,
|
||||
hetznerKey,
|
||||
cloudFlareKey,
|
||||
backblazeCredential,
|
||||
serverDomain,
|
||||
|
@ -288,7 +288,7 @@ class ServerInstallationRecovery extends ServerInstallationState {
|
|||
];
|
||||
|
||||
ServerInstallationRecovery copyWith({
|
||||
final String? providerApiToken,
|
||||
final String? hetznerKey,
|
||||
final String? cloudFlareKey,
|
||||
final BackblazeCredential? backblazeCredential,
|
||||
final ServerDomain? serverDomain,
|
||||
|
@ -298,7 +298,7 @@ class ServerInstallationRecovery extends ServerInstallationState {
|
|||
final ServerRecoveryCapabilities? recoveryCapabilities,
|
||||
}) =>
|
||||
ServerInstallationRecovery(
|
||||
providerApiToken: providerApiToken ?? this.providerApiToken,
|
||||
hetznerKey: hetznerKey ?? this.hetznerKey,
|
||||
cloudFlareKey: cloudFlareKey ?? this.cloudFlareKey,
|
||||
backblazeCredential: backblazeCredential ?? this.backblazeCredential,
|
||||
serverDomain: serverDomain ?? this.serverDomain,
|
||||
|
@ -309,7 +309,7 @@ class ServerInstallationRecovery extends ServerInstallationState {
|
|||
);
|
||||
|
||||
ServerInstallationFinished finish() => ServerInstallationFinished(
|
||||
providerApiToken: providerApiToken!,
|
||||
hetznerKey: hetznerKey!,
|
||||
cloudFlareKey: cloudFlareKey!,
|
||||
backblazeCredential: backblazeCredential!,
|
||||
serverDomain: serverDomain!,
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server.dart';
|
||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_disk_volume.dart';
|
||||
|
||||
part 'server_volume_state.dart';
|
||||
|
||||
class ApiServerVolumeCubit
|
||||
extends ServerInstallationDependendCubit<ApiServerVolumeState> {
|
||||
ApiServerVolumeCubit(final ServerInstallationCubit serverInstallationCubit)
|
||||
: super(serverInstallationCubit, const ApiServerVolumeState.initial());
|
||||
|
||||
final ServerApi serverApi = ServerApi();
|
||||
|
||||
@override
|
||||
Future<void> load() async {
|
||||
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||
_refetch();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _refetch() async {
|
||||
final List<ServerDiskVolume> volumes =
|
||||
await serverApi.getServerDiskVolumes();
|
||||
if (volumes.isNotEmpty) {
|
||||
emit(ApiServerVolumeState(volumes, LoadingStatus.success));
|
||||
} else {
|
||||
emit(const ApiServerVolumeState([], LoadingStatus.error));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void clear() {
|
||||
emit(const ApiServerVolumeState.initial());
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
part of 'server_volume_cubit.dart';
|
||||
|
||||
class ApiServerVolumeState extends ServerInstallationDependendState {
|
||||
const ApiServerVolumeState(this._volumes, this.status);
|
||||
|
||||
const ApiServerVolumeState.initial()
|
||||
: this(const [], LoadingStatus.uninitialized);
|
||||
final List<ServerDiskVolume> _volumes;
|
||||
final LoadingStatus status;
|
||||
|
||||
List<ServerDiskVolume> get volumes => _volumes;
|
||||
|
||||
ApiServerVolumeState copyWith({
|
||||
final List<ServerDiskVolume>? volumes,
|
||||
final LoadingStatus? status,
|
||||
}) =>
|
||||
ApiServerVolumeState(
|
||||
volumes ?? _volumes,
|
||||
status ?? this.status,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [_volumes];
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'package:selfprivacy/config/hive_config.dart';
|
|||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/server.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||
|
||||
export 'package:provider/provider.dart';
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ class ApiConfigModel {
|
|||
|
||||
Future<void> storeBackblazeCredential(final BackblazeCredential value) async {
|
||||
await _box.put(BNames.backblazeCredential, value);
|
||||
|
||||
_backblazeCredential = value;
|
||||
}
|
||||
|
||||
|
@ -63,6 +64,7 @@ class ApiConfigModel {
|
|||
|
||||
void init() {
|
||||
_hetznerKey = _box.get(BNames.hetznerKey);
|
||||
|
||||
_cloudFlareKey = _box.get(BNames.cloudFlareKey);
|
||||
_backblazeCredential = _box.get(BNames.backblazeCredential);
|
||||
_serverDomain = _box.get(BNames.serverDomain);
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
class DiskSize {
|
||||
DiskSize({final this.byte = 0});
|
||||
|
||||
double asKb() => byte / 1000.0;
|
||||
double asMb() => byte / 1000000.0;
|
||||
double asGb() => byte / 1000000000.0;
|
||||
|
||||
int byte;
|
||||
}
|
|
@ -55,21 +55,12 @@ class ServerVolume {
|
|||
ServerVolume({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.sizeByte,
|
||||
required this.serverId,
|
||||
required this.linuxDevice,
|
||||
});
|
||||
|
||||
@HiveField(1)
|
||||
int id;
|
||||
@HiveField(2)
|
||||
String name;
|
||||
@HiveField(3, defaultValue: 10737418240) // 10 Gb
|
||||
int sizeByte;
|
||||
@HiveField(4, defaultValue: null)
|
||||
int? serverId;
|
||||
@HiveField(5, defaultValue: null)
|
||||
String? linuxDevice;
|
||||
}
|
||||
|
||||
@HiveType(typeId: 101)
|
||||
|
|
|
@ -73,26 +73,17 @@ class ServerVolumeAdapter extends TypeAdapter<ServerVolume> {
|
|||
return ServerVolume(
|
||||
id: fields[1] as int,
|
||||
name: fields[2] as String,
|
||||
sizeByte: fields[3] == null ? 10737418240 : fields[3] as int,
|
||||
serverId: fields[4] as int?,
|
||||
linuxDevice: fields[5] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, ServerVolume obj) {
|
||||
writer
|
||||
..writeByte(5)
|
||||
..writeByte(2)
|
||||
..writeByte(1)
|
||||
..write(obj.id)
|
||||
..writeByte(2)
|
||||
..write(obj.name)
|
||||
..writeByte(3)
|
||||
..write(obj.sizeByte)
|
||||
..writeByte(4)
|
||||
..write(obj.serverId)
|
||||
..writeByte(5)
|
||||
..write(obj.linuxDevice);
|
||||
..write(obj.name);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -11,9 +11,9 @@ class UserAdapter extends TypeAdapter<User> {
|
|||
final int typeId = 1;
|
||||
|
||||
@override
|
||||
User read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
User read(final BinaryReader reader) {
|
||||
final int numOfFields = reader.readByte();
|
||||
final Map<int, dynamic> fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return User(
|
||||
|
@ -26,7 +26,7 @@ class UserAdapter extends TypeAdapter<User> {
|
|||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, User obj) {
|
||||
void write(final BinaryWriter writer, final User obj) {
|
||||
writer
|
||||
..writeByte(5)
|
||||
..writeByte(0)
|
||||
|
@ -45,7 +45,7 @@ class UserAdapter extends TypeAdapter<User> {
|
|||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
bool operator ==(final Object other) =>
|
||||
identical(this, other) ||
|
||||
other is UserAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
|
|
|
@ -7,8 +7,8 @@ import 'package:selfprivacy/utils/password_generator.dart';
|
|||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
|
||||
@immutable
|
||||
class ClientJob extends Equatable {
|
||||
ClientJob({
|
||||
class Job extends Equatable {
|
||||
Job({
|
||||
required this.title,
|
||||
final String? id,
|
||||
}) : id = id ?? StringGenerators.simpleId();
|
||||
|
@ -20,7 +20,7 @@ class ClientJob extends Equatable {
|
|||
List<Object> get props => [id, title];
|
||||
}
|
||||
|
||||
class CreateUserJob extends ClientJob {
|
||||
class CreateUserJob extends Job {
|
||||
CreateUserJob({
|
||||
required this.user,
|
||||
}) : super(title: '${"jobs.createUser".tr()} ${user.login}');
|
||||
|
@ -31,7 +31,7 @@ class CreateUserJob extends ClientJob {
|
|||
List<Object> get props => [id, title, user];
|
||||
}
|
||||
|
||||
class DeleteUserJob extends ClientJob {
|
||||
class DeleteUserJob extends Job {
|
||||
DeleteUserJob({
|
||||
required this.user,
|
||||
}) : super(title: '${"jobs.deleteUser".tr()} ${user.login}');
|
||||
|
@ -42,7 +42,7 @@ class DeleteUserJob extends ClientJob {
|
|||
List<Object> get props => [id, title, user];
|
||||
}
|
||||
|
||||
class ToggleJob extends ClientJob {
|
||||
class ToggleJob extends Job {
|
||||
ToggleJob({
|
||||
required this.type,
|
||||
required final super.title,
|
||||
|
@ -66,7 +66,7 @@ class ServiceToggleJob extends ToggleJob {
|
|||
final bool needToTurnOn;
|
||||
}
|
||||
|
||||
class CreateSSHKeyJob extends ClientJob {
|
||||
class CreateSSHKeyJob extends Job {
|
||||
CreateSSHKeyJob({
|
||||
required this.user,
|
||||
required this.publicKey,
|
||||
|
@ -79,7 +79,7 @@ class CreateSSHKeyJob extends ClientJob {
|
|||
List<Object> get props => [id, title, user, publicKey];
|
||||
}
|
||||
|
||||
class DeleteSSHKeyJob extends ClientJob {
|
||||
class DeleteSSHKeyJob extends Job {
|
||||
DeleteSSHKeyJob({
|
||||
required this.user,
|
||||
required this.publicKey,
|
||||
|
|
|
@ -11,9 +11,3 @@ ApiToken _$ApiTokenFromJson(Map<String, dynamic> json) => ApiToken(
|
|||
date: DateTime.parse(json['date'] as String),
|
||||
isCaller: json['is_caller'] as bool,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ApiTokenToJson(ApiToken instance) => <String, dynamic>{
|
||||
'name': instance.name,
|
||||
'date': instance.date.toIso8601String(),
|
||||
'is_caller': instance.isCaller,
|
||||
};
|
||||
|
|
|
@ -11,24 +11,12 @@ Backup _$BackupFromJson(Map<String, dynamic> json) => Backup(
|
|||
id: json['short_id'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$BackupToJson(Backup instance) => <String, dynamic>{
|
||||
'time': instance.time.toIso8601String(),
|
||||
'short_id': instance.id,
|
||||
};
|
||||
|
||||
BackupStatus _$BackupStatusFromJson(Map<String, dynamic> json) => BackupStatus(
|
||||
status: $enumDecode(_$BackupStatusEnumEnumMap, json['status']),
|
||||
progress: (json['progress'] as num).toDouble(),
|
||||
errorMessage: json['error_message'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$BackupStatusToJson(BackupStatus instance) =>
|
||||
<String, dynamic>{
|
||||
'status': _$BackupStatusEnumEnumMap[instance.status],
|
||||
'progress': instance.progress,
|
||||
'error_message': instance.errorMessage,
|
||||
};
|
||||
|
||||
const _$BackupStatusEnumEnumMap = {
|
||||
BackupStatusEnum.noKey: 'NO_KEY',
|
||||
BackupStatusEnum.notInitialized: 'NOT_INITIALIZED',
|
||||
|
|
|
@ -10,9 +10,3 @@ DeviceToken _$DeviceTokenFromJson(Map<String, dynamic> json) => DeviceToken(
|
|||
device: json['device'] as String,
|
||||
token: json['token'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$DeviceTokenToJson(DeviceToken instance) =>
|
||||
<String, dynamic>{
|
||||
'device': instance.device,
|
||||
'token': instance.token,
|
||||
};
|
||||
|
|
|
@ -19,18 +19,6 @@ HetznerServerInfo _$HetznerServerInfoFromJson(Map<String, dynamic> json) =>
|
|||
(json['volumes'] as List<dynamic>).map((e) => e as int).toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$HetznerServerInfoToJson(HetznerServerInfo instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'name': instance.name,
|
||||
'status': _$ServerStatusEnumMap[instance.status],
|
||||
'created': instance.created.toIso8601String(),
|
||||
'volumes': instance.volumes,
|
||||
'server_type': instance.serverType,
|
||||
'datacenter': instance.location,
|
||||
'public_net': instance.publicNet,
|
||||
};
|
||||
|
||||
const _$ServerStatusEnumMap = {
|
||||
ServerStatus.running: 'running',
|
||||
ServerStatus.initializing: 'initializing',
|
||||
|
@ -49,12 +37,6 @@ HetznerPublicNetInfo _$HetznerPublicNetInfoFromJson(
|
|||
HetznerIp4.fromJson(json['ipv4'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$HetznerPublicNetInfoToJson(
|
||||
HetznerPublicNetInfo instance) =>
|
||||
<String, dynamic>{
|
||||
'ipv4': instance.ipv4,
|
||||
};
|
||||
|
||||
HetznerIp4 _$HetznerIp4FromJson(Map<String, dynamic> json) => HetznerIp4(
|
||||
json['id'] as int,
|
||||
json['ip'] as String,
|
||||
|
@ -62,14 +44,6 @@ HetznerIp4 _$HetznerIp4FromJson(Map<String, dynamic> json) => HetznerIp4(
|
|||
json['dns_ptr'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$HetznerIp4ToJson(HetznerIp4 instance) =>
|
||||
<String, dynamic>{
|
||||
'blocked': instance.blocked,
|
||||
'dns_ptr': instance.reverseDns,
|
||||
'id': instance.id,
|
||||
'ip': instance.ip,
|
||||
};
|
||||
|
||||
HetznerServerTypeInfo _$HetznerServerTypeInfoFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
HetznerServerTypeInfo(
|
||||
|
@ -81,27 +55,12 @@ HetznerServerTypeInfo _$HetznerServerTypeInfoFromJson(
|
|||
.toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$HetznerServerTypeInfoToJson(
|
||||
HetznerServerTypeInfo instance) =>
|
||||
<String, dynamic>{
|
||||
'cores': instance.cores,
|
||||
'memory': instance.memory,
|
||||
'disk': instance.disk,
|
||||
'prices': instance.prices,
|
||||
};
|
||||
|
||||
HetznerPriceInfo _$HetznerPriceInfoFromJson(Map<String, dynamic> json) =>
|
||||
HetznerPriceInfo(
|
||||
HetznerPriceInfo.getPrice(json['price_hourly'] as Map),
|
||||
HetznerPriceInfo.getPrice(json['price_monthly'] as Map),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$HetznerPriceInfoToJson(HetznerPriceInfo instance) =>
|
||||
<String, dynamic>{
|
||||
'price_hourly': instance.hourly,
|
||||
'price_monthly': instance.monthly,
|
||||
};
|
||||
|
||||
HetznerLocation _$HetznerLocationFromJson(Map<String, dynamic> json) =>
|
||||
HetznerLocation(
|
||||
json['country'] as String,
|
||||
|
@ -109,11 +68,3 @@ HetznerLocation _$HetznerLocationFromJson(Map<String, dynamic> json) =>
|
|||
json['description'] as String,
|
||||
json['network_zone'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$HetznerLocationToJson(HetznerLocation instance) =>
|
||||
<String, dynamic>{
|
||||
'country': instance.country,
|
||||
'city': instance.city,
|
||||
'description': instance.description,
|
||||
'network_zone': instance.zone,
|
||||
};
|
||||
|
|
|
@ -17,12 +17,3 @@ RecoveryKeyStatus _$RecoveryKeyStatusFromJson(Map<String, dynamic> json) =>
|
|||
: DateTime.parse(json['expiration'] as String),
|
||||
usesLeft: json['uses_left'] as int?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$RecoveryKeyStatusToJson(RecoveryKeyStatus instance) =>
|
||||
<String, dynamic>{
|
||||
'exists': instance.exists,
|
||||
'date': instance.date?.toIso8601String(),
|
||||
'expiration': instance.expiration?.toIso8601String(),
|
||||
'uses_left': instance.usesLeft,
|
||||
'valid': instance.valid,
|
||||
};
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'server_disk_volume.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class ServerDiskVolume {
|
||||
factory ServerDiskVolume.fromJson(final Map<String, dynamic> json) =>
|
||||
_$ServerDiskVolumeFromJson(json);
|
||||
ServerDiskVolume({
|
||||
required this.freeSpace,
|
||||
required this.model,
|
||||
required this.name,
|
||||
required this.root,
|
||||
required this.serial,
|
||||
required this.totalSpace,
|
||||
required this.type,
|
||||
required this.usedSpace,
|
||||
});
|
||||
|
||||
final String freeSpace;
|
||||
final String? model;
|
||||
final String name;
|
||||
final bool root;
|
||||
final String? serial;
|
||||
final String totalSpace;
|
||||
final String type;
|
||||
final String usedSpace;
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'server_disk_volume.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ServerDiskVolume _$ServerDiskVolumeFromJson(Map<String, dynamic> json) =>
|
||||
ServerDiskVolume(
|
||||
freeSpace: json['freeSpace'] as String,
|
||||
model: json['model'] as String?,
|
||||
name: json['name'] as String,
|
||||
root: json['root'] as bool,
|
||||
serial: json['serial'] as String?,
|
||||
totalSpace: json['totalSpace'] as String,
|
||||
type: json['type'] as String,
|
||||
usedSpace: json['usedSpace'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ServerDiskVolumeToJson(ServerDiskVolume instance) =>
|
||||
<String, dynamic>{
|
||||
'freeSpace': instance.freeSpace,
|
||||
'model': instance.model,
|
||||
'name': instance.name,
|
||||
'root': instance.root,
|
||||
'serial': instance.serial,
|
||||
'totalSpace': instance.totalSpace,
|
||||
'type': instance.type,
|
||||
'usedSpace': instance.usedSpace,
|
||||
};
|
|
@ -1,39 +0,0 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'server_job.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class ServerJob {
|
||||
factory ServerJob.fromJson(final Map<String, dynamic> json) =>
|
||||
_$ServerJobFromJson(json);
|
||||
ServerJob({
|
||||
required this.name,
|
||||
required this.description,
|
||||
required this.status,
|
||||
required this.uid,
|
||||
required this.updatedAt,
|
||||
required this.createdAt,
|
||||
final this.error,
|
||||
final this.progress,
|
||||
final this.result,
|
||||
final this.statusText,
|
||||
final this.finishedAt,
|
||||
});
|
||||
|
||||
final String name;
|
||||
final String description;
|
||||
final String status;
|
||||
final String uid;
|
||||
@JsonKey(name: 'updated_at')
|
||||
final String updatedAt;
|
||||
@JsonKey(name: 'created_at')
|
||||
final DateTime createdAt;
|
||||
|
||||
final String? error;
|
||||
final int? progress;
|
||||
final String? result;
|
||||
@JsonKey(name: 'status_text')
|
||||
final String? statusText;
|
||||
@JsonKey(name: 'finished_at')
|
||||
final String? finishedAt;
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'server_job.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ServerJob _$ServerJobFromJson(Map<String, dynamic> json) => ServerJob(
|
||||
name: json['name'] as String,
|
||||
description: json['description'] as String,
|
||||
status: json['status'] as String,
|
||||
uid: json['uid'] as String,
|
||||
updatedAt: json['updated_at'] as String,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
error: json['error'] as String?,
|
||||
progress: json['progress'] as int?,
|
||||
result: json['result'] as String?,
|
||||
statusText: json['status_text'] as String?,
|
||||
finishedAt: json['finished_at'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ServerJobToJson(ServerJob instance) => <String, dynamic>{
|
||||
'name': instance.name,
|
||||
'description': instance.description,
|
||||
'status': instance.status,
|
||||
'uid': instance.uid,
|
||||
'updated_at': instance.updatedAt,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'error': instance.error,
|
||||
'progress': instance.progress,
|
||||
'result': instance.result,
|
||||
'status_text': instance.statusText,
|
||||
'finished_at': instance.finishedAt,
|
||||
};
|
|
@ -1 +1 @@
|
|||
enum StateType { uninitialized, stable, warning, error }
|
||||
enum StateType { uninitialized, stable, warning }
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class BrandOutlinedButton extends StatelessWidget {
|
||||
const BrandOutlinedButton({
|
||||
final super.key,
|
||||
this.onPressed,
|
||||
this.title,
|
||||
this.child,
|
||||
this.disabled = false,
|
||||
});
|
||||
|
||||
final VoidCallback? onPressed;
|
||||
final String? title;
|
||||
final Widget? child;
|
||||
final bool disabled;
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) => ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
minHeight: 40,
|
||||
minWidth: double.infinity,
|
||||
),
|
||||
child: OutlinedButton(
|
||||
onPressed: onPressed,
|
||||
child: child ??
|
||||
Text(
|
||||
title ?? '',
|
||||
style: Theme.of(context).textTheme.button?.copyWith(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class BrandLinearIndicator extends StatelessWidget {
|
||||
const BrandLinearIndicator({
|
||||
required this.value,
|
||||
required this.color,
|
||||
required this.backgroundColor,
|
||||
required this.height,
|
||||
final super.key,
|
||||
});
|
||||
|
||||
final double value;
|
||||
final Color color;
|
||||
final Color backgroundColor;
|
||||
final double height;
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) => Container(
|
||||
height: height,
|
||||
width: double.infinity,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.circular(height),
|
||||
),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: FractionallySizedBox(
|
||||
widthFactor: value,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
borderRadius: BorderRadius.circular(height),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
|
@ -28,12 +28,6 @@ class IconStatusMask extends StatelessWidget {
|
|||
case StateType.warning:
|
||||
colors = BrandColors.warningGradientColors;
|
||||
break;
|
||||
case StateType.error:
|
||||
colors = [
|
||||
Theme.of(context).colorScheme.error,
|
||||
Theme.of(context).colorScheme.error,
|
||||
];
|
||||
break;
|
||||
}
|
||||
return ShaderMask(
|
||||
shaderCallback: (final bounds) => LinearGradient(
|
||||
|
|
|
@ -11,7 +11,6 @@ import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
|||
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_loader/brand_loader.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
||||
import 'package:selfprivacy/ui/components/jobs_content/server_job_card.dart';
|
||||
|
||||
class JobsContent extends StatelessWidget {
|
||||
const JobsContent({final super.key});
|
||||
|
@ -68,7 +67,7 @@ class JobsContent extends StatelessWidget {
|
|||
];
|
||||
} else if (state is JobsStateWithJobs) {
|
||||
widgets = [
|
||||
...state.clientJobList
|
||||
...state.jobList
|
||||
.map(
|
||||
(final j) => Row(
|
||||
children: [
|
||||
|
@ -118,15 +117,7 @@ class JobsContent extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
...widgets,
|
||||
const SizedBox(height: 8),
|
||||
const Divider(),
|
||||
const SizedBox(height: 8),
|
||||
...state.serverJobList.map(
|
||||
(final job) => ServerJobCard(
|
||||
serverJob: job,
|
||||
),
|
||||
),
|
||||
...widgets
|
||||
],
|
||||
);
|
||||
},
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_linear_indicator/brand_linear_indicator.dart';
|
||||
|
||||
class ServerJobCard extends StatelessWidget {
|
||||
const ServerJobCard({
|
||||
required final this.serverJob,
|
||||
final super.key,
|
||||
});
|
||||
|
||||
final ServerJob serverJob;
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) => GestureDetector(
|
||||
child: BrandCards.big(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
serverJob.name,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
Text(
|
||||
serverJob.description,
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
BrandLinearIndicator(
|
||||
value: serverJob.progress == null
|
||||
? 0.0
|
||||
: serverJob.progress! / 100.0,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
backgroundColor: Theme.of(context).colorScheme.surfaceVariant,
|
||||
height: 7.0,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
|
@ -83,14 +83,10 @@ class _ProgressBarState extends State<ProgressBar> {
|
|||
height: 5,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: Theme.of(context).colorScheme.surfaceVariant,
|
||||
gradient: LinearGradient(
|
||||
gradient: const LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
Theme.of(context).colorScheme.primary,
|
||||
Theme.of(context).colorScheme.secondary
|
||||
],
|
||||
colors: BrandColors.stableGradientColors,
|
||||
),
|
||||
),
|
||||
duration: const Duration(
|
||||
|
@ -126,7 +122,15 @@ class _ProgressBarState extends State<ProgressBar> {
|
|||
text: TextSpan(
|
||||
style: progressTextStyleLight,
|
||||
children: [
|
||||
TextSpan(text: '${index + 1}.', style: style),
|
||||
if (checked)
|
||||
const WidgetSpan(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(bottom: 2, right: 2),
|
||||
child: Icon(BrandIcons.check, size: 11),
|
||||
),
|
||||
)
|
||||
else
|
||||
TextSpan(text: '${index + 1}.', style: style),
|
||||
TextSpan(text: step, style: style)
|
||||
],
|
||||
),
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/config/brand_theme.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_md/brand_md.dart';
|
||||
|
@ -17,13 +16,8 @@ class AboutPage extends StatelessWidget {
|
|||
hasBackButton: true,
|
||||
),
|
||||
),
|
||||
body: ListView(
|
||||
padding: paddingH15V0,
|
||||
children: const [
|
||||
BrandMarkdown(
|
||||
fileName: 'about',
|
||||
),
|
||||
],
|
||||
body: const BrandMarkdown(
|
||||
fileName: 'about',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/config/brand_theme.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
||||
|
@ -24,16 +23,9 @@ class InfoPage extends StatelessWidget {
|
|||
const BrandDivider(),
|
||||
const SizedBox(height: 10),
|
||||
FutureBuilder(
|
||||
future: _packageVersion(),
|
||||
future: _version(),
|
||||
builder: (final context, final snapshot) => BrandText.body1(
|
||||
'more.about_app_page.application_version_text'
|
||||
.tr(args: [snapshot.data.toString()]),
|
||||
),
|
||||
),
|
||||
FutureBuilder(
|
||||
future: _apiVersion(),
|
||||
builder: (final context, final snapshot) => BrandText.body1(
|
||||
'more.about_app_page.api_version_text'
|
||||
'more.about_app_page.text'
|
||||
.tr(args: [snapshot.data.toString()]),
|
||||
),
|
||||
),
|
||||
|
@ -42,7 +34,7 @@ class InfoPage extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
|
||||
Future<String> _packageVersion() async {
|
||||
Future<String> _version() async {
|
||||
String packageVersion = 'unknown';
|
||||
try {
|
||||
final PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||
|
@ -53,15 +45,4 @@ class InfoPage extends StatelessWidget {
|
|||
|
||||
return packageVersion;
|
||||
}
|
||||
|
||||
Future<String> _apiVersion() async {
|
||||
String apiVersion = 'unknown';
|
||||
try {
|
||||
apiVersion = await ServerApi().getApiVersion() ?? apiVersion;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
|
||||
return apiVersion;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,11 +5,6 @@ import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart';
|
|||
import 'package:selfprivacy/logic/cubit/dns_records/dns_records_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/providers/providers_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_disk_volume.dart';
|
||||
import 'package:selfprivacy/logic/models/provider.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart';
|
||||
|
@ -20,9 +15,7 @@ import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart';
|
|||
import 'package:selfprivacy/ui/helpers/modals.dart';
|
||||
import 'package:selfprivacy/ui/pages/backup_details/backup_details.dart';
|
||||
import 'package:selfprivacy/ui/pages/dns_details/dns_details.dart';
|
||||
import 'package:selfprivacy/ui/pages/providers/storage_card.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_details/server_details_screen.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_storage/disk_status.dart';
|
||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||
|
||||
GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||
|
@ -74,17 +67,6 @@ class _ProvidersPageState extends State<ProvidersPage> {
|
|||
),
|
||||
)
|
||||
.toList();
|
||||
cards.add(
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 30),
|
||||
child: StorageCard(
|
||||
diskStatus: toDiskStatus(
|
||||
context.read<ApiServerVolumeCubit>().state.volumes,
|
||||
context.read<ApiProviderVolumeCubit>().state.volumes,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
return Scaffold(
|
||||
appBar: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(52),
|
||||
|
@ -104,60 +86,6 @@ class _ProvidersPageState extends State<ProvidersPage> {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
DiskStatus toDiskStatus(
|
||||
final List<ServerDiskVolume> serverVolumes,
|
||||
final List<ServerVolume> providerVolumes,
|
||||
) {
|
||||
final DiskStatus diskStatus = DiskStatus();
|
||||
diskStatus.isDiskOkay = true;
|
||||
|
||||
if (providerVolumes.isEmpty || serverVolumes.isEmpty) {
|
||||
diskStatus.isDiskOkay = false;
|
||||
}
|
||||
|
||||
diskStatus.diskVolumes = serverVolumes.map((
|
||||
final ServerDiskVolume volume,
|
||||
) {
|
||||
final DiskVolume diskVolume = DiskVolume();
|
||||
diskVolume.sizeUsed = DiskSize(
|
||||
byte: volume.usedSpace == 'None' ? 0 : int.parse(volume.usedSpace),
|
||||
);
|
||||
diskVolume.sizeTotal = DiskSize(
|
||||
byte: volume.totalSpace == 'None' ? 0 : int.parse(volume.totalSpace),
|
||||
);
|
||||
diskVolume.serverDiskVolume = volume;
|
||||
|
||||
for (final ServerVolume providerVolume in providerVolumes) {
|
||||
if (providerVolume.linuxDevice == null ||
|
||||
volume.model == null ||
|
||||
volume.serial == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final String deviceId = providerVolume.linuxDevice!.split('/').last;
|
||||
if (deviceId.contains(volume.model!) &&
|
||||
deviceId.contains(volume.serial!)) {
|
||||
diskVolume.providerVolume = providerVolume;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
diskVolume.name = volume.name;
|
||||
diskVolume.root = volume.root;
|
||||
diskVolume.percentage =
|
||||
volume.usedSpace != 'None' && volume.totalSpace != 'None'
|
||||
? 1.0 / diskVolume.sizeTotal.byte * diskVolume.sizeUsed.byte
|
||||
: 0.0;
|
||||
if (diskVolume.percentage >= 0.8 ||
|
||||
diskVolume.sizeTotal.asGb() - diskVolume.sizeUsed.asGb() <= 2.0) {
|
||||
diskStatus.isDiskOkay = false;
|
||||
}
|
||||
return diskVolume;
|
||||
}).toList();
|
||||
|
||||
return diskStatus;
|
||||
}
|
||||
}
|
||||
|
||||
class _Card extends StatelessWidget {
|
||||
|
@ -175,6 +103,9 @@ class _Card extends StatelessWidget {
|
|||
final ServerInstallationState appConfig =
|
||||
context.watch<ServerInstallationCubit>().state;
|
||||
|
||||
final String domainName =
|
||||
appConfig.isDomainFilled ? appConfig.serverDomain!.domainName : '';
|
||||
|
||||
switch (provider.type) {
|
||||
case ProviderType.server:
|
||||
title = 'providers.server.card_title'.tr();
|
||||
|
@ -190,9 +121,7 @@ class _Card extends StatelessWidget {
|
|||
break;
|
||||
case ProviderType.domain:
|
||||
title = 'providers.domain.screen_title'.tr();
|
||||
message = appConfig.isDomainSelected
|
||||
? appConfig.serverDomain!.domainName
|
||||
: '';
|
||||
message = domainName;
|
||||
stableText = 'providers.domain.status'.tr();
|
||||
|
||||
onTap = () => Navigator.of(context).push(
|
||||
|
@ -222,17 +151,12 @@ class _Card extends StatelessWidget {
|
|||
status: provider.state,
|
||||
child: Icon(provider.icon, size: 30, color: Colors.white),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
title,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BrandText.h2(title),
|
||||
const SizedBox(height: 10),
|
||||
if (message != null) ...[
|
||||
Text(
|
||||
message,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
BrandText.body2(message),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
if (provider.state == StateType.stable) BrandText.body2(stableText),
|
||||
],
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/providers/providers_cubit.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart';
|
||||
import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_storage/disk_status.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_storage/server_storage.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_storage/server_storage_list_item.dart';
|
||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||
|
||||
class StorageCard extends StatelessWidget {
|
||||
const StorageCard({
|
||||
required final this.diskStatus,
|
||||
final super.key,
|
||||
});
|
||||
|
||||
final DiskStatus diskStatus;
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) {
|
||||
final List<Widget> sections = [];
|
||||
for (final DiskVolume volume in diskStatus.diskVolumes) {
|
||||
sections.add(
|
||||
const SizedBox(height: 16),
|
||||
);
|
||||
sections.add(
|
||||
ServerStorageListItem(
|
||||
volume: volume,
|
||||
dense: true,
|
||||
showIcon: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
StateType state = context.watch<ServerInstallationCubit>().state
|
||||
is ServerInstallationFinished
|
||||
? StateType.stable
|
||||
: StateType.uninitialized;
|
||||
|
||||
if (state == StateType.stable && !diskStatus.isDiskOkay) {
|
||||
state = StateType.error;
|
||||
}
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => Navigator.of(context).push(
|
||||
materialRoute(
|
||||
ServerStoragePage(
|
||||
diskStatus: diskStatus,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: BrandCards.big(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
IconStatusMask(
|
||||
status: state,
|
||||
child: const Icon(
|
||||
Icons.storage_outlined,
|
||||
size: 30,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
if (state != StateType.uninitialized)
|
||||
IconStatusMask(
|
||||
status: state,
|
||||
child: Icon(
|
||||
diskStatus.isDiskOkay
|
||||
? Icons.check_circle_outline
|
||||
: Icons.error_outline,
|
||||
size: 24,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'providers.storage.card_title'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
if (state != StateType.uninitialized)
|
||||
Text(
|
||||
diskStatus.isDiskOkay
|
||||
? 'providers.storage.status_ok'.tr()
|
||||
: 'providers.storage.status_error'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
...sections,
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -294,6 +294,7 @@ class _RecoveryKeyConfigurationState extends State<RecoveryKeyConfiguration> {
|
|||
}
|
||||
|
||||
_amountController.addListener(_updateErrorStatuses);
|
||||
|
||||
_expirationController.addListener(_updateErrorStatuses);
|
||||
|
||||
return Column(
|
||||
|
@ -320,7 +321,6 @@ class _RecoveryKeyConfigurationState extends State<RecoveryKeyConfiguration> {
|
|||
children: [
|
||||
const SizedBox(height: 8),
|
||||
TextField(
|
||||
textInputAction: TextInputAction.next,
|
||||
enabled: _isAmountToggled,
|
||||
controller: _amountController,
|
||||
decoration: InputDecoration(
|
||||
|
@ -360,7 +360,6 @@ class _RecoveryKeyConfigurationState extends State<RecoveryKeyConfiguration> {
|
|||
children: [
|
||||
const SizedBox(height: 8),
|
||||
TextField(
|
||||
textInputAction: TextInputAction.next,
|
||||
enabled: _isExpirationToggled,
|
||||
controller: _expirationController,
|
||||
onTap: () {
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_storage/disk_status.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_storage/server_storage_list_item.dart';
|
||||
|
||||
class DataMigrationPage extends StatefulWidget {
|
||||
const DataMigrationPage({
|
||||
required this.diskVolumeToResize,
|
||||
required this.diskStatus,
|
||||
required this.resizeTarget,
|
||||
final super.key,
|
||||
});
|
||||
|
||||
final DiskVolume diskVolumeToResize;
|
||||
final DiskStatus diskStatus;
|
||||
final DiskSize resizeTarget;
|
||||
|
||||
@override
|
||||
State<DataMigrationPage> createState() => _DataMigrationPageState();
|
||||
}
|
||||
|
||||
class _DataMigrationPageState extends State<DataMigrationPage> {
|
||||
@override
|
||||
Widget build(final BuildContext context) {
|
||||
int a = 0;
|
||||
return BrandHeroScreen(
|
||||
hasBackButton: true,
|
||||
heroTitle: 'providers.storage.data_migration_title'.tr(),
|
||||
children: [
|
||||
...widget.diskStatus.diskVolumes
|
||||
.map(
|
||||
(final volume) => Column(
|
||||
children: [
|
||||
ServerStorageListItem(
|
||||
volume: volume,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/json/server_disk_volume.dart';
|
||||
|
||||
class DiskVolume {
|
||||
DiskSize sizeUsed = DiskSize();
|
||||
DiskSize sizeTotal = DiskSize();
|
||||
String name = '';
|
||||
bool root = false;
|
||||
bool isResizable = true;
|
||||
ServerDiskVolume? serverDiskVolume;
|
||||
ServerVolume? providerVolume;
|
||||
|
||||
/// from 0.0 to 1.0
|
||||
double percentage = 0.0;
|
||||
}
|
||||
|
||||
class DiskStatus {
|
||||
bool isDiskOkay = false;
|
||||
List<DiskVolume> diskVolumes = [];
|
||||
}
|
|
@ -1,149 +0,0 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_button/filled_button.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_storage/disk_status.dart';
|
||||
|
||||
class ExtendingVolumePage extends StatefulWidget {
|
||||
const ExtendingVolumePage({
|
||||
required this.diskVolumeToResize,
|
||||
required this.diskStatus,
|
||||
final super.key,
|
||||
});
|
||||
|
||||
final DiskVolume diskVolumeToResize;
|
||||
final DiskStatus diskStatus;
|
||||
|
||||
@override
|
||||
State<ExtendingVolumePage> createState() => _ExtendingVolumePageState();
|
||||
}
|
||||
|
||||
class _ExtendingVolumePageState extends State<ExtendingVolumePage> {
|
||||
bool _isError = false;
|
||||
|
||||
double _currentSliderGbValue = -1;
|
||||
double _euroPerGb = 1.0;
|
||||
|
||||
final DiskSize maxSize = DiskSize(byte: 500000000000);
|
||||
DiskSize minSize = DiskSize();
|
||||
|
||||
final TextEditingController _sizeController = TextEditingController();
|
||||
final TextEditingController _priceController = TextEditingController();
|
||||
|
||||
void _updateErrorStatuses() {
|
||||
_isError = minSize.asGb() > _currentSliderGbValue;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) => FutureBuilder(
|
||||
future: context.read<ApiProviderVolumeCubit>().getPricePerGb(),
|
||||
builder: (
|
||||
final BuildContext context,
|
||||
final AsyncSnapshot<void> snapshot,
|
||||
) {
|
||||
if (!snapshot.hasData) {
|
||||
return BrandHeroScreen(
|
||||
hasBackButton: true,
|
||||
heroTitle: 'providers.storage.extending_volume_title'.tr(),
|
||||
heroSubtitle:
|
||||
'providers.storage.extending_volume_description'.tr(),
|
||||
children: const [
|
||||
SizedBox(height: 16),
|
||||
],
|
||||
);
|
||||
}
|
||||
_euroPerGb = snapshot.data as double;
|
||||
_sizeController.text = _currentSliderGbValue.truncate().toString();
|
||||
_priceController.text =
|
||||
(_euroPerGb * double.parse(_sizeController.text))
|
||||
.toStringAsPrecision(2);
|
||||
minSize = widget.diskVolumeToResize.sizeTotal;
|
||||
if (_currentSliderGbValue < 0) {
|
||||
_currentSliderGbValue = minSize.asGb();
|
||||
}
|
||||
|
||||
return BrandHeroScreen(
|
||||
hasBackButton: true,
|
||||
heroTitle: 'providers.storage.extending_volume_title'.tr(),
|
||||
heroSubtitle: 'providers.storage.extending_volume_description'.tr(),
|
||||
children: [
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 130),
|
||||
child: TextField(
|
||||
readOnly: true,
|
||||
textAlign: TextAlign.start,
|
||||
textInputAction: TextInputAction.next,
|
||||
enabled: true,
|
||||
controller: _sizeController,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
errorText: _isError ? ' ' : null,
|
||||
labelText: 'providers.storage.size'.tr(),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 130),
|
||||
child: TextField(
|
||||
readOnly: true,
|
||||
textAlign: TextAlign.start,
|
||||
textInputAction: TextInputAction.next,
|
||||
enabled: true,
|
||||
controller: _priceController,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
errorText: _isError ? ' ' : null,
|
||||
labelText: 'providers.storage.euro'.tr(),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Slider(
|
||||
min: minSize.asGb(),
|
||||
value: _currentSliderGbValue,
|
||||
max: maxSize.asGb(),
|
||||
onChanged: (final double value) {
|
||||
setState(() {
|
||||
_currentSliderGbValue = value;
|
||||
_updateErrorStatuses();
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FilledButton(
|
||||
title: 'providers.storage.extend_volume_button.title'.tr(),
|
||||
onPressed: null,
|
||||
disabled: _isError,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const Divider(
|
||||
height: 1.0,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Icon(
|
||||
Icons.info_outlined,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text('providers.storage.extending_volume_price_info'.tr()),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_button/outlined_button.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_storage/disk_status.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_storage/extending_volume.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_storage/server_storage_list_item.dart';
|
||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||
|
||||
class ServerStoragePage extends StatefulWidget {
|
||||
const ServerStoragePage({required this.diskStatus, final super.key});
|
||||
|
||||
final DiskStatus diskStatus;
|
||||
|
||||
@override
|
||||
State<ServerStoragePage> createState() => _ServerStoragePageState();
|
||||
}
|
||||
|
||||
class _ServerStoragePageState extends State<ServerStoragePage> {
|
||||
@override
|
||||
Widget build(final BuildContext context) {
|
||||
final bool isReady = context.watch<ServerInstallationCubit>().state
|
||||
is ServerInstallationFinished;
|
||||
|
||||
if (!isReady) {
|
||||
return BrandHeroScreen(
|
||||
hasBackButton: true,
|
||||
heroTitle: 'providers.storage.card_title'.tr(),
|
||||
children: const [],
|
||||
);
|
||||
}
|
||||
|
||||
return BrandHeroScreen(
|
||||
hasBackButton: true,
|
||||
heroTitle: 'providers.storage.card_title'.tr(),
|
||||
children: [
|
||||
// ...sections,
|
||||
...widget.diskStatus.diskVolumes
|
||||
.map(
|
||||
(final volume) => Column(
|
||||
children: [
|
||||
ServerStorageSection(
|
||||
volume: volume,
|
||||
diskStatus: widget.diskStatus,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const Divider(),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ServerStorageSection extends StatelessWidget {
|
||||
const ServerStorageSection({
|
||||
required this.volume,
|
||||
required this.diskStatus,
|
||||
final super.key,
|
||||
});
|
||||
|
||||
final DiskVolume volume;
|
||||
final DiskStatus diskStatus;
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) => Column(
|
||||
children: [
|
||||
ServerStorageListItem(
|
||||
volume: volume,
|
||||
),
|
||||
if (volume.isResizable) ...[
|
||||
const SizedBox(height: 16),
|
||||
BrandOutlinedButton(
|
||||
title: 'providers.storage.extend_volume_button.title'.tr(),
|
||||
onPressed: () => Navigator.of(context).push(
|
||||
materialRoute(
|
||||
ExtendingVolumePage(
|
||||
diskVolumeToResize: volume,
|
||||
diskStatus: diskStatus,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_linear_indicator/brand_linear_indicator.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_storage/disk_status.dart';
|
||||
|
||||
class ServerStorageListItem extends StatelessWidget {
|
||||
const ServerStorageListItem({
|
||||
required this.volume,
|
||||
final this.showIcon = true,
|
||||
final this.dense = false,
|
||||
final super.key,
|
||||
});
|
||||
|
||||
final DiskVolume volume;
|
||||
final bool showIcon;
|
||||
final bool dense;
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) {
|
||||
final TextStyle? titleStyle = dense
|
||||
? Theme.of(context).textTheme.titleMedium
|
||||
: Theme.of(context).textTheme.titleLarge;
|
||||
|
||||
final TextStyle? subtitleStyle = dense
|
||||
? Theme.of(context).textTheme.bodySmall
|
||||
: Theme.of(context).textTheme.bodyMedium;
|
||||
|
||||
return Row(
|
||||
children: [
|
||||
if (showIcon)
|
||||
const Icon(
|
||||
Icons.storage_outlined,
|
||||
size: 24,
|
||||
color: Colors.white,
|
||||
),
|
||||
if (showIcon) const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'providers.storage.disk_usage'.tr(
|
||||
args: [
|
||||
volume.sizeUsed.asGb().toStringAsPrecision(3),
|
||||
],
|
||||
),
|
||||
style: titleStyle,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
BrandLinearIndicator(
|
||||
value: volume.percentage,
|
||||
color: volume.root
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.secondary,
|
||||
backgroundColor: Theme.of(context).colorScheme.surfaceVariant,
|
||||
height: 14.0,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'providers.storage.disk_total'.tr(
|
||||
args: [
|
||||
volume.sizeTotal.asGb().toStringAsPrecision(3),
|
||||
volume.name,
|
||||
],
|
||||
),
|
||||
style: subtitleStyle,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_linear_indicator/brand_linear_indicator.dart';
|
||||
|
||||
class ServiceStorageConsumptionListItem extends StatelessWidget {
|
||||
const ServiceStorageConsumptionListItem({
|
||||
required this.title,
|
||||
required this.percentage,
|
||||
required this.storageConsumptionText,
|
||||
required this.color,
|
||||
required this.icon,
|
||||
final super.key,
|
||||
});
|
||||
|
||||
final String title;
|
||||
final double percentage;
|
||||
final String storageConsumptionText;
|
||||
final Color color;
|
||||
final IconData icon;
|
||||
@override
|
||||
Widget build(final BuildContext context) => Row(
|
||||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
Text(
|
||||
storageConsumptionText,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
BrandLinearIndicator(
|
||||
value: percentage,
|
||||
color: color,
|
||||
backgroundColor: Theme.of(context).colorScheme.surfaceVariant,
|
||||
height: 7.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue