From bc6c55b5287daffc8419434fe890c7358c451567 Mon Sep 17 00:00:00 2001 From: Kherel Date: Fri, 26 Mar 2021 00:30:34 +0100 Subject: [PATCH] change http client --- assets/translations/ru.json | 2 +- lib/config/get_it_config.dart | 2 + lib/logic/api_maps/api_map.dart | 46 ++++++-- lib/logic/api_maps/backblaze.dart | 51 +++++---- lib/logic/api_maps/cloudflare.dart | 104 ++++++++++-------- lib/logic/api_maps/hetzner.dart | 92 +++++++++++----- lib/logic/api_maps/server.dart | 51 ++++----- .../cubit/app_config/app_config_cubit.dart | 28 ++--- .../app_config/app_config_repository.dart | 39 +++---- .../initializing/backblaze_form_cubit.dart | 13 +-- .../initializing/cloudflare_form_cubit.dart | 5 +- .../forms/initializing/domain_cloudflare.dart | 20 +--- .../forms/initializing/domain_form_cubit.dart | 68 ------------ .../initializing/hetzner_form_cubit.dart | 12 +- .../initializing/root_user_form_cubit.dart | 13 --- .../cubit/forms/user/user_form_cubit.dart | 1 - lib/logic/cubit/services/services_cubit.dart | 28 ----- lib/logic/cubit/services/services_state.dart | 26 ----- lib/logic/models/server_info.dart | 23 ++++ lib/logic/models/service.dart | 25 ----- lib/main.dart | 2 + lib/ui/pages/initializing/initializing.dart | 2 +- lib/ui/pages/onboarding/onboarding.dart | 6 +- lib/ui/pages/services/services.dart | 1 + pubspec.lock | 7 ++ pubspec.yaml | 1 + 26 files changed, 292 insertions(+), 376 deletions(-) delete mode 100644 lib/logic/cubit/forms/initializing/domain_form_cubit.dart delete mode 100644 lib/logic/cubit/services/services_cubit.dart delete mode 100644 lib/logic/cubit/services/services_state.dart create mode 100644 lib/logic/models/server_info.dart delete mode 100644 lib/logic/models/service.dart diff --git a/assets/translations/ru.json b/assets/translations/ru.json index a6e0d26ba0..0a7bbd2e6a 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -29,7 +29,7 @@ "configuration_wizard": "Мастер Подключения", "about_project": "О проекте SelfPrivacy", "about_app": "О приложении", - "onboarding": "Onboarding", + "onboarding": "Приветствие", "console": "Console", "about_app_page": { "text": "Тут любая служебная информация, v.{}" diff --git a/lib/config/get_it_config.dart b/lib/config/get_it_config.dart index 8d7faa7ba5..3f01e6d3fc 100644 --- a/lib/config/get_it_config.dart +++ b/lib/config/get_it_config.dart @@ -4,10 +4,12 @@ import 'package:selfprivacy/logic/get_it/console.dart'; import 'package:selfprivacy/logic/get_it/navigation.dart'; import 'package:selfprivacy/logic/get_it/timer.dart'; +export 'package:selfprivacy/logic/get_it/api_config.dart'; export 'package:selfprivacy/logic/get_it/console.dart'; export 'package:selfprivacy/logic/get_it/navigation.dart'; export 'package:selfprivacy/logic/get_it/timer.dart'; + final getIt = GetIt.instance; Future getItSetup() async { diff --git a/lib/logic/api_maps/api_map.dart b/lib/logic/api_maps/api_map.dart index e67da5c1e8..ce5484a599 100644 --- a/lib/logic/api_maps/api_map.dart +++ b/lib/logic/api_maps/api_map.dart @@ -1,32 +1,58 @@ +import 'dart:async'; import 'dart:developer'; import 'dart:io'; import 'package:dio/adapter.dart'; import 'package:dio/dio.dart'; +import 'package:pretty_dio_logger/pretty_dio_logger.dart'; import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/logic/get_it/console.dart'; import 'package:selfprivacy/logic/models/message.dart'; -abstract class ApiMapOld { - ApiMapOld() { - var client = Dio()..interceptors.add(ConsoleInterceptor()); - (client.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = +abstract class ApiMap { + + Future getClient() async { + var dio = Dio(await options); + if (hasLoger) { + dio.interceptors.add(PrettyDioLogger()); + } + dio..interceptors.add(ConsoleInterceptor()); + (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) { client.badCertificateCallback = (X509Certificate cert, String host, int port) => true; return client; }; - loggedClient = client; + return dio; } - String? rootAddress; - late Dio loggedClient; + FutureOr get options; - void close() { - loggedClient.close(); - } + abstract final String rootAddress; + abstract final bool hasLoger; + abstract final bool isWithToken; } +// abstract class ApiMapOld { +// ApiMapOld() { +// var client = Dio()..interceptors.add(ConsoleInterceptor()); +// (client.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = +// (HttpClient client) { +// client.badCertificateCallback = +// (X509Certificate cert, String host, int port) => true; +// return client; +// }; +// loggedClient = client; +// } +// String? rootAddress; + +// late Dio loggedClient; + +// void close() { +// loggedClient.close(); +// } +// } + class ConsoleInterceptor extends InterceptorsWrapper { void addMessage(Message message) { getIt.get().addMessage(message); diff --git a/lib/logic/api_maps/backblaze.dart b/lib/logic/api_maps/backblaze.dart index de04225e31..f398975145 100644 --- a/lib/logic/api_maps/backblaze.dart +++ b/lib/logic/api_maps/backblaze.dart @@ -1,31 +1,38 @@ 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'; -class BackblazeApi extends ApiMapOld { - BackblazeApi([String? token]) { - if (token != null) { - loggedClient.options = BaseOptions( - headers: {'Authorization': 'Basic $token'}, - baseUrl: rootAddress!, - ); +class BackblazeApi extends ApiMap { + BackblazeApi({this.hasLoger = false, this.isWithToken = true}); + + BaseOptions get options { + var options = BaseOptions(baseUrl: rootAddress); + if (isWithToken) { + var backblazeCredential = getIt().backblazeCredential; + var token = backblazeCredential!.applicationKey; + assert(token != null); + options.headers = {'Authorization': 'Basic $token'}; } + + if (validateStatus != null) { + options.validateStatus = validateStatus!; + } + + return options; } + ValidateStatus? validateStatus; @override - String? rootAddress = - 'https://api.backblazeb2.com/b2api/v2/b2_authorize_account'; + String rootAddress = 'https://api.backblazeb2.com/b2api/v2/'; - Future isValid(String token) async { - var options = Options( - headers: {'Authorization': 'Basic $token'}, - validateStatus: (status) { - return status == HttpStatus.ok || status == HttpStatus.unauthorized; - }, + Future isValid(String encodedApiKey) async { + var client = await getClient(); + Response response = await client.get( + 'b2_authorize_account', + options: Options(headers: {'Authorization': 'Basic $encodedApiKey'}), ); - - Response response = await loggedClient.get(rootAddress!, options: options); - + client.close(); if (response.statusCode == HttpStatus.ok) { return true; } else if (response.statusCode == HttpStatus.unauthorized) { @@ -34,4 +41,10 @@ class BackblazeApi extends ApiMapOld { throw Exception('code: ${response.statusCode}'); } } -} \ No newline at end of file + + @override + bool hasLoger; + + @override + bool isWithToken; +} diff --git a/lib/logic/api_maps/cloudflare.dart b/lib/logic/api_maps/cloudflare.dart index 1f09a0f3cf..40cbef4253 100644 --- a/lib/logic/api_maps/cloudflare.dart +++ b/lib/logic/api_maps/cloudflare.dart @@ -1,30 +1,43 @@ 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/cloudflare_domain.dart'; import 'package:selfprivacy/logic/models/dns_records.dart'; -class CloudflareApi extends ApiMapOld { - CloudflareApi([String? token]) { - if (token != null) { - loggedClient.options = - BaseOptions(headers: {'Authorization': 'Bearer $token'}); +class CloudflareApi extends ApiMap { + CloudflareApi({this.hasLoger = false, this.isWithToken = true}); + + BaseOptions get options { + var options = BaseOptions(baseUrl: rootAddress); + if (isWithToken) { + var token = getIt().cloudFlareKey; + assert(token != null); + options.headers = {'Authorization': 'Bearer $token'}; } + + if (validateStatus != null) { + options.validateStatus = validateStatus!; + } + return options; } + ValidateStatus? validateStatus; + @override - String? rootAddress = 'https://api.cloudflare.com/client/v4'; + String rootAddress = 'https://api.cloudflare.com/client/v4'; Future isValid(String token) async { - var url = '$rootAddress/user/tokens/verify'; - var options = Options( - headers: {'Authorization': 'Bearer $token'}, - validateStatus: (status) { - return status == HttpStatus.ok || status == HttpStatus.unauthorized; - }, - ); + validateStatus = (status) { + return status == HttpStatus.ok || status == HttpStatus.unauthorized; + }; - Response response = await loggedClient.get(url, options: options); + var client = await getClient(); + Response response = await client.get('/user/tokens/verify', + options: Options(headers: {'Authorization': 'Bearer $token'})); + + client.close(); + validateStatus = null; if (response.statusCode == HttpStatus.ok) { return true; @@ -35,22 +48,19 @@ class CloudflareApi extends ApiMapOld { } } - Future getZoneId(String? token, String domain) async { - var url = '$rootAddress/zones'; - - var options = Options( - headers: {'Authorization': 'Bearer $token'}, - validateStatus: (status) { - return status == HttpStatus.ok || status == HttpStatus.forbidden; - }, - ); - - Response response = await loggedClient.get( - url, - options: options, + Future getZoneId(String domain) async { + validateStatus = (status) { + return status == HttpStatus.ok || status == HttpStatus.forbidden; + }; + var client = await getClient(); + Response response = await client.get( + '/zones', queryParameters: {'name': domain}, ); + client.close(); + validateStatus = null; + try { return response.data['result'][0]['id']; } catch (error) { @@ -65,20 +75,24 @@ class CloudflareApi extends ApiMapOld { var domainName = cloudFlareDomain.domainName; var domainZoneId = cloudFlareDomain.zoneId; - var url = '$rootAddress/zones/$domainZoneId/dns_records'; + var url = '/zones/$domainZoneId/dns_records'; + + var client = await getClient(); + Response response = await client.get(url); - var response = await loggedClient.get(url); List records = response.data['result'] ?? []; var allDeleteFutures = []; for (var record in records) { if (record['zone_name'] == domainName) { allDeleteFutures.add( - loggedClient.delete('$url/${record["id"]}'), + client.delete('$url/${record["id"]}'), ); } } + await Future.wait(allDeleteFutures); + client.close(); } Future createMultipleDnsRecords({ @@ -92,10 +106,11 @@ class CloudflareApi extends ApiMapOld { var url = '$rootAddress/zones/$domainZoneId/dns_records'; var allCreateFutures = []; + var client = await getClient(); for (var record in listDnsRecords) { allCreateFutures.add( - loggedClient.post( + client.post( url, data: record.toJson(), ), @@ -103,23 +118,9 @@ class CloudflareApi extends ApiMapOld { } await Future.wait(allCreateFutures); + client.close(); } - // setDkim(String dkimRecordString, String domainZoneId) { - // var txt3 = DnsRecords( - // type: 'TXT', - // name: 'selector._domainkey', - // content: dkimRecordString, - // ttl: 18000, - // ); - - // var url = '$rootAddress/zones/$domainZoneId/dns_records'; - // loggedClient.post( - // url, - // data: txt3.toJson(), - // ); - // } - List projectDnsRecords(String? domainName, String? ip4) { var domainA = DnsRecords(type: 'A', name: domainName, content: ip4); @@ -163,13 +164,22 @@ class CloudflareApi extends ApiMapOld { Future> domainList() async { var url = '$rootAddress/zones?per_page=50'; - var response = await loggedClient.get( + var client = await getClient(); + + var response = await client.get( url, queryParameters: {'per_page': 50}, ); + client.close(); return response.data['result'] .map((el) => el['name'] as String) .toList(); } + + @override + final bool hasLoger; + + @override + final bool isWithToken; } diff --git a/lib/logic/api_maps/hetzner.dart b/lib/logic/api_maps/hetzner.dart index dabec6b712..26018a51d3 100644 --- a/lib/logic/api_maps/hetzner.dart +++ b/lib/logic/api_maps/hetzner.dart @@ -2,33 +2,50 @@ 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/server_details.dart'; import 'package:selfprivacy/logic/models/user.dart'; import 'package:selfprivacy/utils/password_generator2.dart'; -class HetznerApi extends ApiMapOld { - HetznerApi([String? token]) { - if (token != null) { - loggedClient.options = BaseOptions( - headers: {'Authorization': 'Bearer $token'}, - baseUrl: rootAddress!, - ); +class HetznerApi extends ApiMap { + bool hasLoger; + bool isWithToken; + + HetznerApi({this.hasLoger = false, this.isWithToken = true}); + + BaseOptions get options { + var options = BaseOptions(baseUrl: rootAddress); + if (isWithToken) { + var token = getIt().hetznerKey; + assert(token != null); + options.headers = {'Authorization': 'Bearer $token'}; } + + if (validateStatus != null) { + options.validateStatus = validateStatus!; + } + + return options; } + ValidateStatus? validateStatus; + @override - String? rootAddress = 'https://api.hetzner.cloud/v1/servers'; + String rootAddress = 'https://api.hetzner.cloud/v1'; Future isValid(String token) async { - var options = Options( - headers: {'Authorization': 'Bearer $token'}, - validateStatus: (status) { - return status == HttpStatus.ok || status == HttpStatus.unauthorized; - }, + validateStatus = (status) { + return status == HttpStatus.ok || status == HttpStatus.unauthorized; + }; + var client = await getClient(); + Response response = await client.get( + '/servers', + options: Options( + headers: {'Authorization': 'Bearer $token'}, + ), ); - - Response response = await loggedClient.get(rootAddress!, options: options); + client.close(); if (response.statusCode == HttpStatus.ok) { return true; @@ -40,9 +57,9 @@ class HetznerApi extends ApiMapOld { } Future createServer({ - required String? cloudFlareKey, + required String cloudFlareKey, required User rootUser, - required String? domainName, + required String domainName, }) async { var dbPassword = getRandomString(40); @@ -50,11 +67,12 @@ class HetznerApi extends ApiMapOld { '''{"name":"selfprivacy-server","server_type":"cx11","start_after_create":false,"image":"ubuntu-20.04", "volumes":[],"networks":[],"user_data":"#cloud-config\\nruncmd:\\n- curl https://git.selfprivacy.org/ilchub/selfprivacy-nixos-infect/raw/branch/master/nixos-infect | PROVIDER=hetzner NIX_CHANNEL=nixos-20.09 DOMAIN=$domainName LUSER=${rootUser.login} PASSWORD=${rootUser.password} HASHED_PASSWORD=${rootUser.hashPassword} CF_TOKEN=$cloudFlareKey DB_PASSWORD=$dbPassword bash 2>&1 | tee /tmp/infect.log","labels":{},"automount":false}''', ); - Response response = await loggedClient.post( - rootAddress!, + var client = await getClient(); + Response response = await client.post( + '/servers', data: data, ); - + client.close(); return HetznerServerDetails( id: response.data['server']['id'], ip4: response.data['server']['public_net']['ipv4']['ip'], @@ -62,20 +80,23 @@ class HetznerApi extends ApiMapOld { ); } - Future deleteSelfprivacyServer({ - required String? cloudFlareKey, - }) async { - Response response = await loggedClient.get(rootAddress!); + Future deleteSelfprivacyServer() async { + var client = await getClient(); + Response response = await client.get('/servers'); List list = response.data['servers']; var server = list.firstWhere((el) => el['name'] == 'selfprivacy-server'); - await loggedClient.delete('$rootAddress/${server['id']}'); + await client.delete('/servers/${server['id']}'); + client.close(); } Future startServer({ required HetznerServerDetails server, }) async { - await loggedClient.post('/${server.id}/actions/poweron'); + var client = await getClient(); + + await client.post('/servers/${server.id}/actions/poweron'); + client.close(); return server.copyWith( startTime: DateTime.now(), @@ -85,10 +106,25 @@ class HetznerApi extends ApiMapOld { Future restart({ required HetznerServerDetails server, }) async { - await loggedClient.post('/${server.id}/actions/poweron'); - + var client = await getClient(); + await client.post('/servers/${server.id}/actions/poweron'); + client.close(); return server.copyWith( startTime: DateTime.now(), ); } + + metrics() async { + var hetznerServer = getIt().hetznerServer; + var client = await getClient(); + await client.post('/servers/${hetznerServer!.id}/metrics'); + client.close(); + } + + getInfo() async { + var hetznerServer = getIt().hetznerServer; + var client = await getClient(); + await client.post('/servers/${hetznerServer!.id}'); + client.close(); + } } diff --git a/lib/logic/api_maps/server.dart b/lib/logic/api_maps/server.dart index 6bf5afa417..0da2704b5e 100644 --- a/lib/logic/api_maps/server.dart +++ b/lib/logic/api_maps/server.dart @@ -1,45 +1,46 @@ +import 'dart:async'; import 'dart:io'; import 'package:dio/dio.dart'; +import 'package:selfprivacy/config/get_it_config.dart'; import 'api_map.dart'; -class ServerApi extends ApiMapOld { - ServerApi(String? domainName) { - loggedClient.options = BaseOptions( - baseUrl: 'https://api.$domainName', - ); +class ServerApi extends ApiMap { + bool hasLoger; + bool isWithToken; + + ServerApi({this.hasLoger = false, this.isWithToken = true}); + + BaseOptions get options { + var options = BaseOptions(); + + if (isWithToken) { + var cloudFlareDomain = getIt().cloudFlareDomain; + var domainName = cloudFlareDomain!.domainName; + assert(domainName != null); + + options = BaseOptions(baseUrl: 'https://api.$domainName'); + } + + return options; } Future isHttpServerWorking() async { bool res; Response response; + + var client = await getClient(); try { - response = await loggedClient.get('/serviceStatus'); + response = await client.get('/serviceStatus'); res = response.statusCode == HttpStatus.ok; } catch (e) { res = false; } - + client.close(); return res; } - // Future getDkim(String domainName) async { - // var response = await loggedClient.get( - // '/getDKIM', - // options: Options(responseType: ResponseType.plain), - // ); - // return _decodeAndCutData(response.data, domainName); - // } + String get rootAddress => + throw UnimplementedError('not used in with implementation'); } - -// String _decodeAndCutData(String text, String domainName) { -// var decodedTextString = text.substring(1, text.length - 1); -// var stringToBase64 = utf8.fuse(base64); - -// return stringToBase64 -// .decode(decodedTextString) -// .replaceAll("selector._domainkey IN TXT ( ", "") -// .replaceAll("\"\n \"", "") -// .replaceAll(' ) ; ----- DKIM key selector for $domainName\n', ''); -// } diff --git a/lib/logic/cubit/app_config/app_config_cubit.dart b/lib/logic/cubit/app_config/app_config_cubit.dart index 8fc1ef7fed..2fcc365244 100644 --- a/lib/logic/cubit/app_config/app_config_cubit.dart +++ b/lib/logic/cubit/app_config/app_config_cubit.dart @@ -74,7 +74,6 @@ class AppConfigCubit extends Cubit { if (isMatch) { var server = await repository.startServer( - state.hetznerKey, state.hetznerServer!, ); repository.saveServerDetails(server); @@ -111,33 +110,30 @@ class AppConfigCubit extends Cubit { AppConfigState? state, bool isImmediate = false, }) async { - state = state ?? this.state; + var dataState = state ?? this.state; var work = () async { - emit(TimerState(dataState: state!, isLoading: true)); + emit(TimerState(dataState: dataState, isLoading: true)); - var isServerWorking = await repository.isHttpServerWorking( - state.cloudFlareDomain!.domainName, - ); + var isServerWorking = await repository.isHttpServerWorking(); if (isServerWorking) { var pauseDuration = Duration(seconds: 30); emit(TimerState( - dataState: state, + dataState: dataState, timerStart: DateTime.now(), isLoading: false, duration: pauseDuration, )); timer = Timer(pauseDuration, () async { var hetznerServerDetails = await repository.restart( - state!.hetznerKey, - state.hetznerServer!, + dataState.hetznerServer!, ); repository.saveIsServerReseted(true); repository.saveServerDetails(hetznerServerDetails); emit( - state.copyWith( + dataState.copyWith( isServerReseted: true, hetznerServer: hetznerServerDetails, isLoading: false, @@ -155,7 +151,7 @@ class AppConfigCubit extends Cubit { var pauseDuration = Duration(seconds: 60); emit( TimerState( - dataState: state, + dataState: dataState, timerStart: DateTime.now(), duration: pauseDuration, isLoading: false, @@ -176,9 +172,7 @@ class AppConfigCubit extends Cubit { var work = () async { emit(TimerState(dataState: state!, isLoading: true)); - var isServerWorking = await repository.isHttpServerWorking( - state.cloudFlareDomain!.domainName, - ); + var isServerWorking = await repository.isHttpServerWorking(); if (isServerWorking) { repository.saveHasFinalChecked(true); @@ -246,7 +240,6 @@ class AppConfigCubit extends Cubit { AppConfigState _stateCopy = state; var onSuccess = (serverDetails) async { await repository.createDnsRecords( - state.cloudFlareKey, serverDetails.ip4, state.cloudFlareDomain!, ); @@ -263,10 +256,9 @@ class AppConfigCubit extends Cubit { try { emit(state.copyWith(isLoading: true)); await repository.createServer( - state.hetznerKey, state.rootUser!, - state.cloudFlareDomain!.domainName, - state.cloudFlareKey, + state.cloudFlareDomain!.domainName!, + state.cloudFlareKey!, onCancel: onCancel, onSuccess: onSuccess, ); diff --git a/lib/logic/cubit/app_config/app_config_repository.dart b/lib/logic/cubit/app_config/app_config_repository.dart index 3980e62401..e4197d06fd 100644 --- a/lib/logic/cubit/app_config/app_config_repository.dart +++ b/lib/logic/cubit/app_config/app_config_repository.dart @@ -22,7 +22,7 @@ class AppConfigRepository { Box box = Hive.box(BNames.appConfig); AppConfigState load() { - return AppConfigState( + var res = AppConfigState( hetznerKey: getIt().hetznerKey, cloudFlareKey: getIt().cloudFlareKey, cloudFlareDomain: getIt().cloudFlareDomain, @@ -35,6 +35,8 @@ class AppConfigRepository { error: null, isLoading: box.get(BNames.isLoading, defaultValue: false), ); + + return res; } void clearAppConfig() { @@ -42,12 +44,10 @@ class AppConfigRepository { } Future startServer( - String? hetznerKey, HetznerServerDetails hetznerServer, ) async { - var hetznerApi = HetznerApi(hetznerKey); + var hetznerApi = HetznerApi(); var serverDetails = await hetznerApi.startServer(server: hetznerServer); - hetznerApi.close(); return serverDetails; } @@ -90,15 +90,14 @@ class AppConfigRepository { } Future createServer( - String? hetznerKey, User rootUser, - String? domainName, - String? cloudFlareKey, { - void Function()? onCancel, + String domainName, + String cloudFlareKey, { + required void Function() onCancel, required Future Function(HetznerServerDetails serverDetails) onSuccess, }) async { - var hetznerApi = HetznerApi(hetznerKey); + var hetznerApi = HetznerApi(); try { var serverDetails = await hetznerApi.createServer( @@ -106,7 +105,6 @@ class AppConfigRepository { rootUser: rootUser, domainName: domainName, ); - hetznerApi.close(); saveServerDetails(serverDetails); onSuccess(serverDetails); } on DioError catch (e) { @@ -121,16 +119,13 @@ class AppConfigRepository { text: 'basis.delete'.tr(), isRed: true, onPressed: () async { - await hetznerApi.deleteSelfprivacyServer( - cloudFlareKey: cloudFlareKey, - ); + await hetznerApi.deleteSelfprivacyServer(); var serverDetails = await hetznerApi.createServer( cloudFlareKey: cloudFlareKey, rootUser: rootUser, domainName: domainName, ); - hetznerApi.close(); await saveServerDetails(serverDetails); onSuccess(serverDetails); @@ -139,8 +134,7 @@ class AppConfigRepository { ActionButton( text: 'basis.cancel'.tr(), onPressed: () { - hetznerApi.close(); - onCancel!(); + onCancel(); }, ), ], @@ -151,11 +145,10 @@ class AppConfigRepository { } Future createDnsRecords( - String? cloudFlareKey, String? ip4, CloudFlareDomain cloudFlareDomain, ) async { - var cloudflareApi = CloudflareApi(cloudFlareKey); + var cloudflareApi = CloudflareApi(); await cloudflareApi.removeSimilarRecords( ip4: ip4, @@ -166,22 +159,18 @@ class AppConfigRepository { ip4: ip4, cloudFlareDomain: cloudFlareDomain, ); - - cloudflareApi.close(); } - Future isHttpServerWorking(String? domainName) async { - var api = ServerApi(domainName); + Future isHttpServerWorking() async { + var api = ServerApi(); var isHttpServerWorking = await api.isHttpServerWorking(); - api.close(); return isHttpServerWorking; } Future restart( - String? hetznerKey, HetznerServerDetails server, ) async { - var hetznerApi = HetznerApi(hetznerKey); + var hetznerApi = HetznerApi(); return await hetznerApi.restart(server: server); } diff --git a/lib/logic/cubit/forms/initializing/backblaze_form_cubit.dart b/lib/logic/cubit/forms/initializing/backblaze_form_cubit.dart index 9ecf3eaaa7..123553cfdb 100644 --- a/lib/logic/cubit/forms/initializing/backblaze_form_cubit.dart +++ b/lib/logic/cubit/forms/initializing/backblaze_form_cubit.dart @@ -5,8 +5,6 @@ import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart'; import 'package:selfprivacy/logic/models/backblaze_credential.dart'; class BackblazeFormCubit extends FormCubit { - BackblazeApi apiClient = BackblazeApi(); - BackblazeFormCubit(this.initializingCubit) { //var regExp = RegExp(r"\s+|[-!$%^&*()@+|~=`{}\[\]:<>?,.\/]"); keyId = FieldCubit( @@ -42,14 +40,14 @@ class BackblazeFormCubit extends FormCubit { final AppConfigCubit initializingCubit; - // ignore: close_sinks late final FieldCubit keyId; - // ignore: close_sinks late final FieldCubit applicationKey; @override FutureOr asyncValidation() async { late bool isKeyValid; + BackblazeApi apiClient = BackblazeApi(isWithToken: false); + try { String encodedApiKey = encodedBackblazeKey( keyId.state.value, @@ -67,11 +65,4 @@ class BackblazeFormCubit extends FormCubit { } return true; } - - @override - Future close() async { - apiClient.close(); - - return super.close(); - } } diff --git a/lib/logic/cubit/forms/initializing/cloudflare_form_cubit.dart b/lib/logic/cubit/forms/initializing/cloudflare_form_cubit.dart index cd33feea76..883470c895 100644 --- a/lib/logic/cubit/forms/initializing/cloudflare_form_cubit.dart +++ b/lib/logic/cubit/forms/initializing/cloudflare_form_cubit.dart @@ -6,8 +6,6 @@ import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/validations/validations.dart'; class CloudFlareFormCubit extends FormCubit { - CloudflareApi apiClient = CloudflareApi(); - CloudFlareFormCubit(this.initializingCubit) { var regExp = RegExp(r"\s+|[!$%^&*()@+|~=`{}\[\]:<>?,.\/]"); apiKey = FieldCubit( @@ -35,6 +33,7 @@ class CloudFlareFormCubit extends FormCubit { @override FutureOr asyncValidation() async { late bool isKeyValid; + CloudflareApi apiClient = CloudflareApi(isWithToken: false); try { isKeyValid = await apiClient.isValid(apiKey.state.value); @@ -51,8 +50,6 @@ class CloudFlareFormCubit extends FormCubit { @override Future close() async { - apiClient.close(); - return super.close(); } } diff --git a/lib/logic/cubit/forms/initializing/domain_cloudflare.dart b/lib/logic/cubit/forms/initializing/domain_cloudflare.dart index 4b1aad9103..1551027c24 100644 --- a/lib/logic/cubit/forms/initializing/domain_cloudflare.dart +++ b/lib/logic/cubit/forms/initializing/domain_cloudflare.dart @@ -4,19 +4,14 @@ import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart'; import 'package:selfprivacy/logic/models/cloudflare_domain.dart'; class DomainSetupCubit extends Cubit { - DomainSetupCubit(this.initializingCubit) : super(Initial()) { - var token = initializingCubit.state.cloudFlareKey; + DomainSetupCubit(this.initializingCubit) : super(Initial()); - assert(token != null, 'no cloudflare token'); - - api = CloudflareApi(token); - } - - AppConfigCubit initializingCubit; - late CloudflareApi api; + final AppConfigCubit initializingCubit; Future load() async { emit(Loading(LoadingTypes.loadingDomain)); + var api = CloudflareApi(); + var list = await api.domainList(); if (list.isEmpty) { emit(Empty()); @@ -29,20 +24,17 @@ class DomainSetupCubit extends Cubit { @override Future close() { - api.close(); return super.close(); } Future saveDomain() async { assert(state is Loaded, 'wrong state'); var domainName = (state as Loaded).domain; + var api = CloudflareApi(); emit(Loading(LoadingTypes.saving)); - var zoneId = await api.getZoneId( - initializingCubit.state.cloudFlareKey, - domainName, - ); + var zoneId = await api.getZoneId(domainName); var domain = CloudFlareDomain( domainName: domainName, diff --git a/lib/logic/cubit/forms/initializing/domain_form_cubit.dart b/lib/logic/cubit/forms/initializing/domain_form_cubit.dart deleted file mode 100644 index e2dfad83b3..0000000000 --- a/lib/logic/cubit/forms/initializing/domain_form_cubit.dart +++ /dev/null @@ -1,68 +0,0 @@ -// import 'dart:async'; - -// import 'package:cubit_form/cubit_form.dart'; -// import 'package:selfprivacy/logic/api_maps/cloudflare.dart'; -// import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart'; -// import 'package:selfprivacy/logic/models/cloudflare_domain.dart'; - -// class DomainFormCubit extends FormCubit { -// CloudflareApi apiClient = CloudflareApi(); - -// DomainFormCubit(this.initializingCubit) { -// var regExp = -// RegExp(r"^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}"); -// domainName = FieldCubit( -// initalValue: '', -// validations: [ -// RequiredStringValidation('required'), -// ValidationModel( -// (s) => !regExp.hasMatch(s), -// 'invalid domain format', -// ), -// ], -// ); - -// super.setFields([domainName]); -// } - -// @override -// FutureOr onSubmit() async { -// var domain = CloudFlareDomain( -// domainName: domainName.state.value, -// zoneId: zoneId, -// ); -// initializingCubit.setDomain(domain); -// } - -// final AppConfigCubit initializingCubit; - -// FieldCubit domainName; -// String zoneId; - -// @override -// FutureOr asyncValidation() async { -// var key = initializingCubit.state.cloudFlareKey; - -// String zoneId; - -// try { -// zoneId = await apiClient.getZoneId(key, domainName.state.value); -// } catch (e) { -// addError(e); -// } - -// if (zoneId == null) { -// domainName.setError('Domain not in the list'); -// return false; -// } -// this.zoneId = zoneId; -// return true; -// } - -// @override -// Future close() async { -// apiClient.close(); - -// return super.close(); -// } -// } diff --git a/lib/logic/cubit/forms/initializing/hetzner_form_cubit.dart b/lib/logic/cubit/forms/initializing/hetzner_form_cubit.dart index 78674e31be..a9e8950121 100644 --- a/lib/logic/cubit/forms/initializing/hetzner_form_cubit.dart +++ b/lib/logic/cubit/forms/initializing/hetzner_form_cubit.dart @@ -6,8 +6,6 @@ import 'package:selfprivacy/logic/cubit/forms/validations/validations.dart'; import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart'; class HetznerFormCubit extends FormCubit { - HetznerApi apiClient = HetznerApi(); - HetznerFormCubit(this.initializingCubit) { var regExp = RegExp(r"\s+|[-!$%^&*()@+|~=`{}\[\]:<>?,.\/]"); apiKey = FieldCubit( @@ -30,12 +28,13 @@ class HetznerFormCubit extends FormCubit { final AppConfigCubit initializingCubit; - // ignore: close_sinks late final FieldCubit apiKey; @override FutureOr asyncValidation() async { late bool isKeyValid; + HetznerApi apiClient = HetznerApi(isWithToken: false); + try { isKeyValid = await apiClient.isValid(apiKey.state.value); } catch (e) { @@ -48,11 +47,4 @@ class HetznerFormCubit extends FormCubit { } return true; } - - @override - Future close() async { - apiClient.close(); - - return super.close(); - } } diff --git a/lib/logic/cubit/forms/initializing/root_user_form_cubit.dart b/lib/logic/cubit/forms/initializing/root_user_form_cubit.dart index 85be05c742..b82bd0f367 100644 --- a/lib/logic/cubit/forms/initializing/root_user_form_cubit.dart +++ b/lib/logic/cubit/forms/initializing/root_user_form_cubit.dart @@ -1,13 +1,10 @@ import 'dart:async'; import 'package:cubit_form/cubit_form.dart'; -import 'package:selfprivacy/logic/api_maps/hetzner.dart'; import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart'; import 'package:selfprivacy/logic/models/user.dart'; class RootUserFormCubit extends FormCubit { - HetznerApi apiClient = HetznerApi(); - RootUserFormCubit(this.initializingCubit) { var userRegExp = RegExp(r"\W"); var passwordRegExp = RegExp(r"[\n\r\s]+"); @@ -46,17 +43,7 @@ class RootUserFormCubit extends FormCubit { final AppConfigCubit initializingCubit; - // ignore: close_sinks late final FieldCubit userName; - // ignore: close_sinks late final FieldCubit password; - // ignore: close_sinks late final FieldCubit isVisible; - - @override - Future close() async { - apiClient.close(); - - return super.close(); - } } diff --git a/lib/logic/cubit/forms/user/user_form_cubit.dart b/lib/logic/cubit/forms/user/user_form_cubit.dart index 2c874eb439..50de369e37 100644 --- a/lib/logic/cubit/forms/user/user_form_cubit.dart +++ b/lib/logic/cubit/forms/user/user_form_cubit.dart @@ -45,7 +45,6 @@ class UserFormCubit extends FormCubit { usersCubit.addUser(user); } - // ignore: close_sinks late FieldCubit login; late FieldCubit password; diff --git a/lib/logic/cubit/services/services_cubit.dart b/lib/logic/cubit/services/services_cubit.dart deleted file mode 100644 index a23b70e72e..0000000000 --- a/lib/logic/cubit/services/services_cubit.dart +++ /dev/null @@ -1,28 +0,0 @@ -// import 'package:bloc/bloc.dart'; -// import 'package:equatable/equatable.dart'; -// import 'package:meta/meta.dart'; -// import 'package:selfprivacy/logic/models/service.dart'; -// import 'package:selfprivacy/logic/models/state_types.dart'; - -// export 'package:provider/provider.dart'; -// export 'package:selfprivacy/logic/models/state_types.dart'; - -// part 'services_state.dart'; - -// class ServicesCubit extends Cubit { -// ServicesCubit() : super(ServicesState(all)); - -// void connect(Service service) { -// var newState = state.updateElement(service, StateType.stable); -// emit(newState); -// } -// } - -// final all = ServiceTypes.values -// .map( -// (type) => Service( -// state: StateType.uninitialized, -// type: type, -// ), -// ) -// .toList(); diff --git a/lib/logic/cubit/services/services_state.dart b/lib/logic/cubit/services/services_state.dart deleted file mode 100644 index d20a63a8a6..0000000000 --- a/lib/logic/cubit/services/services_state.dart +++ /dev/null @@ -1,26 +0,0 @@ -// part of 'services_cubit.dart'; - -// @immutable -// class ServicesState extends Equatable{ -// ServicesState(this.all); - -// final List all; - -// ServicesState updateElement(Service service, StateType newState) { -// var newList = [...all]; -// var index = newList.indexOf(service); -// newList[index] = service.updateState(newState); -// return ServicesState(newList); -// } - -// List get connected => all -// .where((service) => service.state != StateType.uninitialized) -// .toList(); - -// List get uninitialized => all -// .where((service) => service.state == StateType.uninitialized) -// .toList(); - -// @override -// List get props => all; -// } diff --git a/lib/logic/models/server_info.dart b/lib/logic/models/server_info.dart new file mode 100644 index 0000000000..12c7e0a8df --- /dev/null +++ b/lib/logic/models/server_info.dart @@ -0,0 +1,23 @@ +import 'package:json_annotation/json_annotation.dart'; + +@JsonSerializable(createFactory: false) +class ServerInfo { + final String id; + final String name; + final ServerStatus status; + final DateTime created; + + ServerInfo(this.id, this.name, this.status, this.created); +} + +enum ServerStatus { + running, + initializing, + starting, + stopping, + off, + deleting, + migrating, + rebuilding, + unknown, +} diff --git a/lib/logic/models/service.dart b/lib/logic/models/service.dart deleted file mode 100644 index 8ce6e310aa..0000000000 --- a/lib/logic/models/service.dart +++ /dev/null @@ -1,25 +0,0 @@ -// import 'package:equatable/equatable.dart'; -// import 'package:selfprivacy/logic/models/state_types.dart'; - -// enum ServiceTypes { -// messanger, -// mail, -// passwordManager, -// github, -// cloud, -// } - -// class Service extends Equatable { -// const Service({required this.state, required this.type}); - -// final StateType state; -// final ServiceTypes type; - -// Service updateState(StateType newState) => Service( -// state: newState, -// type: type, -// ); - -// @override -// List get props => [state, type]; -// } diff --git a/lib/main.dart b/lib/main.dart index 231a7dca28..141c95c2e9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -37,6 +37,8 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { AppSettingsState appSettings = context.watch().state; + var a = DateTime.parse('2021-03-23T20:00:06+00:00'); + print(a); return AnnotatedRegion( value: SystemUiOverlayStyle.light, // Manually changnig appbar color child: MaterialApp( diff --git a/lib/ui/pages/initializing/initializing.dart b/lib/ui/pages/initializing/initializing.dart index e26ebd5403..589ce6540b 100644 --- a/lib/ui/pages/initializing/initializing.dart +++ b/lib/ui/pages/initializing/initializing.dart @@ -408,7 +408,7 @@ class InitializingPage extends StatelessWidget { Spacer(), BrandButton.rised( onPressed: - isLoading! ? null : appConfigCubit.createServerAndSetDnsRecords, + isLoading! ? null : () => appConfigCubit.createServerAndSetDnsRecords(), title: isLoading ? 'basis.loading'.tr() : 'initializing.11'.tr(), ), Spacer(flex: 2), diff --git a/lib/ui/pages/onboarding/onboarding.dart b/lib/ui/pages/onboarding/onboarding.dart index 07790f607e..835e40e00f 100644 --- a/lib/ui/pages/onboarding/onboarding.dart +++ b/lib/ui/pages/onboarding/onboarding.dart @@ -124,8 +124,10 @@ class _OnboardingPageState extends State { BrandButton.rised( onPressed: () { context.read().turnOffOnboarding(); - Navigator.of(context) - .pushReplacement(materialRoute(widget.nextPage)); + Navigator.of(context).pushAndRemoveUntil( + materialRoute(widget.nextPage), + (route) => false, + ); }, title: 'basis.got_it'.tr(), ), diff --git a/lib/ui/pages/services/services.dart b/lib/ui/pages/services/services.dart index dd48ae6d62..69dea2b7d4 100644 --- a/lib/ui/pages/services/services.dart +++ b/lib/ui/pages/services/services.dart @@ -366,6 +366,7 @@ class _ServiceDetails extends StatelessWidget { ), SizedBox(height: 10), BrandText.h1(title), + SizedBox(height: 10), child, ], ), diff --git a/pubspec.lock b/pubspec.lock index b7ef872499..83d5ac4b92 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -574,6 +574,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.5.0" + pretty_dio_logger: + dependency: "direct main" + description: + name: pretty_dio_logger + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0-beta-1" process: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 03565a4ed4..d692fbcf46 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -25,6 +25,7 @@ dependencies: hive_flutter: ^1.0.0 json_annotation: ^4.0.0 package_info: ^2.0.0 + pretty_dio_logger: ^1.1.1 provider: ^5.0.0 url_launcher: ^6.0.2 wakelock: ^0.5.0+2