mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2024-11-19 07:09:14 +00:00
Merge pull request 'refactor: Introduce a new storage for tokens' (#505) from inex/april-refactor into master
Reviewed-on: https://git.selfprivacy.org/SelfPrivacy/selfprivacy.org.app/pulls/505
This commit is contained in:
commit
59cf273fa9
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
|
@ -31,7 +31,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"name": "debug (production)",
|
||||
"name": "debug (production flavor)",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"args": [
|
||||
|
@ -41,7 +41,7 @@
|
|||
},
|
||||
|
||||
{
|
||||
"name": "debug (nightly)",
|
||||
"name": "debug (nightly flavor)",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"args": [
|
||||
|
|
|
@ -46,12 +46,10 @@
|
|||
},
|
||||
"console_page": {
|
||||
"title": "Console",
|
||||
"waiting": "Waiting for initialization…",
|
||||
"copy": "Copy",
|
||||
"copy_raw": "Raw response",
|
||||
"history_empty": "No data yet",
|
||||
"error": "Error",
|
||||
"log": "Log",
|
||||
"rest_api_request": "Rest API Request",
|
||||
"rest_api_response": "Rest API Response",
|
||||
"graphql_request": "GraphQL Request",
|
||||
|
|
18
lib/config/config.dart
Normal file
18
lib/config/config.dart
Normal file
|
@ -0,0 +1,18 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
|
||||
/// internal app configuration
|
||||
const config = InternalConfig(
|
||||
shouldDebugPrint: kDebugMode,
|
||||
);
|
||||
|
||||
class InternalConfig {
|
||||
const InternalConfig({
|
||||
required this.shouldDebugPrint,
|
||||
});
|
||||
|
||||
final bool shouldDebugPrint;
|
||||
|
||||
// example of other possible fields
|
||||
// final String appVersion;
|
||||
//
|
||||
}
|
|
@ -3,6 +3,7 @@ import 'package:selfprivacy/logic/get_it/api_config.dart';
|
|||
import 'package:selfprivacy/logic/get_it/api_connection_repository.dart';
|
||||
import 'package:selfprivacy/logic/get_it/console_model.dart';
|
||||
import 'package:selfprivacy/logic/get_it/navigation.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
|
||||
export 'package:selfprivacy/logic/get_it/api_config.dart';
|
||||
export 'package:selfprivacy/logic/get_it/api_connection_repository.dart';
|
||||
|
@ -14,9 +15,10 @@ final GetIt getIt = GetIt.instance;
|
|||
Future<void> getItSetup() async {
|
||||
getIt.registerSingleton<NavigationService>(NavigationService());
|
||||
getIt.registerSingleton<ConsoleModel>(ConsoleModel());
|
||||
getIt.registerSingleton<ResourcesModel>(ResourcesModel()..init());
|
||||
getIt.registerSingleton<WizardDataModel>(WizardDataModel()..init());
|
||||
|
||||
final apiConfigModel = ApiConfigModel();
|
||||
await apiConfigModel.init();
|
||||
getIt.registerSingleton<ApiConfigModel>(apiConfigModel);
|
||||
|
||||
getIt.registerSingleton<ApiConnectionRepository>(
|
||||
|
|
|
@ -1,75 +1,227 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backblaze_bucket.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backups_credential.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/dns_provider_credential.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server.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/server_provider_credential.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/wizards_data/server_installation_wizard_data.dart';
|
||||
import 'package:selfprivacy/utils/app_logger.dart';
|
||||
import 'package:selfprivacy/utils/platform_adapter.dart';
|
||||
import 'package:selfprivacy/utils/secure_storage.dart';
|
||||
|
||||
class HiveConfig {
|
||||
static final log = const AppLogger(name: 'hive_config').log;
|
||||
|
||||
/// bump on schema changes
|
||||
static const version = 2;
|
||||
|
||||
static Future<void> init() async {
|
||||
final String? storagePath = PlatformAdapter.storagePath;
|
||||
print('HiveConfig: Custom storage path: $storagePath');
|
||||
log('set custom storage path to: "$storagePath"');
|
||||
|
||||
await Hive.initFlutter(storagePath);
|
||||
Hive.registerAdapter(UserAdapter());
|
||||
Hive.registerAdapter(ServerHostingDetailsAdapter());
|
||||
Hive.registerAdapter(ServerDomainAdapter());
|
||||
Hive.registerAdapter(BackupsCredentialAdapter());
|
||||
Hive.registerAdapter(BackblazeBucketAdapter());
|
||||
Hive.registerAdapter(ServerProviderVolumeAdapter());
|
||||
Hive.registerAdapter(UserTypeAdapter());
|
||||
Hive.registerAdapter(DnsProviderTypeAdapter());
|
||||
Hive.registerAdapter(ServerProviderTypeAdapter());
|
||||
Hive.registerAdapter(BackupsProviderTypeAdapter());
|
||||
|
||||
await Hive.openBox(BNames.appSettingsBox);
|
||||
registerAdapters();
|
||||
await decryptBoxes();
|
||||
await performMigrations();
|
||||
}
|
||||
|
||||
static void registerAdapters() {
|
||||
try {
|
||||
final HiveAesCipher cipher = HiveAesCipher(
|
||||
await getEncryptedKey(BNames.serverInstallationEncryptionKey),
|
||||
Hive.registerAdapter(UserAdapter());
|
||||
Hive.registerAdapter(ServerHostingDetailsAdapter());
|
||||
Hive.registerAdapter(ServerDomainAdapter());
|
||||
Hive.registerAdapter(BackupsCredentialAdapter());
|
||||
Hive.registerAdapter(ServerProviderVolumeAdapter());
|
||||
Hive.registerAdapter(BackblazeBucketAdapter());
|
||||
Hive.registerAdapter(ServerProviderCredentialAdapter());
|
||||
Hive.registerAdapter(DnsProviderCredentialAdapter());
|
||||
Hive.registerAdapter(ServerAdapter());
|
||||
Hive.registerAdapter(DnsProviderTypeAdapter());
|
||||
Hive.registerAdapter(ServerProviderTypeAdapter());
|
||||
Hive.registerAdapter(UserTypeAdapter());
|
||||
Hive.registerAdapter(BackupsProviderTypeAdapter());
|
||||
Hive.registerAdapter(ServerInstallationWizardDataAdapter());
|
||||
log('successfully registered every adapter');
|
||||
} catch (error, stackTrace) {
|
||||
log(
|
||||
'error registering adapters',
|
||||
error: error,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
await Hive.openBox<User>(BNames.usersDeprecated);
|
||||
await Hive.openBox<User>(BNames.usersBox, encryptionCipher: cipher);
|
||||
static Future<HiveAesCipher> getCipher() async {
|
||||
List<int>? key = await SecureStorage.getKey();
|
||||
if (key == null) {
|
||||
key = Hive.generateSecureKey();
|
||||
await SecureStorage.setKey(key);
|
||||
}
|
||||
return HiveAesCipher(key);
|
||||
}
|
||||
|
||||
final Box<User> deprecatedUsers = Hive.box<User>(BNames.usersDeprecated);
|
||||
if (deprecatedUsers.isNotEmpty) {
|
||||
final Box<User> users = Hive.box<User>(BNames.usersBox);
|
||||
await users.addAll(deprecatedUsers.values.toList());
|
||||
await deprecatedUsers.clear();
|
||||
}
|
||||
static Future<void> decryptBoxes() async {
|
||||
try {
|
||||
// load encrypted boxes into memory
|
||||
final HiveAesCipher cipher = await getCipher();
|
||||
|
||||
await Hive.openBox(
|
||||
BNames.serverInstallationBox,
|
||||
encryptionCipher: cipher,
|
||||
);
|
||||
} on PlatformException catch (e) {
|
||||
print('HiveConfig: Error while opening boxes: $e');
|
||||
await Hive.openBox(
|
||||
BNames.resourcesBox,
|
||||
encryptionCipher: cipher,
|
||||
);
|
||||
await Hive.openBox(
|
||||
BNames.wizardDataBox,
|
||||
encryptionCipher: cipher,
|
||||
);
|
||||
log('successfully decrypted boxes');
|
||||
} catch (error, stackTrace) {
|
||||
log(
|
||||
'error initializing encrypted boxes',
|
||||
error: error,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<Uint8List> getEncryptedKey(final String encKey) async {
|
||||
const FlutterSecureStorage secureStorage = FlutterSecureStorage();
|
||||
// migrations
|
||||
|
||||
static Future<void> performMigrations() async {
|
||||
try {
|
||||
final bool hasEncryptionKey =
|
||||
await secureStorage.containsKey(key: encKey);
|
||||
if (!hasEncryptionKey) {
|
||||
final List<int> key = Hive.generateSecureKey();
|
||||
await secureStorage.write(key: encKey, value: base64UrlEncode(key));
|
||||
// perform migration check
|
||||
final localSettingsBox = await Hive.openBox(BNames.appSettingsBox);
|
||||
|
||||
// if it is an initial app launch, we do not need to perform any migrations
|
||||
final savedVersion = localSettingsBox.isEmpty
|
||||
? version
|
||||
// if box was initialized, but database version was not introduced in
|
||||
// it yet, it means that we have initial value
|
||||
: await localSettingsBox.get(BNames.databaseVersion, defaultValue: 1);
|
||||
|
||||
/// launch migrations based on version
|
||||
if (savedVersion < version) {
|
||||
if (savedVersion < 2) {
|
||||
await migrateFrom1To2();
|
||||
}
|
||||
|
||||
/// add new migrations here, like:
|
||||
/// if (version < 3) {...}, etc.
|
||||
}
|
||||
|
||||
final String? string = await secureStorage.read(key: encKey);
|
||||
return base64Url.decode(string!);
|
||||
} on PlatformException catch (e) {
|
||||
print('HiveConfig: Error while getting encryption key: $e');
|
||||
/// update saved version after successfull migrations
|
||||
await localSettingsBox.put(BNames.databaseVersion, version);
|
||||
} catch (error, stackTrace) {
|
||||
log(
|
||||
'error running db migrations',
|
||||
error: error,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// introduce and populate resourcesBox
|
||||
static Future<void> migrateFrom1To2() async {
|
||||
final Box resourcesBox = Hive.box(BNames.resourcesBox);
|
||||
if (resourcesBox.isEmpty) {
|
||||
final Box serverInstallationBox = Hive.box(BNames.serverInstallationBox);
|
||||
|
||||
final ServerHostingDetails? serverDetails =
|
||||
serverInstallationBox.get(BNames.serverDetails);
|
||||
|
||||
// move server provider config
|
||||
|
||||
final ServerProviderType? serverProvider =
|
||||
serverInstallationBox.get(BNames.serverProvider) ??
|
||||
serverDetails?.provider;
|
||||
final String? serverProviderKey =
|
||||
serverInstallationBox.get(BNames.hetznerKey);
|
||||
|
||||
if (serverProviderKey != null && serverProvider.isSpecified) {
|
||||
final ServerProviderCredential serverProviderCredential =
|
||||
ServerProviderCredential(
|
||||
tokenId: null,
|
||||
token: serverProviderKey,
|
||||
provider: serverProvider!,
|
||||
associatedServerIds: [if (serverDetails != null) serverDetails.id],
|
||||
);
|
||||
|
||||
await resourcesBox.put(
|
||||
BNames.serverProviderTokens,
|
||||
[serverProviderCredential],
|
||||
);
|
||||
}
|
||||
|
||||
final String? serverLocation =
|
||||
serverInstallationBox.get(BNames.serverLocation);
|
||||
final String? serverType =
|
||||
serverInstallationBox.get(BNames.serverTypeIdentifier);
|
||||
final ServerDomain? serverDomain =
|
||||
serverInstallationBox.get(BNames.serverDomain);
|
||||
|
||||
if (serverDetails != null && serverDomain != null) {
|
||||
await resourcesBox.put(
|
||||
BNames.servers,
|
||||
[
|
||||
Server(
|
||||
domain: serverDomain,
|
||||
hostingDetails: serverDetails.copyWith(
|
||||
serverLocation: serverLocation,
|
||||
serverType: serverType,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// move dns config
|
||||
final String? dnsProviderKey =
|
||||
serverInstallationBox.get(BNames.cloudFlareKey);
|
||||
final DnsProviderType? dnsProvider =
|
||||
serverInstallationBox.get(BNames.dnsProvider) ??
|
||||
serverDomain?.provider;
|
||||
|
||||
if (dnsProviderKey != null && dnsProvider.isSpecified) {
|
||||
final DnsProviderCredential dnsProviderCredential =
|
||||
DnsProviderCredential(
|
||||
tokenId: null,
|
||||
token: dnsProviderKey,
|
||||
provider: dnsProvider!,
|
||||
associatedDomainNames: [
|
||||
if (serverDomain != null) serverDomain.domainName,
|
||||
],
|
||||
);
|
||||
|
||||
await resourcesBox
|
||||
.put(BNames.dnsProviderTokens, [dnsProviderCredential]);
|
||||
}
|
||||
|
||||
// move backblaze (backups) config
|
||||
final BackupsCredential? backblazeCredential =
|
||||
serverInstallationBox.get(BNames.backblazeCredential);
|
||||
final BackblazeBucket? backblazeBucket =
|
||||
serverInstallationBox.get(BNames.backblazeBucket);
|
||||
|
||||
if (backblazeCredential != null) {
|
||||
await resourcesBox
|
||||
.put(BNames.backupsProviderTokens, [backblazeCredential]);
|
||||
}
|
||||
|
||||
if (backblazeBucket != null) {
|
||||
await resourcesBox.put(BNames.backblazeBucket, backblazeBucket);
|
||||
}
|
||||
}
|
||||
log('successfully migrated db from 1 to 2 version');
|
||||
}
|
||||
}
|
||||
|
||||
/// Mappings for the different boxes and their keys
|
||||
|
@ -77,6 +229,9 @@ class BNames {
|
|||
/// App settings box. Contains app settings like [darkThemeModeOn], [shouldShowOnboarding]
|
||||
static String appSettingsBox = 'appSettings';
|
||||
|
||||
/// An integer with last saved version of the database
|
||||
static String databaseVersion = 'databaseVersion';
|
||||
|
||||
/// A boolean field of [appSettingsBox] box.
|
||||
static String darkThemeModeOn = 'isDarkModeOn';
|
||||
|
||||
|
@ -89,9 +244,6 @@ class BNames {
|
|||
/// A string field
|
||||
static String appLocale = 'appLocale';
|
||||
|
||||
/// Encryption key to decrypt [serverInstallationBox] and [usersBox] box.
|
||||
static String serverInstallationEncryptionKey = 'key';
|
||||
|
||||
/// Server installation box. Contains server details and provider tokens.
|
||||
static String serverInstallationBox = 'appConfig';
|
||||
|
||||
|
@ -122,7 +274,7 @@ class BNames {
|
|||
/// A String field of [serverInstallationBox] box.
|
||||
static String cloudFlareKey = 'cloudFlareKey';
|
||||
|
||||
/// A String field of [serverTypeIdentifier] box.
|
||||
/// A String field of [serverInstallationBox] box.
|
||||
static String serverTypeIdentifier = 'serverTypeIdentifier';
|
||||
|
||||
/// A [User] field of [serverInstallationBox] box.
|
||||
|
@ -149,9 +301,24 @@ class BNames {
|
|||
/// A boolean field of [serverInstallationBox] box.
|
||||
static String isRecoveringServer = 'isRecoveringServer';
|
||||
|
||||
/// Deprecated users box as it is unencrypted
|
||||
static String usersDeprecated = 'users';
|
||||
/// Resources and provider tokens box,
|
||||
static String resourcesBox = 'resourcesBox';
|
||||
|
||||
/// Box with users
|
||||
static String usersBox = 'usersEncrypted';
|
||||
/// Server Provider Tokens of [resourcesBox] box.
|
||||
static String serverProviderTokens = 'serverProviderTokens';
|
||||
|
||||
/// DNS Provider Tokens of [resourcesBox] box.
|
||||
static String dnsProviderTokens = 'dnsProviderTokens';
|
||||
|
||||
/// Backups Provider Tokens of [resourcesBox] box.
|
||||
static String backupsProviderTokens = 'backupsProviderTokens';
|
||||
|
||||
/// Servers of [resourcesBox] box.
|
||||
static String servers = 'servers';
|
||||
|
||||
/// Wizard data box
|
||||
static String wizardDataBox = 'wizardDataBox';
|
||||
|
||||
/// Server installation wizard data of [wizardDataBox] box.
|
||||
static String serverInstallationWizardData = 'serverInstallationWizardData';
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:graphql_flutter/graphql_flutter.dart';
|
|||
import 'package:http/io_client.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/tls_options.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
import 'package:selfprivacy/logic/models/console_log.dart';
|
||||
|
||||
void _addConsoleLog(final ConsoleLog message) =>
|
||||
|
@ -120,7 +121,7 @@ abstract class GraphQLApiMap {
|
|||
|
||||
String get _token {
|
||||
String token = '';
|
||||
final serverDetails = getIt<ApiConfigModel>().serverDetails;
|
||||
final serverDetails = getIt<ResourcesModel>().serverDetails;
|
||||
if (serverDetails != null) {
|
||||
token = serverDetails.apiToken;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server_api.graphq
|
|||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/server_settings.graphql.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/services.graphql.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/users.graphql.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart';
|
||||
import 'package:selfprivacy/logic/models/backup.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
|
@ -57,7 +58,7 @@ class ServerApi extends GraphQLApiMap
|
|||
String customToken;
|
||||
@override
|
||||
String? get rootAddress =>
|
||||
overrideDomain ?? getIt<ApiConfigModel>().serverDomain?.domainName;
|
||||
overrideDomain ?? getIt<ResourcesModel>().serverDomain?.domainName;
|
||||
String? overrideDomain;
|
||||
|
||||
Future<String?> getApiVersion() async {
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:dio/dio.dart';
|
|||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/generic_result.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/rest_api_map.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
import 'package:selfprivacy/logic/models/backup.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backblaze_bucket.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backups_credential.dart';
|
||||
|
@ -39,7 +40,7 @@ class BackblazeApi extends RestApiMap {
|
|||
);
|
||||
if (isWithToken) {
|
||||
final BackupsCredential? backblazeCredential =
|
||||
getIt<ApiConfigModel>().backblazeCredential;
|
||||
getIt<ResourcesModel>().backblazeCredential;
|
||||
final String token = backblazeCredential!.applicationKey;
|
||||
options.headers = {'Authorization': 'Basic $token'};
|
||||
}
|
||||
|
@ -59,7 +60,7 @@ class BackblazeApi extends RestApiMap {
|
|||
Future<BackblazeApiAuth> getAuthorizationToken() async {
|
||||
final Dio client = await getClient();
|
||||
final BackupsCredential? backblazeCredential =
|
||||
getIt<ApiConfigModel>().backblazeCredential;
|
||||
getIt<ResourcesModel>().backblazeCredential;
|
||||
if (backblazeCredential == null) {
|
||||
throw Exception('Backblaze credential is null');
|
||||
}
|
||||
|
@ -124,7 +125,7 @@ class BackblazeApi extends RestApiMap {
|
|||
Future<String> createBucket(final String bucketName) async {
|
||||
final BackblazeApiAuth auth = await getAuthorizationToken();
|
||||
final BackupsCredential? backblazeCredential =
|
||||
getIt<ApiConfigModel>().backblazeCredential;
|
||||
getIt<ResourcesModel>().backblazeCredential;
|
||||
final Dio client = await getClient();
|
||||
client.options.baseUrl = auth.apiUrl;
|
||||
final Response response = await client.post(
|
||||
|
@ -161,7 +162,7 @@ class BackblazeApi extends RestApiMap {
|
|||
final Response response = await client.post(
|
||||
'$apiPrefix/b2_create_key',
|
||||
data: {
|
||||
'accountId': getIt<ApiConfigModel>().backblazeCredential!.keyId,
|
||||
'accountId': getIt<ResourcesModel>().backblazeCredential!.keyId,
|
||||
'bucketId': bucketId,
|
||||
'capabilities': ['listBuckets', 'listFiles', 'readFiles', 'writeFiles'],
|
||||
'keyName': 'selfprivacy-restricted-server-key',
|
||||
|
@ -192,7 +193,7 @@ class BackblazeApi extends RestApiMap {
|
|||
final Response response = await client.get(
|
||||
'$apiPrefix/b2_list_buckets',
|
||||
queryParameters: {
|
||||
'accountId': getIt<ApiConfigModel>().backblazeCredential!.keyId,
|
||||
'accountId': getIt<ResourcesModel>().backblazeCredential!.keyId,
|
||||
},
|
||||
options: Options(
|
||||
headers: {'Authorization': auth.authorizationToken},
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:dio/dio.dart';
|
|||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/generic_result.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/rest_api_map.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
import 'package:selfprivacy/logic/models/json/dns_providers/cloudflare_dns_info.dart';
|
||||
|
||||
class CloudflareApi extends RestApiMap {
|
||||
|
@ -27,7 +28,7 @@ class CloudflareApi extends RestApiMap {
|
|||
responseType: ResponseType.json,
|
||||
);
|
||||
if (isWithToken) {
|
||||
final String? token = getIt<ApiConfigModel>().dnsProviderKey;
|
||||
final String? token = getIt<ResourcesModel>().dnsProviderKey;
|
||||
assert(token != null);
|
||||
options.headers = {'Authorization': 'Bearer $token'};
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:dio/dio.dart';
|
|||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/generic_result.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/rest_api_map.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
import 'package:selfprivacy/logic/models/json/dns_providers/desec_dns_info.dart';
|
||||
|
||||
class DesecApi extends RestApiMap {
|
||||
|
@ -27,7 +28,7 @@ class DesecApi extends RestApiMap {
|
|||
responseType: ResponseType.json,
|
||||
);
|
||||
if (isWithToken) {
|
||||
final String? token = getIt<ApiConfigModel>().dnsProviderKey;
|
||||
final String? token = getIt<ResourcesModel>().dnsProviderKey;
|
||||
assert(token != null);
|
||||
options.headers = {'Authorization': 'Token $token'};
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:dio/dio.dart';
|
|||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/generic_result.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/rest_api_map.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
import 'package:selfprivacy/logic/models/json/dns_providers/digital_ocean_dns_info.dart';
|
||||
|
||||
class DigitalOceanDnsApi extends RestApiMap {
|
||||
|
@ -27,7 +28,7 @@ class DigitalOceanDnsApi extends RestApiMap {
|
|||
responseType: ResponseType.json,
|
||||
);
|
||||
if (isWithToken) {
|
||||
final String? token = getIt<ApiConfigModel>().dnsProviderKey;
|
||||
final String? token = getIt<ResourcesModel>().dnsProviderKey;
|
||||
assert(token != null);
|
||||
options.headers = {'Authorization': 'Bearer $token'};
|
||||
}
|
||||
|
|
|
@ -1,19 +1,25 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:dio/io.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
|
||||
import 'package:selfprivacy/config/config.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/models/console_log.dart';
|
||||
import 'package:selfprivacy/utils/app_logger.dart';
|
||||
|
||||
abstract class RestApiMap {
|
||||
static final log = const AppLogger(name: 'rest_api_map').log;
|
||||
|
||||
Future<Dio> getClient({final BaseOptions? customOptions}) async {
|
||||
final Dio dio = Dio(customOptions ?? (await options));
|
||||
if (hasLogger) {
|
||||
dio.interceptors.add(PrettyDioLogger());
|
||||
if (hasLogger && config.shouldDebugPrint) {
|
||||
dio.interceptors.add(
|
||||
PrettyDioLogger(logPrint: (final object) => debugPrint('$object')),
|
||||
);
|
||||
}
|
||||
dio.interceptors.add(ConsoleInterceptor());
|
||||
dio.httpClientAdapter = IOHttpClientAdapter(
|
||||
|
@ -28,14 +34,13 @@ abstract class RestApiMap {
|
|||
|
||||
dio.interceptors.add(
|
||||
InterceptorsWrapper(
|
||||
onError: (final DioException e, final ErrorInterceptorHandler handler) {
|
||||
print(e.requestOptions.path);
|
||||
print(e.requestOptions.data);
|
||||
onError: (
|
||||
final DioException exception,
|
||||
final ErrorInterceptorHandler handler,
|
||||
) {
|
||||
log('got dio exception:', error: exception);
|
||||
|
||||
print(e.message);
|
||||
print(e.response);
|
||||
|
||||
return handler.next(e);
|
||||
return handler.next(exception);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -103,7 +108,6 @@ class ConsoleInterceptor extends InterceptorsWrapper {
|
|||
final ErrorInterceptorHandler handler,
|
||||
) async {
|
||||
final Response? response = err.response;
|
||||
log(err.toString());
|
||||
|
||||
addConsoleLog(
|
||||
ManualConsoleLog.warning(
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:selfprivacy/config/get_it_config.dart';
|
|||
import 'package:selfprivacy/logic/api_maps/generic_result.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/rest_api_map.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/tls_options.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
import 'package:selfprivacy/logic/models/json/digital_ocean_server_info.dart';
|
||||
import 'package:selfprivacy/utils/password_generator.dart';
|
||||
|
@ -30,7 +31,7 @@ class DigitalOceanApi extends RestApiMap {
|
|||
responseType: ResponseType.json,
|
||||
);
|
||||
if (isWithToken) {
|
||||
final String? token = getIt<ApiConfigModel>().serverProviderKey;
|
||||
final String? token = getIt<ResourcesModel>().serverProviderKey;
|
||||
assert(token != null);
|
||||
options.headers = {'Authorization': 'Bearer $token'};
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:selfprivacy/config/get_it_config.dart';
|
|||
import 'package:selfprivacy/logic/api_maps/generic_result.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/rest_maps/rest_api_map.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/tls_options.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
import 'package:selfprivacy/logic/models/json/hetzner_server_info.dart';
|
||||
|
@ -31,7 +32,7 @@ class HetznerApi extends RestApiMap {
|
|||
responseType: ResponseType.json,
|
||||
);
|
||||
if (isWithToken) {
|
||||
final String? token = getIt<ApiConfigModel>().serverProviderKey;
|
||||
final String? token = getIt<ResourcesModel>().serverProviderKey;
|
||||
assert(token != null);
|
||||
options.headers = {'Authorization': 'Bearer $token'};
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ 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/rest_maps/backblaze.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
import 'package:selfprivacy/logic/models/backup.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backblaze_bucket.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backups_credential.dart';
|
||||
|
@ -108,7 +109,7 @@ class BackupsBloc extends Bloc<BackupsEvent, BackupsState> {
|
|||
final BackupsServerLoaded event,
|
||||
final Emitter<BackupsState> emit,
|
||||
) async {
|
||||
BackblazeBucket? bucket = getIt<ApiConfigModel>().backblazeBucket;
|
||||
BackblazeBucket? bucket = getIt<ResourcesModel>().backblazeBucket;
|
||||
final backups = getIt<ApiConnectionRepository>().apiData.backups;
|
||||
final backupConfig = getIt<ApiConnectionRepository>().apiData.backupConfig;
|
||||
if (backupConfig.data == null || backups.data == null) {
|
||||
|
@ -227,7 +228,7 @@ class BackupsBloc extends Bloc<BackupsEvent, BackupsState> {
|
|||
emit(BackupsUnititialized());
|
||||
return;
|
||||
}
|
||||
final BackblazeBucket? bucket = getIt<ApiConfigModel>().backblazeBucket;
|
||||
final BackblazeBucket? bucket = getIt<ResourcesModel>().backblazeBucket;
|
||||
emit(
|
||||
BackupsInitialized(
|
||||
backblazeBucket: bucket,
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:selfprivacy/config/get_it_config.dart';
|
|||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||
|
||||
import 'package:selfprivacy/logic/cubit/metrics/metrics_cubit.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
import 'package:selfprivacy/logic/providers/providers_controller.dart';
|
||||
|
||||
class MetricsLoadException implements Exception {
|
||||
|
@ -30,7 +31,7 @@ class MetricsRepository {
|
|||
break;
|
||||
}
|
||||
|
||||
final serverId = getIt<ApiConfigModel>().serverDetails!.id;
|
||||
final serverId = getIt<ResourcesModel>().serverDetails!.id;
|
||||
final result = await ProvidersController.currentServerProvider!.getMetrics(
|
||||
serverId,
|
||||
start,
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_connection_dependent/server_connection_dependent_cubit.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart';
|
||||
import 'package:selfprivacy/logic/models/server_metadata.dart';
|
||||
import 'package:selfprivacy/logic/models/ssh_settings.dart';
|
||||
|
@ -43,7 +44,7 @@ class ServerDetailsCubit
|
|||
final serverProviderApi = ProvidersController.currentServerProvider;
|
||||
final dnsProviderApi = ProvidersController.currentDnsProvider;
|
||||
if (serverProviderApi != null && dnsProviderApi != null) {
|
||||
final serverId = getIt<ApiConfigModel>().serverDetails?.id ?? 0;
|
||||
final serverId = getIt<ResourcesModel>().serverDetails?.id ?? 0;
|
||||
final metadataResult = await serverProviderApi.getMetadata(serverId);
|
||||
metadataResult.data.add(
|
||||
ServerMetadataEntity(
|
||||
|
@ -60,7 +61,7 @@ class ServerDetailsCubit
|
|||
}
|
||||
|
||||
void check() async {
|
||||
final bool isReadyToCheck = getIt<ApiConfigModel>().serverDetails != null;
|
||||
final bool isReadyToCheck = getIt<ResourcesModel>().serverDetails != null;
|
||||
try {
|
||||
if (isReadyToCheck) {
|
||||
emit(const ServerDetailsLoading());
|
||||
|
|
|
@ -15,6 +15,7 @@ import 'package:selfprivacy/logic/models/hive/backups_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/hive/wizards_data/server_installation_wizard_data.dart';
|
||||
import 'package:selfprivacy/logic/models/launch_installation_data.dart';
|
||||
import 'package:selfprivacy/logic/models/price.dart';
|
||||
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
||||
|
@ -222,12 +223,14 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
provider: BackupsProviderType.backblaze,
|
||||
);
|
||||
final BackblazeBucket? bucket;
|
||||
await repository.saveBackblazeKey(backblazeCredential);
|
||||
await repository.saveBackupsCredential(backblazeCredential);
|
||||
if (state is ServerInstallationRecovery) {
|
||||
final configuration = await ServerApi(
|
||||
customToken:
|
||||
(state as ServerInstallationRecovery).serverDetails!.apiToken,
|
||||
isWithToken: true,
|
||||
overrideDomain:
|
||||
(state as ServerInstallationRecovery).serverDomain!.domainName,
|
||||
).getBackupsConfiguration();
|
||||
if (configuration != null) {
|
||||
try {
|
||||
|
@ -401,7 +404,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
);
|
||||
timer = Timer(pauseDuration, () async {
|
||||
final ServerHostingDetails serverDetails = await repository.restart();
|
||||
await repository.saveIsServerResetedFirstTime(true);
|
||||
await repository.saveIsServerRebootedFirstTime(true);
|
||||
await repository.saveServerDetails(serverDetails);
|
||||
|
||||
final ServerInstallationNotFinished newState = dataState.copyWith(
|
||||
|
@ -442,7 +445,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
);
|
||||
timer = Timer(pauseDuration, () async {
|
||||
final ServerHostingDetails serverDetails = await repository.restart();
|
||||
await repository.saveIsServerResetedSecondTime(true);
|
||||
await repository.saveIsServerRebootedSecondTime(true);
|
||||
await repository.saveServerDetails(serverDetails);
|
||||
|
||||
final ServerInstallationNotFinished newState = dataState.copyWith(
|
||||
|
@ -577,10 +580,12 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
final ServerProviderType serverProvider = await ServerApi(
|
||||
customToken: serverDetails.apiToken,
|
||||
isWithToken: true,
|
||||
overrideDomain: serverDomain.domainName,
|
||||
).getServerProviderType();
|
||||
final dnsProvider = await ServerApi(
|
||||
customToken: serverDetails.apiToken,
|
||||
isWithToken: true,
|
||||
overrideDomain: serverDomain.domainName,
|
||||
).getDnsProviderType();
|
||||
if (serverProvider == ServerProviderType.unknown ||
|
||||
dnsProvider == DnsProviderType.unknown) {
|
||||
|
@ -762,6 +767,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
final dnsProviderType = await ServerApi(
|
||||
customToken: dataState.serverDetails!.apiToken,
|
||||
isWithToken: true,
|
||||
overrideDomain: serverDomain.domainName,
|
||||
).getDnsProviderType();
|
||||
await repository.saveDomain(
|
||||
ServerDomain(
|
||||
|
@ -769,6 +775,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
provider: dnsProviderType,
|
||||
),
|
||||
);
|
||||
await repository.setDnsApiToken(token);
|
||||
emit(
|
||||
dataState.copyWith(
|
||||
serverDomain: ServerDomain(
|
||||
|
@ -785,21 +792,18 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
|||
final BackupsCredential backblazeCredential,
|
||||
) async {
|
||||
await repository.saveIsServerStarted(true);
|
||||
await repository.saveIsServerResetedFirstTime(true);
|
||||
await repository.saveIsServerResetedSecondTime(true);
|
||||
await repository.saveHasFinalChecked(true);
|
||||
await repository.saveIsServerRebootedFirstTime(true);
|
||||
await repository.saveIsServerRebootedSecondTime(true);
|
||||
await repository.saveIsRecoveringServer(false);
|
||||
final serverType = await ProvidersController.currentServerProvider!
|
||||
.getServerType(state.serverDetails!.id);
|
||||
await repository.saveServerType(serverType.data!);
|
||||
await ProvidersController.currentServerProvider!
|
||||
.trySetServerLocation(serverType.data!.location.identifier);
|
||||
final User mainUser = await repository.getMainUser();
|
||||
await repository.saveRootUser(mainUser);
|
||||
await repository.saveHasFinalChecked(true);
|
||||
final ServerInstallationRecovery updatedState =
|
||||
(state as ServerInstallationRecovery).copyWith(
|
||||
backblazeCredential: backblazeCredential,
|
||||
rootUser: mainUser,
|
||||
serverTypeIdentificator: serverType.data!.identifier,
|
||||
);
|
||||
emit(updatedState.finish());
|
||||
|
|
|
@ -9,10 +9,15 @@ import 'package:selfprivacy/config/hive_config.dart';
|
|||
import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server_api.dart';
|
||||
import 'package:selfprivacy/logic/api_maps/tls_options.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backups_credential.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/dns_provider_credential.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server.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/server_provider_credential.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/wizards_data/server_installation_wizard_data.dart';
|
||||
import 'package:selfprivacy/logic/models/json/device_token.dart';
|
||||
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
||||
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
||||
|
@ -34,22 +39,25 @@ class ServerAuthorizationException implements Exception {
|
|||
|
||||
class ServerInstallationRepository {
|
||||
Box box = Hive.box(BNames.serverInstallationBox);
|
||||
Box<User> usersBox = Hive.box(BNames.usersBox);
|
||||
|
||||
Future<ServerInstallationState> load() async {
|
||||
final String? providerApiToken = getIt<ApiConfigModel>().serverProviderKey;
|
||||
final String? location = getIt<ApiConfigModel>().serverLocation;
|
||||
final String? dnsApiToken = getIt<ApiConfigModel>().dnsProviderKey;
|
||||
final String? serverTypeIdentificator = getIt<ApiConfigModel>().serverType;
|
||||
final ServerDomain? serverDomain = getIt<ApiConfigModel>().serverDomain;
|
||||
final DnsProviderType? dnsProvider = getIt<ApiConfigModel>().dnsProvider;
|
||||
final ServerInstallationWizardData? wizardData =
|
||||
getIt<WizardDataModel>().serverInstallation;
|
||||
final List<Server> servers = getIt<ResourcesModel>().servers;
|
||||
final String? providerApiToken = getIt<ResourcesModel>().serverProviderKey;
|
||||
final String? location = getIt<ResourcesModel>().serverLocation;
|
||||
final String? dnsApiToken = getIt<ResourcesModel>().dnsProviderKey;
|
||||
final String? serverTypeIdentificator = getIt<ResourcesModel>().serverType;
|
||||
final ServerDomain? serverDomain = getIt<ResourcesModel>().serverDomain;
|
||||
final DnsProviderType? dnsProvider = getIt<ResourcesModel>().dnsProvider;
|
||||
final ServerProviderType? serverProvider =
|
||||
getIt<ApiConfigModel>().serverProvider;
|
||||
getIt<ResourcesModel>().serverProvider;
|
||||
final BackupsCredential? backblazeCredential =
|
||||
getIt<ApiConfigModel>().backblazeCredential;
|
||||
getIt<ResourcesModel>().backblazeCredential;
|
||||
final ServerHostingDetails? serverDetails =
|
||||
getIt<ApiConfigModel>().serverDetails;
|
||||
getIt<ResourcesModel>().serverDetails;
|
||||
|
||||
// TODO: Init server providers in another place
|
||||
if (serverProvider != null ||
|
||||
(serverDetails != null &&
|
||||
serverDetails.provider != ServerProviderType.unknown)) {
|
||||
|
@ -73,85 +81,48 @@ class ServerInstallationRepository {
|
|||
);
|
||||
}
|
||||
|
||||
if (box.get(BNames.hasFinalChecked, defaultValue: false)) {
|
||||
TlsOptions.verifyCertificate = true;
|
||||
if (serverTypeIdentificator == null && serverDetails != null) {
|
||||
final finalServerType = await ProvidersController.currentServerProvider!
|
||||
.getServerType(serverDetails.id);
|
||||
await saveServerType(finalServerType.data!);
|
||||
await ProvidersController.currentServerProvider!
|
||||
.trySetServerLocation(finalServerType.data!.location.identifier);
|
||||
return ServerInstallationFinished(
|
||||
installationDialoguePopUp: null,
|
||||
providerApiToken: providerApiToken!,
|
||||
serverTypeIdentificator: finalServerType.data!.identifier,
|
||||
dnsApiToken: dnsApiToken!,
|
||||
serverDomain: serverDomain!,
|
||||
backblazeCredential: backblazeCredential!,
|
||||
serverDetails: serverDetails,
|
||||
rootUser: box.get(BNames.rootUser),
|
||||
isServerStarted: box.get(BNames.isServerStarted, defaultValue: false),
|
||||
isServerResetedFirstTime:
|
||||
box.get(BNames.isServerResetedFirstTime, defaultValue: false),
|
||||
isServerResetedSecondTime:
|
||||
box.get(BNames.isServerResetedSecondTime, defaultValue: false),
|
||||
// If we don't have any wizard data, we either have a server set up, or we are starting from scratch
|
||||
// This behaviour shall change when we introduce multitenancy
|
||||
if (wizardData == null) {
|
||||
if (servers.isEmpty) {
|
||||
// We don't have anything set up, so we start from scratch
|
||||
return ServerInstallationNotFinished.fromWizardData(
|
||||
ServerInstallationWizardData.empty(),
|
||||
);
|
||||
} else {
|
||||
// We have a server set up, so we load it
|
||||
TlsOptions.verifyCertificate = true;
|
||||
return ServerInstallationFinished(
|
||||
installationDialoguePopUp: null,
|
||||
providerApiToken: providerApiToken!,
|
||||
serverTypeIdentificator: serverTypeIdentificator!,
|
||||
dnsApiToken: dnsApiToken!,
|
||||
serverDomain: serverDomain!,
|
||||
backblazeCredential: backblazeCredential!,
|
||||
serverDetails: serverDetails!,
|
||||
rootUser: box.get(BNames.rootUser),
|
||||
isServerStarted: box.get(BNames.isServerStarted, defaultValue: false),
|
||||
isServerResetedFirstTime:
|
||||
box.get(BNames.isServerResetedFirstTime, defaultValue: false),
|
||||
isServerResetedSecondTime:
|
||||
box.get(BNames.isServerResetedSecondTime, defaultValue: false),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (box.get(BNames.isRecoveringServer, defaultValue: false) &&
|
||||
serverDomain != null) {
|
||||
if (wizardData.isRecoveringServer && wizardData.serverDomain != null) {
|
||||
return ServerInstallationRecovery(
|
||||
providerApiToken: providerApiToken,
|
||||
dnsApiToken: dnsApiToken,
|
||||
serverDomain: serverDomain,
|
||||
serverTypeIdentificator: serverTypeIdentificator,
|
||||
backblazeCredential: backblazeCredential,
|
||||
serverDetails: serverDetails,
|
||||
rootUser: box.get(BNames.rootUser),
|
||||
providerApiToken: wizardData.serverProviderKey,
|
||||
dnsApiToken: wizardData.dnsProviderKey,
|
||||
serverDomain: wizardData.serverDomain,
|
||||
serverTypeIdentificator: wizardData.serverTypeIdentifier,
|
||||
backblazeCredential: wizardData.backupsCredential,
|
||||
serverDetails: wizardData.serverDetails,
|
||||
currentStep: _getCurrentRecoveryStep(
|
||||
providerApiToken,
|
||||
dnsApiToken,
|
||||
serverDomain,
|
||||
serverDetails,
|
||||
wizardData.serverProviderKey,
|
||||
wizardData.dnsProviderKey,
|
||||
wizardData.serverDomain!,
|
||||
wizardData.serverDetails,
|
||||
),
|
||||
recoveryCapabilities: await getRecoveryCapabilities(serverDomain),
|
||||
recoveryCapabilities:
|
||||
await getRecoveryCapabilities(wizardData.serverDomain!),
|
||||
);
|
||||
}
|
||||
|
||||
return ServerInstallationNotFinished(
|
||||
providerApiToken: providerApiToken,
|
||||
dnsApiToken: dnsApiToken,
|
||||
serverDomain: serverDomain,
|
||||
serverTypeIdentificator: serverTypeIdentificator,
|
||||
backblazeCredential: backblazeCredential,
|
||||
serverDetails: serverDetails,
|
||||
rootUser: box.get(BNames.rootUser),
|
||||
isServerStarted: box.get(BNames.isServerStarted, defaultValue: false),
|
||||
isServerResetedFirstTime:
|
||||
box.get(BNames.isServerResetedFirstTime, defaultValue: false),
|
||||
isServerResetedSecondTime:
|
||||
box.get(BNames.isServerResetedSecondTime, defaultValue: false),
|
||||
isLoading: box.get(BNames.isLoading, defaultValue: false),
|
||||
dnsMatches: null,
|
||||
customSshKey: null,
|
||||
);
|
||||
return ServerInstallationNotFinished.fromWizardData(wizardData);
|
||||
}
|
||||
|
||||
RecoveryStep _getCurrentRecoveryStep(
|
||||
|
@ -177,7 +148,9 @@ class ServerInstallationRepository {
|
|||
|
||||
void clearAppConfig() {
|
||||
box.clear();
|
||||
usersBox.clear();
|
||||
getIt<ResourcesModel>().clear();
|
||||
getIt<WizardDataModel>().clear();
|
||||
getIt<ApiConnectionRepository>().clear();
|
||||
}
|
||||
|
||||
Future<ServerHostingDetails> startServer(
|
||||
|
@ -209,6 +182,9 @@ class ServerInstallationRepository {
|
|||
if (!domainResult.success || domainResult.data.isEmpty) {
|
||||
return false;
|
||||
}
|
||||
await getIt<ResourcesModel>().removeDnsProviderToken(
|
||||
getIt<ResourcesModel>().dnsProviderCredentials.first,
|
||||
);
|
||||
|
||||
return domainResult.data.any(
|
||||
(final serverDomain) => serverDomain.domainName == domain,
|
||||
|
@ -216,7 +192,12 @@ class ServerInstallationRepository {
|
|||
}
|
||||
|
||||
Future<void> createDkimRecord(final ServerDomain domain) async {
|
||||
final ServerApi api = ServerApi();
|
||||
final ServerApi api = ServerApi(
|
||||
overrideDomain: domain.domainName,
|
||||
customToken:
|
||||
getIt<WizardDataModel>().serverInstallation!.serverDetails!.apiToken,
|
||||
isWithToken: true,
|
||||
);
|
||||
|
||||
late DnsRecord record;
|
||||
try {
|
||||
|
@ -233,14 +214,26 @@ class ServerInstallationRepository {
|
|||
}
|
||||
|
||||
Future<bool> isHttpServerWorking() async {
|
||||
final ServerApi api = ServerApi();
|
||||
final ServerApi api = ServerApi(
|
||||
overrideDomain:
|
||||
getIt<WizardDataModel>().serverInstallation!.serverDomain!.domainName,
|
||||
customToken:
|
||||
getIt<WizardDataModel>().serverInstallation!.serverDetails!.apiToken,
|
||||
isWithToken: true,
|
||||
);
|
||||
return api.isHttpServerWorking();
|
||||
}
|
||||
|
||||
Future<ServerHostingDetails> restart() async {
|
||||
final server = getIt<ApiConfigModel>().serverDetails!;
|
||||
final server = getIt<WizardDataModel>().serverInstallation!.serverDetails!;
|
||||
|
||||
final result = await ServerApi().reboot();
|
||||
final result = await ServerApi(
|
||||
overrideDomain:
|
||||
getIt<WizardDataModel>().serverInstallation!.serverDomain!.domainName,
|
||||
customToken:
|
||||
getIt<WizardDataModel>().serverInstallation!.serverDetails!.apiToken,
|
||||
isWithToken: true,
|
||||
).reboot();
|
||||
|
||||
if (result.success && result.data != null) {
|
||||
server.copyWith(startTime: result.data);
|
||||
|
@ -252,7 +245,7 @@ class ServerInstallationRepository {
|
|||
}
|
||||
|
||||
Future<ServerHostingDetails> powerOn() async {
|
||||
final server = getIt<ApiConfigModel>().serverDetails!;
|
||||
final server = getIt<ResourcesModel>().serverDetails!;
|
||||
return startServer(server);
|
||||
}
|
||||
|
||||
|
@ -436,174 +429,119 @@ class ServerInstallationRepository {
|
|||
);
|
||||
}
|
||||
|
||||
Future<User> getMainUser() async {
|
||||
final ServerApi serverApi = ServerApi();
|
||||
const User fallbackUser = User(
|
||||
isFoundOnServer: false,
|
||||
type: UserType.primary,
|
||||
note: "Couldn't find main user on server, API is outdated",
|
||||
login: 'UNKNOWN',
|
||||
sshKeys: [],
|
||||
);
|
||||
|
||||
final String? serverApiVersion = await serverApi.getApiVersion();
|
||||
final users = await serverApi.getAllUsers();
|
||||
if (serverApiVersion == null || users.isEmpty) {
|
||||
return fallbackUser;
|
||||
}
|
||||
try {
|
||||
final Version parsedVersion = Version.parse(serverApiVersion);
|
||||
if (!VersionConstraint.parse('>=1.2.5').allows(parsedVersion)) {
|
||||
return fallbackUser;
|
||||
}
|
||||
return users.firstWhere(
|
||||
(final User user) => user.type == UserType.primary,
|
||||
);
|
||||
} on FormatException {
|
||||
return fallbackUser;
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<ServerBasicInfo>> getServersOnProviderAccount() async =>
|
||||
(await ProvidersController.currentServerProvider!.getServers()).data;
|
||||
|
||||
Future<void> saveServerDetails(
|
||||
final ServerHostingDetails serverDetails,
|
||||
) async {
|
||||
await getIt<ApiConfigModel>().setServerDetails(serverDetails);
|
||||
await getIt<WizardDataModel>().setServerDetails(serverDetails);
|
||||
}
|
||||
|
||||
Future<void> deleteServerDetails() async {
|
||||
await box.delete(BNames.serverDetails);
|
||||
await getIt<ApiConfigModel>().init();
|
||||
await getIt<WizardDataModel>().deleteServerDetails();
|
||||
}
|
||||
|
||||
Future<void> saveServerProviderType(final ServerProviderType type) async {
|
||||
await getIt<ApiConfigModel>().storeServerProviderType(type);
|
||||
await getIt<WizardDataModel>().setServerProviderType(type);
|
||||
}
|
||||
|
||||
Future<void> saveDnsProviderType(final DnsProviderType type) async {
|
||||
await getIt<ApiConfigModel>().setDnsProviderType(type);
|
||||
await getIt<WizardDataModel>().setDnsProviderType(type);
|
||||
}
|
||||
|
||||
Future<void> saveServerProviderKey(final String key) async {
|
||||
await getIt<ApiConfigModel>().setServerProviderKey(key);
|
||||
await getIt<WizardDataModel>().setServerProviderKey(key);
|
||||
await getIt<ResourcesModel>().addServerProviderToken(
|
||||
ServerProviderCredential(
|
||||
tokenId: null,
|
||||
token: key,
|
||||
provider:
|
||||
getIt<WizardDataModel>().serverInstallation!.serverProviderType!,
|
||||
associatedServerIds: [],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> saveServerType(final ServerType serverType) async {
|
||||
await getIt<ApiConfigModel>().setServerTypeIdentifier(
|
||||
await getIt<WizardDataModel>().setServerTypeIdentifier(
|
||||
serverType.identifier,
|
||||
);
|
||||
await getIt<ApiConfigModel>().setServerLocation(
|
||||
await getIt<WizardDataModel>().setServerLocation(
|
||||
serverType.location.identifier,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteServerProviderKey() async {
|
||||
await box.delete(BNames.hetznerKey);
|
||||
await getIt<ApiConfigModel>().init();
|
||||
}
|
||||
|
||||
Future<void> saveBackblazeKey(
|
||||
final BackupsCredential backblazeCredential,
|
||||
Future<void> saveBackupsCredential(
|
||||
final BackupsCredential backupsCredential,
|
||||
) async {
|
||||
await getIt<ApiConfigModel>().setBackblazeCredential(backblazeCredential);
|
||||
}
|
||||
|
||||
Future<void> deleteBackblazeKey() async {
|
||||
await box.delete(BNames.backblazeCredential);
|
||||
await getIt<ApiConfigModel>().init();
|
||||
await getIt<WizardDataModel>().setBackupsCredential(backupsCredential);
|
||||
}
|
||||
|
||||
Future<void> setDnsApiToken(final String key) async {
|
||||
await getIt<ApiConfigModel>().setDnsProviderKey(key);
|
||||
}
|
||||
|
||||
Future<void> deleteDnsProviderKey() async {
|
||||
await box.delete(BNames.cloudFlareKey);
|
||||
await getIt<ApiConfigModel>().init();
|
||||
await getIt<WizardDataModel>().setDnsProviderKey(key);
|
||||
await getIt<ResourcesModel>().addDnsProviderToken(
|
||||
DnsProviderCredential(
|
||||
tokenId: null,
|
||||
token: key,
|
||||
provider: getIt<WizardDataModel>().serverInstallation!.dnsProviderType!,
|
||||
associatedDomainNames: [],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> saveDomain(final ServerDomain serverDomain) async {
|
||||
await getIt<ApiConfigModel>().setServerDomain(serverDomain);
|
||||
await getIt<WizardDataModel>().setServerDomain(serverDomain);
|
||||
}
|
||||
|
||||
Future<void> deleteDomain() async {
|
||||
await box.delete(BNames.serverDomain);
|
||||
await getIt<ApiConfigModel>().init();
|
||||
await getIt<WizardDataModel>().deleteServerDomain();
|
||||
}
|
||||
|
||||
Future<void> saveIsServerStarted(final bool value) async {
|
||||
await box.put(BNames.isServerStarted, value);
|
||||
await getIt<WizardDataModel>().setIsServerStarted(value);
|
||||
}
|
||||
|
||||
Future<void> saveIsServerResetedFirstTime(final bool value) async {
|
||||
await box.put(BNames.isServerResetedFirstTime, value);
|
||||
Future<void> saveIsServerRebootedFirstTime(final bool value) async {
|
||||
await getIt<WizardDataModel>().setIsServerRebootedFirstTime(value);
|
||||
}
|
||||
|
||||
Future<void> saveIsServerResetedSecondTime(final bool value) async {
|
||||
await box.put(BNames.isServerResetedSecondTime, value);
|
||||
Future<void> saveIsServerRebootedSecondTime(final bool value) async {
|
||||
await getIt<WizardDataModel>().setIsServerRebootedSecondTime(value);
|
||||
}
|
||||
|
||||
Future<void> saveRootUser(final User rootUser) async {
|
||||
await box.put(BNames.rootUser, rootUser);
|
||||
await getIt<WizardDataModel>().setRootUser(rootUser);
|
||||
}
|
||||
|
||||
Future<void> saveIsRecoveringServer(final bool value) async {
|
||||
await box.put(BNames.isRecoveringServer, value);
|
||||
await getIt<WizardDataModel>().setIsRecoveringServer(value);
|
||||
}
|
||||
|
||||
Future<void> saveHasFinalChecked(final bool value) async {
|
||||
await box.put(BNames.hasFinalChecked, value);
|
||||
}
|
||||
|
||||
Future<bool> deleteServer(final ServerDomain serverDomain) async {
|
||||
final ServerApi api = ServerApi();
|
||||
final dnsRecords = await api.getDnsRecords();
|
||||
final GenericResult<void> removalResult =
|
||||
await ProvidersController.currentDnsProvider!.removeDomainRecords(
|
||||
domain: serverDomain,
|
||||
records: dnsRecords,
|
||||
// We are finished here. Time to save the state and finish the wizard
|
||||
// TODO: A lot of null checks are skipped here. Implication that every value exists might become false in the future.
|
||||
// TODO: We would actually want to handle token creation elsewhere.
|
||||
await getIt<WizardDataModel>().moveServerTypeToServerDetails();
|
||||
final ServerInstallationWizardData wizardData =
|
||||
getIt<WizardDataModel>().serverInstallation!;
|
||||
await getIt<ResourcesModel>().addServer(
|
||||
Server(
|
||||
hostingDetails: wizardData.serverDetails!,
|
||||
domain: wizardData.serverDomain!,
|
||||
),
|
||||
);
|
||||
|
||||
if (!removalResult.success) {
|
||||
getIt<NavigationService>().showSnackBar(
|
||||
'modals.dns_removal_error'.tr(),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
final deletionResult =
|
||||
await ProvidersController.currentServerProvider!.deleteServer(
|
||||
serverDomain.domainName,
|
||||
await getIt<ResourcesModel>().associateServerWithToken(
|
||||
wizardData.serverDetails!.id,
|
||||
wizardData.serverProviderKey!,
|
||||
);
|
||||
|
||||
if (!deletionResult.success) {
|
||||
getIt<NavigationService>().showSnackBar(
|
||||
'modals.server_validators_error'.tr(),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
await box.put(BNames.hasFinalChecked, false);
|
||||
await box.put(BNames.isServerStarted, false);
|
||||
await box.put(BNames.isServerResetedFirstTime, false);
|
||||
await box.put(BNames.isServerResetedSecondTime, false);
|
||||
await box.put(BNames.isLoading, false);
|
||||
await box.put(BNames.serverDetails, null);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<void> deleteServerRelatedRecords() async {
|
||||
await box.deleteAll([
|
||||
BNames.serverDetails,
|
||||
BNames.isServerStarted,
|
||||
BNames.isServerResetedFirstTime,
|
||||
BNames.isServerResetedSecondTime,
|
||||
BNames.hasFinalChecked,
|
||||
BNames.isLoading,
|
||||
]);
|
||||
await getIt<ApiConfigModel>().init();
|
||||
await getIt<ResourcesModel>().associateDomainWithToken(
|
||||
wizardData.serverDomain!.domainName,
|
||||
wizardData.dnsProviderKey!,
|
||||
);
|
||||
await getIt<ResourcesModel>().addBackupsCredential(
|
||||
wizardData.backupsCredential!,
|
||||
);
|
||||
await getIt<WizardDataModel>().clearServerInstallation();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ abstract class ServerInstallationState extends Equatable {
|
|||
ServerSetupProgress get progress => ServerSetupProgress
|
||||
.values[_fulfillmentList.where((final el) => el!).length];
|
||||
|
||||
int get porgressBar {
|
||||
int get progressBar {
|
||||
if (progress.index < 6) {
|
||||
return progress.index;
|
||||
} else if (progress.index < 10) {
|
||||
|
@ -119,7 +119,7 @@ class TimerState extends ServerInstallationNotFinished {
|
|||
enum ServerSetupProgress {
|
||||
nothingYet,
|
||||
serverProviderFilled,
|
||||
servertTypeFilled,
|
||||
serverTypeFilled,
|
||||
dnsProviderFilled,
|
||||
backblazeFilled,
|
||||
domainFilled,
|
||||
|
@ -147,6 +147,26 @@ class ServerInstallationNotFinished extends ServerInstallationState {
|
|||
super.serverDetails,
|
||||
super.installationDialoguePopUp,
|
||||
});
|
||||
|
||||
ServerInstallationNotFinished.fromWizardData(
|
||||
final ServerInstallationWizardData data,
|
||||
) : this(
|
||||
providerApiToken: data.serverProviderKey,
|
||||
dnsApiToken: data.dnsProviderKey,
|
||||
serverDomain: data.serverDomain,
|
||||
serverTypeIdentificator: data.serverTypeIdentifier,
|
||||
backblazeCredential: data.backupsCredential,
|
||||
serverDetails: data.serverDetails,
|
||||
rootUser: data.rootUser,
|
||||
isServerStarted: data.isServerStarted,
|
||||
isServerResetedFirstTime: data.isServerResetedFirstTime,
|
||||
isServerResetedSecondTime: data.isServerResetedSecondTime,
|
||||
isLoading: data.isLoading,
|
||||
dnsMatches: null,
|
||||
customSshKey: null,
|
||||
installationDialoguePopUp: null,
|
||||
);
|
||||
|
||||
final bool isLoading;
|
||||
final Map<String, DnsRecordStatus>? dnsMatches;
|
||||
final String? customSshKey;
|
||||
|
@ -211,12 +231,7 @@ class ServerInstallationNotFinished extends ServerInstallationState {
|
|||
dnsApiToken: dnsApiToken!,
|
||||
backblazeCredential: backblazeCredential!,
|
||||
serverDomain: serverDomain!,
|
||||
rootUser: rootUser!,
|
||||
serverDetails: serverDetails!,
|
||||
isServerStarted: isServerStarted,
|
||||
isServerResetedFirstTime: isServerResetedFirstTime,
|
||||
isServerResetedSecondTime: isServerResetedSecondTime,
|
||||
installationDialoguePopUp: installationDialoguePopUp,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -247,13 +262,14 @@ class ServerInstallationFinished extends ServerInstallationState {
|
|||
required String super.dnsApiToken,
|
||||
required BackupsCredential super.backblazeCredential,
|
||||
required ServerDomain super.serverDomain,
|
||||
required User super.rootUser,
|
||||
required ServerHostingDetails super.serverDetails,
|
||||
required super.isServerStarted,
|
||||
required super.isServerResetedFirstTime,
|
||||
required super.isServerResetedSecondTime,
|
||||
required super.installationDialoguePopUp,
|
||||
});
|
||||
}) : super(
|
||||
rootUser: null,
|
||||
isServerStarted: true,
|
||||
isServerResetedFirstTime: true,
|
||||
isServerResetedSecondTime: true,
|
||||
installationDialoguePopUp: null,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
|
@ -302,9 +318,9 @@ class ServerInstallationRecovery extends ServerInstallationState {
|
|||
super.dnsApiToken,
|
||||
super.backblazeCredential,
|
||||
super.serverDomain,
|
||||
super.rootUser,
|
||||
super.serverDetails,
|
||||
}) : super(
|
||||
rootUser: null,
|
||||
isServerStarted: true,
|
||||
isServerResetedFirstTime: true,
|
||||
isServerResetedSecondTime: true,
|
||||
|
@ -334,7 +350,6 @@ class ServerInstallationRecovery extends ServerInstallationState {
|
|||
final String? dnsApiToken,
|
||||
final BackupsCredential? backblazeCredential,
|
||||
final ServerDomain? serverDomain,
|
||||
final User? rootUser,
|
||||
final ServerHostingDetails? serverDetails,
|
||||
final RecoveryStep? currentStep,
|
||||
final ServerRecoveryCapabilities? recoveryCapabilities,
|
||||
|
@ -346,7 +361,6 @@ class ServerInstallationRecovery extends ServerInstallationState {
|
|||
dnsApiToken: dnsApiToken ?? this.dnsApiToken,
|
||||
backblazeCredential: backblazeCredential ?? this.backblazeCredential,
|
||||
serverDomain: serverDomain ?? this.serverDomain,
|
||||
rootUser: rootUser ?? this.rootUser,
|
||||
serverDetails: serverDetails ?? this.serverDetails,
|
||||
currentStep: currentStep ?? this.currentStep,
|
||||
recoveryCapabilities: recoveryCapabilities ?? this.recoveryCapabilities,
|
||||
|
@ -358,11 +372,6 @@ class ServerInstallationRecovery extends ServerInstallationState {
|
|||
dnsApiToken: dnsApiToken!,
|
||||
backblazeCredential: backblazeCredential!,
|
||||
serverDomain: serverDomain!,
|
||||
rootUser: rootUser!,
|
||||
serverDetails: serverDetails!,
|
||||
isServerStarted: true,
|
||||
isServerResetedFirstTime: true,
|
||||
isServerResetedSecondTime: true,
|
||||
installationDialoguePopUp: null,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,115 +1,18 @@
|
|||
import 'package:hive/hive.dart';
|
||||
import 'package:selfprivacy/config/hive_config.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backblaze_bucket.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backups_credential.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
|
||||
class ApiConfigModel {
|
||||
final Box _box = Hive.box(BNames.serverInstallationBox);
|
||||
|
||||
ServerHostingDetails? get serverDetails => _serverDetails;
|
||||
String? get serverProviderKey => _serverProviderKey;
|
||||
String? get serverLocation => _serverLocation;
|
||||
String? get serverType => _serverType;
|
||||
String? get dnsProviderKey => _dnsProviderKey;
|
||||
ServerProviderType? get serverProvider => _serverProvider;
|
||||
DnsProviderType? get dnsProvider => _dnsProvider;
|
||||
|
||||
BackupsCredential? get backblazeCredential => _backblazeCredential;
|
||||
ServerDomain? get serverDomain => _serverDomain;
|
||||
BackblazeBucket? get backblazeBucket => _backblazeBucket;
|
||||
|
||||
static const localeCodeFallback = 'en';
|
||||
String? _localeCode;
|
||||
|
||||
String get localeCode => _localeCode ?? localeCodeFallback;
|
||||
Future<void> setLocaleCode(final String value) async => _localeCode = value;
|
||||
Future<void> resetLocaleCode() async => _localeCode = null;
|
||||
|
||||
String? _serverProviderKey;
|
||||
String? _serverLocation;
|
||||
String? _dnsProviderKey;
|
||||
String? _serverType;
|
||||
ServerProviderType? _serverProvider;
|
||||
DnsProviderType? _dnsProvider;
|
||||
ServerHostingDetails? _serverDetails;
|
||||
BackupsCredential? _backblazeCredential;
|
||||
ServerDomain? _serverDomain;
|
||||
BackblazeBucket? _backblazeBucket;
|
||||
|
||||
Future<void> storeServerProviderType(final ServerProviderType value) async {
|
||||
await _box.put(BNames.serverProvider, value);
|
||||
_serverProvider = value;
|
||||
}
|
||||
|
||||
Future<void> setDnsProviderType(final DnsProviderType value) async {
|
||||
await _box.put(BNames.dnsProvider, value);
|
||||
_dnsProvider = value;
|
||||
}
|
||||
|
||||
Future<void> setServerProviderKey(final String value) async {
|
||||
await _box.put(BNames.hetznerKey, value);
|
||||
_serverProviderKey = value;
|
||||
}
|
||||
|
||||
Future<void> setDnsProviderKey(final String value) async {
|
||||
await _box.put(BNames.cloudFlareKey, value);
|
||||
_dnsProviderKey = value;
|
||||
}
|
||||
|
||||
Future<void> setServerTypeIdentifier(final String typeIdentifier) async {
|
||||
await _box.put(BNames.serverTypeIdentifier, typeIdentifier);
|
||||
_serverType = typeIdentifier;
|
||||
}
|
||||
|
||||
Future<void> setServerLocation(final String serverLocation) async {
|
||||
await _box.put(BNames.serverLocation, serverLocation);
|
||||
_serverLocation = serverLocation;
|
||||
}
|
||||
|
||||
Future<void> setBackblazeCredential(final BackupsCredential value) async {
|
||||
await _box.put(BNames.backblazeCredential, value);
|
||||
_backblazeCredential = value;
|
||||
}
|
||||
|
||||
Future<void> setServerDomain(final ServerDomain value) async {
|
||||
await _box.put(BNames.serverDomain, value);
|
||||
_serverDomain = value;
|
||||
}
|
||||
|
||||
Future<void> setServerDetails(final ServerHostingDetails value) async {
|
||||
await _box.put(BNames.serverDetails, value);
|
||||
_serverDetails = value;
|
||||
}
|
||||
|
||||
Future<void> setBackblazeBucket(final BackblazeBucket value) async {
|
||||
await _box.put(BNames.backblazeBucket, value);
|
||||
_backblazeBucket = value;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_serverProviderKey = null;
|
||||
_dnsProvider = null;
|
||||
_serverLocation = null;
|
||||
_dnsProviderKey = null;
|
||||
_backblazeCredential = null;
|
||||
_serverDomain = null;
|
||||
_serverDetails = null;
|
||||
_backblazeBucket = null;
|
||||
_serverType = null;
|
||||
_serverProvider = null;
|
||||
}
|
||||
|
||||
Future<void> init() async {
|
||||
_serverProviderKey = _box.get(BNames.hetznerKey);
|
||||
_serverLocation = _box.get(BNames.serverLocation);
|
||||
_dnsProviderKey = _box.get(BNames.cloudFlareKey);
|
||||
_backblazeCredential = _box.get(BNames.backblazeCredential);
|
||||
_serverDomain = _box.get(BNames.serverDomain);
|
||||
_serverDetails = _box.get(BNames.serverDetails);
|
||||
_backblazeBucket = _box.get(BNames.backblazeBucket);
|
||||
_serverType = _box.get(BNames.serverTypeIdentifier);
|
||||
_serverProvider = _box.get(BNames.serverProvider);
|
||||
_dnsProvider = _box.get(BNames.dnsProvider);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ 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/graphql_maps/server_api/server_api.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart';
|
||||
import 'package:selfprivacy/logic/models/backup.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
|
@ -246,14 +247,12 @@ class ApiConnectionRepository {
|
|||
}
|
||||
|
||||
ServerHostingDetails? get serverDetails =>
|
||||
getIt<ApiConfigModel>().serverDetails;
|
||||
ServerDomain? get serverDomain => getIt<ApiConfigModel>().serverDomain;
|
||||
getIt<ResourcesModel>().serverDetails;
|
||||
ServerDomain? get serverDomain => getIt<ResourcesModel>().serverDomain;
|
||||
|
||||
void init() async {
|
||||
final serverDetails = getIt<ApiConfigModel>().serverDetails;
|
||||
final hasFinalChecked =
|
||||
box.get(BNames.hasFinalChecked, defaultValue: false);
|
||||
if (serverDetails == null || !hasFinalChecked) {
|
||||
final serverDetails = getIt<ResourcesModel>().serverDetails;
|
||||
if (serverDetails == null) {
|
||||
return;
|
||||
}
|
||||
connectionStatus = ConnectionStatus.reconnecting;
|
||||
|
@ -281,6 +280,12 @@ class ApiConnectionRepository {
|
|||
);
|
||||
}
|
||||
|
||||
void clear() async {
|
||||
connectionStatus = ConnectionStatus.nonexistent;
|
||||
_connectionStatusStream.add(connectionStatus);
|
||||
_timer?.cancel();
|
||||
}
|
||||
|
||||
Future<void> _refetchEverything(final Version version) async {
|
||||
await _apiData.serverJobs
|
||||
.refetchData(version, () => _dataStream.add(_apiData));
|
||||
|
@ -302,7 +307,7 @@ class ApiConnectionRepository {
|
|||
}
|
||||
|
||||
Future<void> reload(final Timer? timer) async {
|
||||
final serverDetails = getIt<ApiConfigModel>().serverDetails;
|
||||
final serverDetails = getIt<ResourcesModel>().serverDetails;
|
||||
if (serverDetails == null) {
|
||||
return;
|
||||
}
|
||||
|
|
342
lib/logic/get_it/resources_model.dart
Normal file
342
lib/logic/get_it/resources_model.dart
Normal file
|
@ -0,0 +1,342 @@
|
|||
import 'package:hive/hive.dart';
|
||||
import 'package:selfprivacy/config/hive_config.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backblaze_bucket.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backups_credential.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/dns_provider_credential.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server.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/server_provider_credential.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/wizards_data/server_installation_wizard_data.dart';
|
||||
|
||||
class ResourcesModel {
|
||||
final Box _box = Hive.box(BNames.resourcesBox);
|
||||
|
||||
List<ServerProviderCredential> get serverProviderCredentials =>
|
||||
_serverProviderTokens;
|
||||
List<DnsProviderCredential> get dnsProviderCredentials => _dnsProviderTokens;
|
||||
List<BackupsCredential> get backupsCredentials => _backupsCredentials;
|
||||
List<Server> get servers => _servers;
|
||||
BackblazeBucket? get backblazeBucket => _backblazeBucket;
|
||||
|
||||
List<ServerProviderCredential> _serverProviderTokens = [];
|
||||
List<DnsProviderCredential> _dnsProviderTokens = [];
|
||||
List<BackupsCredential> _backupsCredentials = [];
|
||||
List<Server> _servers = [];
|
||||
// TODO: As we will add support for other backup storages, we should
|
||||
// refactor this.
|
||||
BackblazeBucket? _backblazeBucket;
|
||||
|
||||
@Deprecated('Compatibility getter')
|
||||
ServerHostingDetails? get serverDetails =>
|
||||
_servers.firstOrNull?.hostingDetails;
|
||||
@Deprecated('Compatibility getter')
|
||||
String? get serverProviderKey => _serverProviderTokens.firstOrNull?.token;
|
||||
@Deprecated('Compatibility getter')
|
||||
String? get serverLocation =>
|
||||
_servers.firstOrNull?.hostingDetails.serverLocation;
|
||||
@Deprecated('Compatibility getter')
|
||||
String? get serverType => _servers.firstOrNull?.hostingDetails.serverType;
|
||||
@Deprecated('Compatibility getter')
|
||||
String? get dnsProviderKey => _dnsProviderTokens.firstOrNull?.token;
|
||||
@Deprecated('Compatibility getter')
|
||||
ServerProviderType? get serverProvider =>
|
||||
_serverProviderTokens.firstOrNull?.provider;
|
||||
@Deprecated('Compatibility getter')
|
||||
DnsProviderType? get dnsProvider => _dnsProviderTokens.firstOrNull?.provider;
|
||||
@Deprecated('Compatibility getter')
|
||||
BackupsCredential? get backblazeCredential => _backupsCredentials.firstOrNull;
|
||||
@Deprecated('Compatibility getter')
|
||||
ServerDomain? get serverDomain => _servers.firstOrNull?.domain;
|
||||
|
||||
Future<void> addServerProviderToken(
|
||||
final ServerProviderCredential token,
|
||||
) async {
|
||||
_serverProviderTokens.add(token);
|
||||
await _box.put(BNames.serverProviderTokens, _serverProviderTokens);
|
||||
}
|
||||
|
||||
Future<void> associateServerWithToken(
|
||||
final int serverId,
|
||||
final String token,
|
||||
) async {
|
||||
_serverProviderTokens
|
||||
.firstWhere(
|
||||
(final credential) => credential.token == token,
|
||||
)
|
||||
.associatedServerIds
|
||||
.add(serverId);
|
||||
await _box.put(BNames.serverProviderTokens, _serverProviderTokens);
|
||||
}
|
||||
|
||||
Future<void> removeServerProviderToken(
|
||||
final ServerProviderCredential token,
|
||||
) async {
|
||||
_serverProviderTokens.remove(token);
|
||||
await _box.put(BNames.serverProviderTokens, _serverProviderTokens);
|
||||
}
|
||||
|
||||
Future<void> addDnsProviderToken(final DnsProviderCredential token) async {
|
||||
// Check if this token already exists
|
||||
if (_dnsProviderTokens
|
||||
.any((final credential) => credential.token == token.token)) {
|
||||
throw Exception('Token already exists');
|
||||
}
|
||||
_dnsProviderTokens.add(token);
|
||||
await _box.put(BNames.dnsProviderTokens, _dnsProviderTokens);
|
||||
}
|
||||
|
||||
Future<void> associateDomainWithToken(
|
||||
final String domain,
|
||||
final String token,
|
||||
) async {
|
||||
_dnsProviderTokens
|
||||
.firstWhere(
|
||||
(final credential) => credential.token == token,
|
||||
)
|
||||
.associatedDomainNames
|
||||
.add(domain);
|
||||
await _box.put(BNames.dnsProviderTokens, _dnsProviderTokens);
|
||||
}
|
||||
|
||||
Future<void> removeDnsProviderToken(final DnsProviderCredential token) async {
|
||||
_dnsProviderTokens.remove(token);
|
||||
await _box.put(BNames.dnsProviderTokens, _dnsProviderTokens);
|
||||
}
|
||||
|
||||
Future<void> addBackupsCredential(final BackupsCredential credential) async {
|
||||
_backupsCredentials.add(credential);
|
||||
await _box.put(BNames.backupsProviderTokens, _backupsCredentials);
|
||||
}
|
||||
|
||||
Future<void> removeBackupsCredential(
|
||||
final BackupsCredential credential,
|
||||
) async {
|
||||
_backupsCredentials.remove(credential);
|
||||
await _box.put(BNames.backupsProviderTokens, _backupsCredentials);
|
||||
}
|
||||
|
||||
Future<void> addServer(final Server server) async {
|
||||
_servers.add(server);
|
||||
await _box.put(BNames.servers, _servers);
|
||||
}
|
||||
|
||||
Future<void> removeServer(final Server server) async {
|
||||
_servers.remove(server);
|
||||
await _box.put(BNames.servers, _servers);
|
||||
}
|
||||
|
||||
Future<void> setBackblazeBucket(final BackblazeBucket bucket) async {
|
||||
_backblazeBucket = bucket;
|
||||
await _box.put(BNames.backblazeBucket, _backblazeBucket);
|
||||
}
|
||||
|
||||
Future<void> removeBackblazeBucket() async {
|
||||
_backblazeBucket = null;
|
||||
await _box.delete(BNames.backblazeBucket);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_servers.clear();
|
||||
_serverProviderTokens.clear();
|
||||
_dnsProviderTokens.clear();
|
||||
_backupsCredentials.clear();
|
||||
_backblazeBucket = null;
|
||||
|
||||
_box.clear();
|
||||
_box.compact();
|
||||
}
|
||||
|
||||
void init() {
|
||||
_serverProviderTokens = _box
|
||||
.get(
|
||||
BNames.serverProviderTokens,
|
||||
defaultValue: <ServerProviderCredential>[],
|
||||
)
|
||||
.map<ServerProviderCredential>(
|
||||
(final e) => e as ServerProviderCredential,
|
||||
)
|
||||
.toList();
|
||||
_dnsProviderTokens = _box
|
||||
.get(
|
||||
BNames.dnsProviderTokens,
|
||||
defaultValue: <DnsProviderCredential>[],
|
||||
)
|
||||
.map<DnsProviderCredential>((final e) => e as DnsProviderCredential)
|
||||
.toList();
|
||||
_backupsCredentials = _box
|
||||
.get(
|
||||
BNames.backupsProviderTokens,
|
||||
defaultValue: <BackupsCredential>[],
|
||||
)
|
||||
.map<BackupsCredential>((final e) => e as BackupsCredential)
|
||||
.toList();
|
||||
_servers = _box
|
||||
.get(
|
||||
BNames.servers,
|
||||
defaultValue: <Server>[],
|
||||
)
|
||||
.map<Server>((final e) => e as Server)
|
||||
.toList();
|
||||
_backblazeBucket = _box.get(BNames.backblazeBucket);
|
||||
}
|
||||
}
|
||||
|
||||
class WizardDataModel {
|
||||
final Box _box = Hive.box(BNames.wizardDataBox);
|
||||
|
||||
ServerInstallationWizardData? get serverInstallation => _serverInstallation;
|
||||
|
||||
ServerInstallationWizardData? _serverInstallation;
|
||||
|
||||
Future<void> setServerProviderType(final ServerProviderType provider) async {
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(serverProviderType: provider);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> setServerProviderKey(final String key) async {
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(serverProviderKey: key);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> setDnsProviderType(final DnsProviderType provider) async {
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(dnsProviderType: provider);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> setDnsProviderKey(final String key) async {
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(dnsProviderKey: key);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> setServerTypeIdentifier(final String identifier) async {
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(serverTypeIdentifier: identifier);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> setServerLocation(final String location) async {
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(serverLocation: location);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> moveServerTypeToServerDetails() async {
|
||||
final details = _serverInstallation?.serverDetails;
|
||||
if (details != null) {
|
||||
if (_serverInstallation?.serverTypeIdentifier != null &&
|
||||
_serverInstallation?.serverLocation != null) {
|
||||
_serverInstallation = _serverInstallation?.copyWith(
|
||||
serverDetails: () => details.copyWith(
|
||||
serverType: _serverInstallation?.serverTypeIdentifier,
|
||||
serverLocation: _serverInstallation?.serverLocation,
|
||||
),
|
||||
);
|
||||
await _box.put(
|
||||
BNames.serverInstallationWizardData,
|
||||
_serverInstallation,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> setServerDetails(final ServerHostingDetails details) async {
|
||||
final detailsWithServerType = details.copyWith(
|
||||
serverLocation: _serverInstallation?.serverLocation,
|
||||
serverType: _serverInstallation?.serverTypeIdentifier,
|
||||
);
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(serverDetails: () => detailsWithServerType);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> deleteServerDetails() async {
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(serverDetails: () => null);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> setBackupsCredential(final BackupsCredential credential) async {
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(backupsCredential: credential);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> setServerDomain(final ServerDomain domain) async {
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(serverDomain: () => domain);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> deleteServerDomain() async {
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(serverDomain: () => null);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> setIsServerStarted(final bool isStarted) async {
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(isServerStarted: isStarted);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> setIsServerRebootedFirstTime(final bool isRebooted) async {
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(isServerResetedFirstTime: isRebooted);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> setIsServerRebootedSecondTime(final bool isRebooted) async {
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(isServerResetedSecondTime: isRebooted);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> setRootUser(final User user) async {
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(rootUser: user);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> setIsRecoveringServer(final bool isRecovering) async {
|
||||
_serverInstallation =
|
||||
(_serverInstallation ?? ServerInstallationWizardData.empty())
|
||||
.copyWith(isRecoveringServer: isRecovering);
|
||||
await _box.put(BNames.serverInstallationWizardData, _serverInstallation);
|
||||
}
|
||||
|
||||
Future<void> clearServerInstallation() async {
|
||||
_serverInstallation = null;
|
||||
await _box.delete(BNames.serverInstallationWizardData);
|
||||
}
|
||||
|
||||
Future<void> clear() async {
|
||||
await _box.clear();
|
||||
await _box.compact();
|
||||
}
|
||||
|
||||
void init() {
|
||||
_serverInstallation =
|
||||
_box.get(BNames.serverInstallationWizardData, defaultValue: null);
|
||||
}
|
||||
}
|
|
@ -3,13 +3,19 @@
|
|||
1. User
|
||||
2. ServerHostingDetails
|
||||
3. ServerDomain
|
||||
4. BackblazeCredential
|
||||
5. ServerVolume
|
||||
4. BackupsCredential
|
||||
5. ServerProviderVolume
|
||||
6. BackblazeBucket
|
||||
7. ServerProviderCredential
|
||||
8. DnsProviderCredential
|
||||
9. Server
|
||||
|
||||
## Wizards store
|
||||
60. ServerInstallationWizardData
|
||||
|
||||
## Enums
|
||||
|
||||
100. DnsProvider
|
||||
101. ServerProvider
|
||||
102. UserType
|
||||
103. BackupsProvider
|
||||
103. BackupsProviderType
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/schema.graphql.da
|
|||
|
||||
part 'backups_credential.g.dart';
|
||||
|
||||
// TODO: Make a constant type.
|
||||
@HiveType(typeId: 4)
|
||||
class BackupsCredential {
|
||||
BackupsCredential({
|
||||
|
|
27
lib/logic/models/hive/dns_provider_credential.dart
Normal file
27
lib/logic/models/hive/dns_provider_credential.dart
Normal file
|
@ -0,0 +1,27 @@
|
|||
import 'package:hive/hive.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
|
||||
part 'dns_provider_credential.g.dart';
|
||||
|
||||
// TODO: Make a constant type.
|
||||
@HiveType(typeId: 8)
|
||||
class DnsProviderCredential {
|
||||
DnsProviderCredential({
|
||||
required this.tokenId,
|
||||
required this.token,
|
||||
required this.provider,
|
||||
required this.associatedDomainNames,
|
||||
});
|
||||
|
||||
@HiveField(0)
|
||||
final String? tokenId;
|
||||
|
||||
@HiveField(1)
|
||||
final String token;
|
||||
|
||||
@HiveField(2)
|
||||
final DnsProviderType provider;
|
||||
|
||||
@HiveField(3)
|
||||
final List<String> associatedDomainNames;
|
||||
}
|
50
lib/logic/models/hive/dns_provider_credential.g.dart
Normal file
50
lib/logic/models/hive/dns_provider_credential.g.dart
Normal file
|
@ -0,0 +1,50 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'dns_provider_credential.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class DnsProviderCredentialAdapter extends TypeAdapter<DnsProviderCredential> {
|
||||
@override
|
||||
final int typeId = 8;
|
||||
|
||||
@override
|
||||
DnsProviderCredential read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return DnsProviderCredential(
|
||||
tokenId: fields[0] as String?,
|
||||
token: fields[1] as String,
|
||||
provider: fields[2] as DnsProviderType,
|
||||
associatedDomainNames: (fields[3] as List).cast<String>(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, DnsProviderCredential obj) {
|
||||
writer
|
||||
..writeByte(4)
|
||||
..writeByte(0)
|
||||
..write(obj.tokenId)
|
||||
..writeByte(1)
|
||||
..write(obj.token)
|
||||
..writeByte(2)
|
||||
..write(obj.provider)
|
||||
..writeByte(3)
|
||||
..write(obj.associatedDomainNames);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is DnsProviderCredentialAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
20
lib/logic/models/hive/server.dart
Normal file
20
lib/logic/models/hive/server.dart
Normal file
|
@ -0,0 +1,20 @@
|
|||
import 'package:hive/hive.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||
|
||||
part 'server.g.dart';
|
||||
|
||||
// TODO: Make a constant type.
|
||||
@HiveType(typeId: 9)
|
||||
class Server {
|
||||
Server({
|
||||
required this.hostingDetails,
|
||||
required this.domain,
|
||||
});
|
||||
|
||||
@HiveField(0)
|
||||
final ServerHostingDetails hostingDetails;
|
||||
|
||||
@HiveField(1)
|
||||
final ServerDomain domain;
|
||||
}
|
44
lib/logic/models/hive/server.g.dart
Normal file
44
lib/logic/models/hive/server.g.dart
Normal file
|
@ -0,0 +1,44 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'server.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class ServerAdapter extends TypeAdapter<Server> {
|
||||
@override
|
||||
final int typeId = 9;
|
||||
|
||||
@override
|
||||
Server read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return Server(
|
||||
hostingDetails: fields[0] as ServerHostingDetails,
|
||||
domain: fields[1] as ServerDomain,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, Server obj) {
|
||||
writer
|
||||
..writeByte(2)
|
||||
..writeByte(0)
|
||||
..write(obj.hostingDetails)
|
||||
..writeByte(1)
|
||||
..write(obj.domain);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is ServerAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
|
@ -12,6 +12,8 @@ class ServerHostingDetails {
|
|||
required this.volume,
|
||||
required this.apiToken,
|
||||
required this.provider,
|
||||
this.serverLocation,
|
||||
this.serverType,
|
||||
this.startTime,
|
||||
});
|
||||
|
||||
|
@ -21,12 +23,13 @@ class ServerHostingDetails {
|
|||
@HiveField(1)
|
||||
final int id;
|
||||
|
||||
@HiveField(3)
|
||||
final DateTime? createTime;
|
||||
|
||||
// TODO: Check if it is still needed
|
||||
@HiveField(2)
|
||||
final DateTime? startTime;
|
||||
|
||||
@HiveField(3)
|
||||
final DateTime? createTime;
|
||||
|
||||
// TODO: Check if it is still needed
|
||||
@HiveField(4)
|
||||
final ServerProviderVolume volume;
|
||||
|
@ -37,9 +40,21 @@ class ServerHostingDetails {
|
|||
@HiveField(6, defaultValue: ServerProviderType.hetzner)
|
||||
final ServerProviderType provider;
|
||||
|
||||
ServerHostingDetails copyWith({final DateTime? startTime}) =>
|
||||
@HiveField(7)
|
||||
final String? serverLocation;
|
||||
|
||||
@HiveField(8)
|
||||
final String? serverType;
|
||||
|
||||
ServerHostingDetails copyWith({
|
||||
final DateTime? startTime,
|
||||
final String? serverLocation,
|
||||
final String? serverType,
|
||||
}) =>
|
||||
ServerHostingDetails(
|
||||
startTime: startTime ?? this.startTime,
|
||||
serverLocation: serverLocation ?? this.serverLocation,
|
||||
serverType: serverType ?? this.serverType,
|
||||
createTime: createTime,
|
||||
id: id,
|
||||
ip4: ip4,
|
||||
|
@ -103,3 +118,7 @@ enum ServerProviderType {
|
|||
unknown => 'Unknown',
|
||||
};
|
||||
}
|
||||
|
||||
extension ServerProviderTypeIsSpecified on ServerProviderType? {
|
||||
bool get isSpecified => this != null && this != ServerProviderType.unknown;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ class ServerHostingDetailsAdapter extends TypeAdapter<ServerHostingDetails> {
|
|||
provider: fields[6] == null
|
||||
? ServerProviderType.hetzner
|
||||
: fields[6] as ServerProviderType,
|
||||
serverLocation: fields[7] as String?,
|
||||
serverType: fields[8] as String?,
|
||||
startTime: fields[2] as DateTime?,
|
||||
);
|
||||
}
|
||||
|
@ -32,21 +34,25 @@ class ServerHostingDetailsAdapter extends TypeAdapter<ServerHostingDetails> {
|
|||
@override
|
||||
void write(BinaryWriter writer, ServerHostingDetails obj) {
|
||||
writer
|
||||
..writeByte(7)
|
||||
..writeByte(9)
|
||||
..writeByte(0)
|
||||
..write(obj.ip4)
|
||||
..writeByte(1)
|
||||
..write(obj.id)
|
||||
..writeByte(3)
|
||||
..write(obj.createTime)
|
||||
..writeByte(2)
|
||||
..write(obj.startTime)
|
||||
..writeByte(3)
|
||||
..write(obj.createTime)
|
||||
..writeByte(4)
|
||||
..write(obj.volume)
|
||||
..writeByte(5)
|
||||
..write(obj.apiToken)
|
||||
..writeByte(6)
|
||||
..write(obj.provider);
|
||||
..write(obj.provider)
|
||||
..writeByte(7)
|
||||
..write(obj.serverLocation)
|
||||
..writeByte(8)
|
||||
..write(obj.serverType);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -57,3 +57,7 @@ enum DnsProviderType {
|
|||
unknown => 'Unknown',
|
||||
};
|
||||
}
|
||||
|
||||
extension DnsProviderTypeIsSpecified on DnsProviderType? {
|
||||
bool get isSpecified => this != null && this != DnsProviderType.unknown;
|
||||
}
|
||||
|
|
27
lib/logic/models/hive/server_provider_credential.dart
Normal file
27
lib/logic/models/hive/server_provider_credential.dart
Normal file
|
@ -0,0 +1,27 @@
|
|||
import 'package:hive/hive.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
|
||||
part 'server_provider_credential.g.dart';
|
||||
|
||||
// TODO: Make a constant type.
|
||||
@HiveType(typeId: 7)
|
||||
class ServerProviderCredential {
|
||||
ServerProviderCredential({
|
||||
required this.tokenId,
|
||||
required this.token,
|
||||
required this.provider,
|
||||
required this.associatedServerIds,
|
||||
});
|
||||
|
||||
@HiveField(0)
|
||||
final String? tokenId;
|
||||
|
||||
@HiveField(1)
|
||||
final String token;
|
||||
|
||||
@HiveField(2)
|
||||
final ServerProviderType provider;
|
||||
|
||||
@HiveField(3)
|
||||
final List<int> associatedServerIds;
|
||||
}
|
51
lib/logic/models/hive/server_provider_credential.g.dart
Normal file
51
lib/logic/models/hive/server_provider_credential.g.dart
Normal file
|
@ -0,0 +1,51 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'server_provider_credential.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class ServerProviderCredentialAdapter
|
||||
extends TypeAdapter<ServerProviderCredential> {
|
||||
@override
|
||||
final int typeId = 7;
|
||||
|
||||
@override
|
||||
ServerProviderCredential read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return ServerProviderCredential(
|
||||
tokenId: fields[0] as String?,
|
||||
token: fields[1] as String,
|
||||
provider: fields[2] as ServerProviderType,
|
||||
associatedServerIds: (fields[3] as List).cast<int>(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, ServerProviderCredential obj) {
|
||||
writer
|
||||
..writeByte(4)
|
||||
..writeByte(0)
|
||||
..write(obj.tokenId)
|
||||
..writeByte(1)
|
||||
..write(obj.token)
|
||||
..writeByte(2)
|
||||
..write(obj.provider)
|
||||
..writeByte(3)
|
||||
..write(obj.associatedServerIds);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is ServerProviderCredentialAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/backups_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';
|
||||
|
||||
part 'server_installation_wizard_data.g.dart';
|
||||
|
||||
@HiveType(typeId: 60)
|
||||
class ServerInstallationWizardData {
|
||||
const ServerInstallationWizardData({
|
||||
required this.hasFinalChecked,
|
||||
required this.isServerStarted,
|
||||
required this.isServerResetedFirstTime,
|
||||
required this.isServerResetedSecondTime,
|
||||
required this.isLoading,
|
||||
required this.isRecoveringServer,
|
||||
required this.rootUser,
|
||||
required this.serverProviderType,
|
||||
required this.serverProviderKey,
|
||||
required this.dnsProviderType,
|
||||
required this.dnsProviderKey,
|
||||
required this.backupsCredential,
|
||||
required this.serverTypeIdentifier,
|
||||
required this.serverLocation,
|
||||
required this.serverDetails,
|
||||
required this.serverDomain,
|
||||
});
|
||||
|
||||
ServerInstallationWizardData.empty()
|
||||
: this(
|
||||
hasFinalChecked: false,
|
||||
isServerStarted: false,
|
||||
isServerResetedFirstTime: false,
|
||||
isServerResetedSecondTime: false,
|
||||
isLoading: false,
|
||||
isRecoveringServer: false,
|
||||
rootUser: null,
|
||||
serverProviderType: null,
|
||||
serverProviderKey: null,
|
||||
dnsProviderType: null,
|
||||
dnsProviderKey: null,
|
||||
backupsCredential: null,
|
||||
serverTypeIdentifier: null,
|
||||
serverLocation: null,
|
||||
serverDetails: null,
|
||||
serverDomain: null,
|
||||
);
|
||||
|
||||
// Bool flags used by installer
|
||||
@HiveField(0)
|
||||
final bool hasFinalChecked;
|
||||
@HiveField(1)
|
||||
final bool isServerStarted;
|
||||
@HiveField(2)
|
||||
final bool isServerResetedFirstTime;
|
||||
@HiveField(3)
|
||||
final bool isServerResetedSecondTime;
|
||||
@HiveField(4)
|
||||
final bool isLoading;
|
||||
|
||||
@HiveField(5)
|
||||
final bool isRecoveringServer;
|
||||
|
||||
@HiveField(6)
|
||||
final User? rootUser;
|
||||
|
||||
@HiveField(7)
|
||||
final ServerProviderType? serverProviderType;
|
||||
@HiveField(8)
|
||||
final String? serverProviderKey;
|
||||
|
||||
@HiveField(9)
|
||||
final DnsProviderType? dnsProviderType;
|
||||
@HiveField(10)
|
||||
final String? dnsProviderKey;
|
||||
|
||||
@HiveField(11)
|
||||
final BackupsCredential? backupsCredential;
|
||||
|
||||
@HiveField(12)
|
||||
final String? serverTypeIdentifier;
|
||||
@HiveField(13)
|
||||
final String? serverLocation;
|
||||
@HiveField(14)
|
||||
final ServerHostingDetails? serverDetails;
|
||||
@HiveField(15)
|
||||
final ServerDomain? serverDomain;
|
||||
|
||||
ServerInstallationWizardData copyWith({
|
||||
final bool? hasFinalChecked,
|
||||
final bool? isServerStarted,
|
||||
final bool? isServerResetedFirstTime,
|
||||
final bool? isServerResetedSecondTime,
|
||||
final bool? isLoading,
|
||||
final bool? isRecoveringServer,
|
||||
final User? rootUser,
|
||||
final ServerProviderType? serverProviderType,
|
||||
final String? serverProviderKey,
|
||||
final DnsProviderType? dnsProviderType,
|
||||
final String? dnsProviderKey,
|
||||
final BackupsCredential? backupsCredential,
|
||||
final String? serverTypeIdentifier,
|
||||
final String? serverLocation,
|
||||
final ValueGetter<ServerHostingDetails?>? serverDetails,
|
||||
final ValueGetter<ServerDomain?>? serverDomain,
|
||||
}) =>
|
||||
ServerInstallationWizardData(
|
||||
hasFinalChecked: hasFinalChecked ?? this.hasFinalChecked,
|
||||
isServerStarted: isServerStarted ?? this.isServerStarted,
|
||||
isServerResetedFirstTime:
|
||||
isServerResetedFirstTime ?? this.isServerResetedFirstTime,
|
||||
isServerResetedSecondTime:
|
||||
isServerResetedSecondTime ?? this.isServerResetedSecondTime,
|
||||
isLoading: isLoading ?? this.isLoading,
|
||||
isRecoveringServer: isRecoveringServer ?? this.isRecoveringServer,
|
||||
rootUser: rootUser ?? this.rootUser,
|
||||
serverProviderType: serverProviderType ?? this.serverProviderType,
|
||||
serverProviderKey: serverProviderKey ?? this.serverProviderKey,
|
||||
dnsProviderType: dnsProviderType ?? this.dnsProviderType,
|
||||
dnsProviderKey: dnsProviderKey ?? this.dnsProviderKey,
|
||||
backupsCredential: backupsCredential ?? this.backupsCredential,
|
||||
serverTypeIdentifier: serverTypeIdentifier ?? this.serverTypeIdentifier,
|
||||
serverLocation: serverLocation ?? this.serverLocation,
|
||||
serverDetails:
|
||||
serverDetails != null ? serverDetails() : this.serverDetails,
|
||||
serverDomain: serverDomain != null ? serverDomain() : this.serverDomain,
|
||||
);
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'server_installation_wizard_data.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class ServerInstallationWizardDataAdapter
|
||||
extends TypeAdapter<ServerInstallationWizardData> {
|
||||
@override
|
||||
final int typeId = 60;
|
||||
|
||||
@override
|
||||
ServerInstallationWizardData read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return ServerInstallationWizardData(
|
||||
hasFinalChecked: fields[0] as bool,
|
||||
isServerStarted: fields[1] as bool,
|
||||
isServerResetedFirstTime: fields[2] as bool,
|
||||
isServerResetedSecondTime: fields[3] as bool,
|
||||
isLoading: fields[4] as bool,
|
||||
isRecoveringServer: fields[5] as bool,
|
||||
rootUser: fields[6] as User?,
|
||||
serverProviderType: fields[7] as ServerProviderType?,
|
||||
serverProviderKey: fields[8] as String?,
|
||||
dnsProviderType: fields[9] as DnsProviderType?,
|
||||
dnsProviderKey: fields[10] as String?,
|
||||
backupsCredential: fields[11] as BackupsCredential?,
|
||||
serverTypeIdentifier: fields[12] as String?,
|
||||
serverLocation: fields[13] as String?,
|
||||
serverDetails: fields[14] as ServerHostingDetails?,
|
||||
serverDomain: fields[15] as ServerDomain?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, ServerInstallationWizardData obj) {
|
||||
writer
|
||||
..writeByte(16)
|
||||
..writeByte(0)
|
||||
..write(obj.hasFinalChecked)
|
||||
..writeByte(1)
|
||||
..write(obj.isServerStarted)
|
||||
..writeByte(2)
|
||||
..write(obj.isServerResetedFirstTime)
|
||||
..writeByte(3)
|
||||
..write(obj.isServerResetedSecondTime)
|
||||
..writeByte(4)
|
||||
..write(obj.isLoading)
|
||||
..writeByte(5)
|
||||
..write(obj.isRecoveringServer)
|
||||
..writeByte(6)
|
||||
..write(obj.rootUser)
|
||||
..writeByte(7)
|
||||
..write(obj.serverProviderType)
|
||||
..writeByte(8)
|
||||
..write(obj.serverProviderKey)
|
||||
..writeByte(9)
|
||||
..write(obj.dnsProviderType)
|
||||
..writeByte(10)
|
||||
..write(obj.dnsProviderKey)
|
||||
..writeByte(11)
|
||||
..write(obj.backupsCredential)
|
||||
..writeByte(12)
|
||||
..write(obj.serverTypeIdentifier)
|
||||
..writeByte(13)
|
||||
..write(obj.serverLocation)
|
||||
..writeByte(14)
|
||||
..write(obj.serverDetails)
|
||||
..writeByte(15)
|
||||
..write(obj.serverDomain);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is ServerInstallationWizardDataAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
|
@ -11,7 +11,7 @@ class Price {
|
|||
enum CurrencyType {
|
||||
eur,
|
||||
usd,
|
||||
unkown,
|
||||
unknown,
|
||||
}
|
||||
|
||||
class Currency {
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:selfprivacy/config/get_it_config.dart';
|
|||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/desired_dns_record.dart';
|
||||
import 'package:selfprivacy/logic/cubit/dns_records/dns_records_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
|
||||
import 'package:selfprivacy/ui/components/cards/filled_card.dart';
|
||||
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||
|
@ -86,7 +87,7 @@ class _DnsDetailsPageState extends State<DnsDetailsPage> {
|
|||
final bool isReady = context.watch<ServerInstallationCubit>().state
|
||||
is ServerInstallationFinished;
|
||||
final String domain =
|
||||
getIt<ApiConfigModel>().serverDomain?.domainName ?? '';
|
||||
getIt<ResourcesModel>().serverDomain?.domainName ?? '';
|
||||
final DnsRecordsState dnsCubit = context.watch<DnsRecordsCubit>().state;
|
||||
|
||||
print(dnsCubit.dnsState);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:selfprivacy/config/get_it_config.dart';
|
||||
import 'package:selfprivacy/logic/models/console_log.dart';
|
||||
import 'package:selfprivacy/ui/pages/more/console/console_log_item_widget.dart';
|
||||
|
@ -18,21 +17,15 @@ class ConsolePage extends StatefulWidget {
|
|||
class _ConsolePageState extends State<ConsolePage> {
|
||||
ConsoleModel get console => getIt<ConsoleModel>();
|
||||
|
||||
/// should freeze logs state to properly read logs
|
||||
late final Future<void> future;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
future = getIt.allReady();
|
||||
console.addListener(update);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
console.removeListener(update);
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
@ -48,66 +41,36 @@ class _ConsolePageState extends State<ConsolePage> {
|
|||
}
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) => SafeArea(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('console_page.title'.tr()),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => Navigator.of(context).maybePop(),
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
console.paused
|
||||
? Icons.play_arrow_outlined
|
||||
: Icons.pause_outlined,
|
||||
),
|
||||
onPressed: console.paused ? console.play : console.pause,
|
||||
Widget build(final BuildContext context) {
|
||||
final List<ConsoleLog> logs = console.logs;
|
||||
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('console_page.title'.tr()),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => Navigator.of(context).maybePop(),
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
console.paused
|
||||
? Icons.play_arrow_outlined
|
||||
: Icons.pause_outlined,
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Scrollbar(
|
||||
child: FutureBuilder(
|
||||
future: future,
|
||||
builder: (
|
||||
final BuildContext context,
|
||||
final AsyncSnapshot<void> snapshot,
|
||||
) {
|
||||
if (snapshot.hasData) {
|
||||
final List<ConsoleLog> logs = console.logs;
|
||||
|
||||
return logs.isEmpty
|
||||
? const _ConsoleViewEmpty()
|
||||
: _ConsoleViewLoaded(logs: logs);
|
||||
}
|
||||
|
||||
return const _ConsoleViewLoading();
|
||||
},
|
||||
onPressed: console.paused ? console.play : console.pause,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class _ConsoleViewLoading extends StatelessWidget {
|
||||
const _ConsoleViewLoading();
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) => Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text('console_page.waiting'.tr()),
|
||||
const Gap(16),
|
||||
const Expanded(
|
||||
child: Center(
|
||||
child: CircularProgressIndicator.adaptive(),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
body: Scrollbar(
|
||||
child: logs.isEmpty
|
||||
? const _ConsoleViewEmpty()
|
||||
: _ConsoleViewLoaded(logs: logs),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ConsoleViewEmpty extends StatelessWidget {
|
||||
|
|
|
@ -112,7 +112,7 @@ class InitializingPage extends StatelessWidget {
|
|||
'Server',
|
||||
'Installation',
|
||||
],
|
||||
activeIndex: cubit.state.porgressBar,
|
||||
activeIndex: cubit.state.progressBar,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
28
lib/utils/app_logger.dart
Normal file
28
lib/utils/app_logger.dart
Normal file
|
@ -0,0 +1,28 @@
|
|||
import 'dart:developer' as developer;
|
||||
|
||||
import 'package:selfprivacy/config/config.dart';
|
||||
|
||||
class AppLogger {
|
||||
const AppLogger({required this.name});
|
||||
|
||||
final String name;
|
||||
|
||||
// TODO: research other possible options, which could support both
|
||||
// throttling and output formatting
|
||||
void log(
|
||||
final String message, {
|
||||
final Object? error,
|
||||
final StackTrace? stackTrace,
|
||||
}) {
|
||||
if (config.shouldDebugPrint) {
|
||||
// TODO: could probably add UI logging for console_page
|
||||
developer.log(
|
||||
message,
|
||||
error: error,
|
||||
stackTrace: stackTrace,
|
||||
time: DateTime.now(),
|
||||
name: name,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
48
lib/utils/secure_storage.dart
Normal file
48
lib/utils/secure_storage.dart
Normal file
|
@ -0,0 +1,48 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:selfprivacy/utils/app_logger.dart';
|
||||
|
||||
class SecureStorage {
|
||||
static final log = const AppLogger(name: 'secure_storage').log;
|
||||
|
||||
static const FlutterSecureStorage secureStorage = FlutterSecureStorage();
|
||||
static String keyName = 'key';
|
||||
|
||||
static Future<Uint8List?> getKey() async {
|
||||
try {
|
||||
final bool hasEncryptionKey =
|
||||
await secureStorage.containsKey(key: keyName);
|
||||
if (!hasEncryptionKey) {
|
||||
return null;
|
||||
}
|
||||
final String? string = await secureStorage.read(key: keyName);
|
||||
log('successfully got encryption key: $string');
|
||||
|
||||
return base64Url.decode(string!);
|
||||
} catch (error, stackTrace) {
|
||||
log(
|
||||
'error reading encryption key',
|
||||
error: error,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> setKey(final List<int> key) async {
|
||||
try {
|
||||
final value = base64UrlEncode(key);
|
||||
await secureStorage.write(key: keyName, value: value);
|
||||
log('successfully saved encryption key: $value');
|
||||
} catch (error, stackTrace) {
|
||||
log(
|
||||
'error saving new encryption key',
|
||||
error: error,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
|
||||
#include <dynamic_color/dynamic_color_plugin_c_api.h>
|
||||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||
#include <local_auth_windows/local_auth_plugin.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
|
@ -18,6 +19,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|||
registry->GetRegistrarForPlugin("DynamicColorPluginCApi"));
|
||||
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
||||
LocalAuthPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("LocalAuthPlugin"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||
connectivity_plus
|
||||
dynamic_color
|
||||
flutter_secure_storage_windows
|
||||
local_auth_windows
|
||||
url_launcher_windows
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in a new issue