mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-09 01:21: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",
|
"request": "launch",
|
||||||
"type": "dart",
|
"type": "dart",
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "debug (nightly)",
|
"name": "debug (nightly flavor)",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "dart",
|
"type": "dart",
|
||||||
"args": [
|
"args": [
|
||||||
|
|
|
@ -46,12 +46,10 @@
|
||||||
},
|
},
|
||||||
"console_page": {
|
"console_page": {
|
||||||
"title": "Console",
|
"title": "Console",
|
||||||
"waiting": "Waiting for initialization…",
|
|
||||||
"copy": "Copy",
|
"copy": "Copy",
|
||||||
"copy_raw": "Raw response",
|
"copy_raw": "Raw response",
|
||||||
"history_empty": "No data yet",
|
"history_empty": "No data yet",
|
||||||
"error": "Error",
|
"error": "Error",
|
||||||
"log": "Log",
|
|
||||||
"rest_api_request": "Rest API Request",
|
"rest_api_request": "Rest API Request",
|
||||||
"rest_api_response": "Rest API Response",
|
"rest_api_response": "Rest API Response",
|
||||||
"graphql_request": "GraphQL Request",
|
"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/api_connection_repository.dart';
|
||||||
import 'package:selfprivacy/logic/get_it/console_model.dart';
|
import 'package:selfprivacy/logic/get_it/console_model.dart';
|
||||||
import 'package:selfprivacy/logic/get_it/navigation.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_config.dart';
|
||||||
export 'package:selfprivacy/logic/get_it/api_connection_repository.dart';
|
export 'package:selfprivacy/logic/get_it/api_connection_repository.dart';
|
||||||
|
@ -14,9 +15,10 @@ final GetIt getIt = GetIt.instance;
|
||||||
Future<void> getItSetup() async {
|
Future<void> getItSetup() async {
|
||||||
getIt.registerSingleton<NavigationService>(NavigationService());
|
getIt.registerSingleton<NavigationService>(NavigationService());
|
||||||
getIt.registerSingleton<ConsoleModel>(ConsoleModel());
|
getIt.registerSingleton<ConsoleModel>(ConsoleModel());
|
||||||
|
getIt.registerSingleton<ResourcesModel>(ResourcesModel()..init());
|
||||||
|
getIt.registerSingleton<WizardDataModel>(WizardDataModel()..init());
|
||||||
|
|
||||||
final apiConfigModel = ApiConfigModel();
|
final apiConfigModel = ApiConfigModel();
|
||||||
await apiConfigModel.init();
|
|
||||||
getIt.registerSingleton<ApiConfigModel>(apiConfigModel);
|
getIt.registerSingleton<ApiConfigModel>(apiConfigModel);
|
||||||
|
|
||||||
getIt.registerSingleton<ApiConnectionRepository>(
|
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:hive_flutter/hive_flutter.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/backblaze_bucket.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/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_details.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/server_domain.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/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/platform_adapter.dart';
|
||||||
|
import 'package:selfprivacy/utils/secure_storage.dart';
|
||||||
|
|
||||||
class HiveConfig {
|
class HiveConfig {
|
||||||
|
static final log = const AppLogger(name: 'hive_config').log;
|
||||||
|
|
||||||
|
/// bump on schema changes
|
||||||
|
static const version = 2;
|
||||||
|
|
||||||
static Future<void> init() async {
|
static Future<void> init() async {
|
||||||
final String? storagePath = PlatformAdapter.storagePath;
|
final String? storagePath = PlatformAdapter.storagePath;
|
||||||
print('HiveConfig: Custom storage path: $storagePath');
|
log('set custom storage path to: "$storagePath"');
|
||||||
|
|
||||||
await Hive.initFlutter(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 {
|
try {
|
||||||
final HiveAesCipher cipher = HiveAesCipher(
|
Hive.registerAdapter(UserAdapter());
|
||||||
await getEncryptedKey(BNames.serverInstallationEncryptionKey),
|
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);
|
static Future<HiveAesCipher> getCipher() async {
|
||||||
await Hive.openBox<User>(BNames.usersBox, encryptionCipher: cipher);
|
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);
|
static Future<void> decryptBoxes() async {
|
||||||
if (deprecatedUsers.isNotEmpty) {
|
try {
|
||||||
final Box<User> users = Hive.box<User>(BNames.usersBox);
|
// load encrypted boxes into memory
|
||||||
await users.addAll(deprecatedUsers.values.toList());
|
final HiveAesCipher cipher = await getCipher();
|
||||||
await deprecatedUsers.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
await Hive.openBox(
|
await Hive.openBox(
|
||||||
BNames.serverInstallationBox,
|
BNames.serverInstallationBox,
|
||||||
encryptionCipher: cipher,
|
encryptionCipher: cipher,
|
||||||
);
|
);
|
||||||
} on PlatformException catch (e) {
|
await Hive.openBox(
|
||||||
print('HiveConfig: Error while opening boxes: $e');
|
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;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<Uint8List> getEncryptedKey(final String encKey) async {
|
// migrations
|
||||||
const FlutterSecureStorage secureStorage = FlutterSecureStorage();
|
|
||||||
|
static Future<void> performMigrations() async {
|
||||||
try {
|
try {
|
||||||
final bool hasEncryptionKey =
|
// perform migration check
|
||||||
await secureStorage.containsKey(key: encKey);
|
final localSettingsBox = await Hive.openBox(BNames.appSettingsBox);
|
||||||
if (!hasEncryptionKey) {
|
|
||||||
final List<int> key = Hive.generateSecureKey();
|
// if it is an initial app launch, we do not need to perform any migrations
|
||||||
await secureStorage.write(key: encKey, value: base64UrlEncode(key));
|
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);
|
/// update saved version after successfull migrations
|
||||||
return base64Url.decode(string!);
|
await localSettingsBox.put(BNames.databaseVersion, version);
|
||||||
} on PlatformException catch (e) {
|
} catch (error, stackTrace) {
|
||||||
print('HiveConfig: Error while getting encryption key: $e');
|
log(
|
||||||
|
'error running db migrations',
|
||||||
|
error: error,
|
||||||
|
stackTrace: stackTrace,
|
||||||
|
);
|
||||||
rethrow;
|
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
|
/// Mappings for the different boxes and their keys
|
||||||
|
@ -77,6 +229,9 @@ class BNames {
|
||||||
/// App settings box. Contains app settings like [darkThemeModeOn], [shouldShowOnboarding]
|
/// App settings box. Contains app settings like [darkThemeModeOn], [shouldShowOnboarding]
|
||||||
static String appSettingsBox = 'appSettings';
|
static String appSettingsBox = 'appSettings';
|
||||||
|
|
||||||
|
/// An integer with last saved version of the database
|
||||||
|
static String databaseVersion = 'databaseVersion';
|
||||||
|
|
||||||
/// A boolean field of [appSettingsBox] box.
|
/// A boolean field of [appSettingsBox] box.
|
||||||
static String darkThemeModeOn = 'isDarkModeOn';
|
static String darkThemeModeOn = 'isDarkModeOn';
|
||||||
|
|
||||||
|
@ -89,9 +244,6 @@ class BNames {
|
||||||
/// A string field
|
/// A string field
|
||||||
static String appLocale = 'appLocale';
|
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.
|
/// Server installation box. Contains server details and provider tokens.
|
||||||
static String serverInstallationBox = 'appConfig';
|
static String serverInstallationBox = 'appConfig';
|
||||||
|
|
||||||
|
@ -122,7 +274,7 @@ class BNames {
|
||||||
/// A String field of [serverInstallationBox] box.
|
/// A String field of [serverInstallationBox] box.
|
||||||
static String cloudFlareKey = 'cloudFlareKey';
|
static String cloudFlareKey = 'cloudFlareKey';
|
||||||
|
|
||||||
/// A String field of [serverTypeIdentifier] box.
|
/// A String field of [serverInstallationBox] box.
|
||||||
static String serverTypeIdentifier = 'serverTypeIdentifier';
|
static String serverTypeIdentifier = 'serverTypeIdentifier';
|
||||||
|
|
||||||
/// A [User] field of [serverInstallationBox] box.
|
/// A [User] field of [serverInstallationBox] box.
|
||||||
|
@ -149,9 +301,24 @@ class BNames {
|
||||||
/// A boolean field of [serverInstallationBox] box.
|
/// A boolean field of [serverInstallationBox] box.
|
||||||
static String isRecoveringServer = 'isRecoveringServer';
|
static String isRecoveringServer = 'isRecoveringServer';
|
||||||
|
|
||||||
/// Deprecated users box as it is unencrypted
|
/// Resources and provider tokens box,
|
||||||
static String usersDeprecated = 'users';
|
static String resourcesBox = 'resourcesBox';
|
||||||
|
|
||||||
/// Box with users
|
/// Server Provider Tokens of [resourcesBox] box.
|
||||||
static String usersBox = 'usersEncrypted';
|
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:http/io_client.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/tls_options.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';
|
import 'package:selfprivacy/logic/models/console_log.dart';
|
||||||
|
|
||||||
void _addConsoleLog(final ConsoleLog message) =>
|
void _addConsoleLog(final ConsoleLog message) =>
|
||||||
|
@ -120,7 +121,7 @@ abstract class GraphQLApiMap {
|
||||||
|
|
||||||
String get _token {
|
String get _token {
|
||||||
String token = '';
|
String token = '';
|
||||||
final serverDetails = getIt<ApiConfigModel>().serverDetails;
|
final serverDetails = getIt<ResourcesModel>().serverDetails;
|
||||||
if (serverDetails != null) {
|
if (serverDetails != null) {
|
||||||
token = serverDetails.apiToken;
|
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/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/services.graphql.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/schema/users.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/auto_upgrade_settings.dart';
|
||||||
import 'package:selfprivacy/logic/models/backup.dart';
|
import 'package:selfprivacy/logic/models/backup.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||||
|
@ -57,7 +58,7 @@ class ServerApi extends GraphQLApiMap
|
||||||
String customToken;
|
String customToken;
|
||||||
@override
|
@override
|
||||||
String? get rootAddress =>
|
String? get rootAddress =>
|
||||||
overrideDomain ?? getIt<ApiConfigModel>().serverDomain?.domainName;
|
overrideDomain ?? getIt<ResourcesModel>().serverDomain?.domainName;
|
||||||
String? overrideDomain;
|
String? overrideDomain;
|
||||||
|
|
||||||
Future<String?> getApiVersion() async {
|
Future<String?> getApiVersion() async {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'package:dio/dio.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/generic_result.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/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/backup.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/backblaze_bucket.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/backups_credential.dart';
|
||||||
|
@ -39,7 +40,7 @@ class BackblazeApi extends RestApiMap {
|
||||||
);
|
);
|
||||||
if (isWithToken) {
|
if (isWithToken) {
|
||||||
final BackupsCredential? backblazeCredential =
|
final BackupsCredential? backblazeCredential =
|
||||||
getIt<ApiConfigModel>().backblazeCredential;
|
getIt<ResourcesModel>().backblazeCredential;
|
||||||
final String token = backblazeCredential!.applicationKey;
|
final String token = backblazeCredential!.applicationKey;
|
||||||
options.headers = {'Authorization': 'Basic $token'};
|
options.headers = {'Authorization': 'Basic $token'};
|
||||||
}
|
}
|
||||||
|
@ -59,7 +60,7 @@ class BackblazeApi extends RestApiMap {
|
||||||
Future<BackblazeApiAuth> getAuthorizationToken() async {
|
Future<BackblazeApiAuth> getAuthorizationToken() async {
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
final BackupsCredential? backblazeCredential =
|
final BackupsCredential? backblazeCredential =
|
||||||
getIt<ApiConfigModel>().backblazeCredential;
|
getIt<ResourcesModel>().backblazeCredential;
|
||||||
if (backblazeCredential == null) {
|
if (backblazeCredential == null) {
|
||||||
throw Exception('Backblaze credential is null');
|
throw Exception('Backblaze credential is null');
|
||||||
}
|
}
|
||||||
|
@ -124,7 +125,7 @@ class BackblazeApi extends RestApiMap {
|
||||||
Future<String> createBucket(final String bucketName) async {
|
Future<String> createBucket(final String bucketName) async {
|
||||||
final BackblazeApiAuth auth = await getAuthorizationToken();
|
final BackblazeApiAuth auth = await getAuthorizationToken();
|
||||||
final BackupsCredential? backblazeCredential =
|
final BackupsCredential? backblazeCredential =
|
||||||
getIt<ApiConfigModel>().backblazeCredential;
|
getIt<ResourcesModel>().backblazeCredential;
|
||||||
final Dio client = await getClient();
|
final Dio client = await getClient();
|
||||||
client.options.baseUrl = auth.apiUrl;
|
client.options.baseUrl = auth.apiUrl;
|
||||||
final Response response = await client.post(
|
final Response response = await client.post(
|
||||||
|
@ -161,7 +162,7 @@ class BackblazeApi extends RestApiMap {
|
||||||
final Response response = await client.post(
|
final Response response = await client.post(
|
||||||
'$apiPrefix/b2_create_key',
|
'$apiPrefix/b2_create_key',
|
||||||
data: {
|
data: {
|
||||||
'accountId': getIt<ApiConfigModel>().backblazeCredential!.keyId,
|
'accountId': getIt<ResourcesModel>().backblazeCredential!.keyId,
|
||||||
'bucketId': bucketId,
|
'bucketId': bucketId,
|
||||||
'capabilities': ['listBuckets', 'listFiles', 'readFiles', 'writeFiles'],
|
'capabilities': ['listBuckets', 'listFiles', 'readFiles', 'writeFiles'],
|
||||||
'keyName': 'selfprivacy-restricted-server-key',
|
'keyName': 'selfprivacy-restricted-server-key',
|
||||||
|
@ -192,7 +193,7 @@ class BackblazeApi extends RestApiMap {
|
||||||
final Response response = await client.get(
|
final Response response = await client.get(
|
||||||
'$apiPrefix/b2_list_buckets',
|
'$apiPrefix/b2_list_buckets',
|
||||||
queryParameters: {
|
queryParameters: {
|
||||||
'accountId': getIt<ApiConfigModel>().backblazeCredential!.keyId,
|
'accountId': getIt<ResourcesModel>().backblazeCredential!.keyId,
|
||||||
},
|
},
|
||||||
options: Options(
|
options: Options(
|
||||||
headers: {'Authorization': auth.authorizationToken},
|
headers: {'Authorization': auth.authorizationToken},
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'package:dio/dio.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/generic_result.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/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';
|
import 'package:selfprivacy/logic/models/json/dns_providers/cloudflare_dns_info.dart';
|
||||||
|
|
||||||
class CloudflareApi extends RestApiMap {
|
class CloudflareApi extends RestApiMap {
|
||||||
|
@ -27,7 +28,7 @@ class CloudflareApi extends RestApiMap {
|
||||||
responseType: ResponseType.json,
|
responseType: ResponseType.json,
|
||||||
);
|
);
|
||||||
if (isWithToken) {
|
if (isWithToken) {
|
||||||
final String? token = getIt<ApiConfigModel>().dnsProviderKey;
|
final String? token = getIt<ResourcesModel>().dnsProviderKey;
|
||||||
assert(token != null);
|
assert(token != null);
|
||||||
options.headers = {'Authorization': 'Bearer $token'};
|
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/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/generic_result.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/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';
|
import 'package:selfprivacy/logic/models/json/dns_providers/desec_dns_info.dart';
|
||||||
|
|
||||||
class DesecApi extends RestApiMap {
|
class DesecApi extends RestApiMap {
|
||||||
|
@ -27,7 +28,7 @@ class DesecApi extends RestApiMap {
|
||||||
responseType: ResponseType.json,
|
responseType: ResponseType.json,
|
||||||
);
|
);
|
||||||
if (isWithToken) {
|
if (isWithToken) {
|
||||||
final String? token = getIt<ApiConfigModel>().dnsProviderKey;
|
final String? token = getIt<ResourcesModel>().dnsProviderKey;
|
||||||
assert(token != null);
|
assert(token != null);
|
||||||
options.headers = {'Authorization': 'Token $token'};
|
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/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/generic_result.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/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';
|
import 'package:selfprivacy/logic/models/json/dns_providers/digital_ocean_dns_info.dart';
|
||||||
|
|
||||||
class DigitalOceanDnsApi extends RestApiMap {
|
class DigitalOceanDnsApi extends RestApiMap {
|
||||||
|
@ -27,7 +28,7 @@ class DigitalOceanDnsApi extends RestApiMap {
|
||||||
responseType: ResponseType.json,
|
responseType: ResponseType.json,
|
||||||
);
|
);
|
||||||
if (isWithToken) {
|
if (isWithToken) {
|
||||||
final String? token = getIt<ApiConfigModel>().dnsProviderKey;
|
final String? token = getIt<ResourcesModel>().dnsProviderKey;
|
||||||
assert(token != null);
|
assert(token != null);
|
||||||
options.headers = {'Authorization': 'Bearer $token'};
|
options.headers = {'Authorization': 'Bearer $token'};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,25 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:dio/io.dart';
|
import 'package:dio/io.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:pretty_dio_logger/pretty_dio_logger.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/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/models/console_log.dart';
|
import 'package:selfprivacy/logic/models/console_log.dart';
|
||||||
|
import 'package:selfprivacy/utils/app_logger.dart';
|
||||||
|
|
||||||
abstract class RestApiMap {
|
abstract class RestApiMap {
|
||||||
|
static final log = const AppLogger(name: 'rest_api_map').log;
|
||||||
|
|
||||||
Future<Dio> getClient({final BaseOptions? customOptions}) async {
|
Future<Dio> getClient({final BaseOptions? customOptions}) async {
|
||||||
final Dio dio = Dio(customOptions ?? (await options));
|
final Dio dio = Dio(customOptions ?? (await options));
|
||||||
if (hasLogger) {
|
if (hasLogger && config.shouldDebugPrint) {
|
||||||
dio.interceptors.add(PrettyDioLogger());
|
dio.interceptors.add(
|
||||||
|
PrettyDioLogger(logPrint: (final object) => debugPrint('$object')),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
dio.interceptors.add(ConsoleInterceptor());
|
dio.interceptors.add(ConsoleInterceptor());
|
||||||
dio.httpClientAdapter = IOHttpClientAdapter(
|
dio.httpClientAdapter = IOHttpClientAdapter(
|
||||||
|
@ -28,14 +34,13 @@ abstract class RestApiMap {
|
||||||
|
|
||||||
dio.interceptors.add(
|
dio.interceptors.add(
|
||||||
InterceptorsWrapper(
|
InterceptorsWrapper(
|
||||||
onError: (final DioException e, final ErrorInterceptorHandler handler) {
|
onError: (
|
||||||
print(e.requestOptions.path);
|
final DioException exception,
|
||||||
print(e.requestOptions.data);
|
final ErrorInterceptorHandler handler,
|
||||||
|
) {
|
||||||
|
log('got dio exception:', error: exception);
|
||||||
|
|
||||||
print(e.message);
|
return handler.next(exception);
|
||||||
print(e.response);
|
|
||||||
|
|
||||||
return handler.next(e);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -103,7 +108,6 @@ class ConsoleInterceptor extends InterceptorsWrapper {
|
||||||
final ErrorInterceptorHandler handler,
|
final ErrorInterceptorHandler handler,
|
||||||
) async {
|
) async {
|
||||||
final Response? response = err.response;
|
final Response? response = err.response;
|
||||||
log(err.toString());
|
|
||||||
|
|
||||||
addConsoleLog(
|
addConsoleLog(
|
||||||
ManualConsoleLog.warning(
|
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/generic_result.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/rest_maps/rest_api_map.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/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/hive/user.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/digital_ocean_server_info.dart';
|
import 'package:selfprivacy/logic/models/json/digital_ocean_server_info.dart';
|
||||||
import 'package:selfprivacy/utils/password_generator.dart';
|
import 'package:selfprivacy/utils/password_generator.dart';
|
||||||
|
@ -30,7 +31,7 @@ class DigitalOceanApi extends RestApiMap {
|
||||||
responseType: ResponseType.json,
|
responseType: ResponseType.json,
|
||||||
);
|
);
|
||||||
if (isWithToken) {
|
if (isWithToken) {
|
||||||
final String? token = getIt<ApiConfigModel>().serverProviderKey;
|
final String? token = getIt<ResourcesModel>().serverProviderKey;
|
||||||
assert(token != null);
|
assert(token != null);
|
||||||
options.headers = {'Authorization': 'Bearer $token'};
|
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/generic_result.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/rest_maps/rest_api_map.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/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/disk_size.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/user.dart';
|
import 'package:selfprivacy/logic/models/hive/user.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/hetzner_server_info.dart';
|
import 'package:selfprivacy/logic/models/json/hetzner_server_info.dart';
|
||||||
|
@ -31,7 +32,7 @@ class HetznerApi extends RestApiMap {
|
||||||
responseType: ResponseType.json,
|
responseType: ResponseType.json,
|
||||||
);
|
);
|
||||||
if (isWithToken) {
|
if (isWithToken) {
|
||||||
final String? token = getIt<ApiConfigModel>().serverProviderKey;
|
final String? token = getIt<ResourcesModel>().serverProviderKey;
|
||||||
assert(token != null);
|
assert(token != null);
|
||||||
options.headers = {'Authorization': 'Bearer $token'};
|
options.headers = {'Authorization': 'Bearer $token'};
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/rest_maps/backblaze.dart';
|
import 'package:selfprivacy/logic/api_maps/rest_maps/backblaze.dart';
|
||||||
|
import 'package:selfprivacy/logic/get_it/resources_model.dart';
|
||||||
import 'package:selfprivacy/logic/models/backup.dart';
|
import 'package:selfprivacy/logic/models/backup.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/backblaze_bucket.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/backups_credential.dart';
|
||||||
|
@ -108,7 +109,7 @@ class BackupsBloc extends Bloc<BackupsEvent, BackupsState> {
|
||||||
final BackupsServerLoaded event,
|
final BackupsServerLoaded event,
|
||||||
final Emitter<BackupsState> emit,
|
final Emitter<BackupsState> emit,
|
||||||
) async {
|
) async {
|
||||||
BackblazeBucket? bucket = getIt<ApiConfigModel>().backblazeBucket;
|
BackblazeBucket? bucket = getIt<ResourcesModel>().backblazeBucket;
|
||||||
final backups = getIt<ApiConnectionRepository>().apiData.backups;
|
final backups = getIt<ApiConnectionRepository>().apiData.backups;
|
||||||
final backupConfig = getIt<ApiConnectionRepository>().apiData.backupConfig;
|
final backupConfig = getIt<ApiConnectionRepository>().apiData.backupConfig;
|
||||||
if (backupConfig.data == null || backups.data == null) {
|
if (backupConfig.data == null || backups.data == null) {
|
||||||
|
@ -227,7 +228,7 @@ class BackupsBloc extends Bloc<BackupsEvent, BackupsState> {
|
||||||
emit(BackupsUnititialized());
|
emit(BackupsUnititialized());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final BackblazeBucket? bucket = getIt<ApiConfigModel>().backblazeBucket;
|
final BackblazeBucket? bucket = getIt<ResourcesModel>().backblazeBucket;
|
||||||
emit(
|
emit(
|
||||||
BackupsInitialized(
|
BackupsInitialized(
|
||||||
backblazeBucket: bucket,
|
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/common_enum/common_enum.dart';
|
||||||
|
|
||||||
import 'package:selfprivacy/logic/cubit/metrics/metrics_cubit.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';
|
import 'package:selfprivacy/logic/providers/providers_controller.dart';
|
||||||
|
|
||||||
class MetricsLoadException implements Exception {
|
class MetricsLoadException implements Exception {
|
||||||
|
@ -30,7 +31,7 @@ class MetricsRepository {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
final serverId = getIt<ApiConfigModel>().serverDetails!.id;
|
final serverId = getIt<ResourcesModel>().serverDetails!.id;
|
||||||
final result = await ProvidersController.currentServerProvider!.getMetrics(
|
final result = await ProvidersController.currentServerProvider!.getMetrics(
|
||||||
serverId,
|
serverId,
|
||||||
start,
|
start,
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
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/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/auto_upgrade_settings.dart';
|
||||||
import 'package:selfprivacy/logic/models/server_metadata.dart';
|
import 'package:selfprivacy/logic/models/server_metadata.dart';
|
||||||
import 'package:selfprivacy/logic/models/ssh_settings.dart';
|
import 'package:selfprivacy/logic/models/ssh_settings.dart';
|
||||||
|
@ -43,7 +44,7 @@ class ServerDetailsCubit
|
||||||
final serverProviderApi = ProvidersController.currentServerProvider;
|
final serverProviderApi = ProvidersController.currentServerProvider;
|
||||||
final dnsProviderApi = ProvidersController.currentDnsProvider;
|
final dnsProviderApi = ProvidersController.currentDnsProvider;
|
||||||
if (serverProviderApi != null && dnsProviderApi != null) {
|
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);
|
final metadataResult = await serverProviderApi.getMetadata(serverId);
|
||||||
metadataResult.data.add(
|
metadataResult.data.add(
|
||||||
ServerMetadataEntity(
|
ServerMetadataEntity(
|
||||||
|
@ -60,7 +61,7 @@ class ServerDetailsCubit
|
||||||
}
|
}
|
||||||
|
|
||||||
void check() async {
|
void check() async {
|
||||||
final bool isReadyToCheck = getIt<ApiConfigModel>().serverDetails != null;
|
final bool isReadyToCheck = getIt<ResourcesModel>().serverDetails != null;
|
||||||
try {
|
try {
|
||||||
if (isReadyToCheck) {
|
if (isReadyToCheck) {
|
||||||
emit(const ServerDetailsLoading());
|
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_details.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/user.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/launch_installation_data.dart';
|
||||||
import 'package:selfprivacy/logic/models/price.dart';
|
import 'package:selfprivacy/logic/models/price.dart';
|
||||||
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
||||||
|
@ -222,12 +223,14 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
provider: BackupsProviderType.backblaze,
|
provider: BackupsProviderType.backblaze,
|
||||||
);
|
);
|
||||||
final BackblazeBucket? bucket;
|
final BackblazeBucket? bucket;
|
||||||
await repository.saveBackblazeKey(backblazeCredential);
|
await repository.saveBackupsCredential(backblazeCredential);
|
||||||
if (state is ServerInstallationRecovery) {
|
if (state is ServerInstallationRecovery) {
|
||||||
final configuration = await ServerApi(
|
final configuration = await ServerApi(
|
||||||
customToken:
|
customToken:
|
||||||
(state as ServerInstallationRecovery).serverDetails!.apiToken,
|
(state as ServerInstallationRecovery).serverDetails!.apiToken,
|
||||||
isWithToken: true,
|
isWithToken: true,
|
||||||
|
overrideDomain:
|
||||||
|
(state as ServerInstallationRecovery).serverDomain!.domainName,
|
||||||
).getBackupsConfiguration();
|
).getBackupsConfiguration();
|
||||||
if (configuration != null) {
|
if (configuration != null) {
|
||||||
try {
|
try {
|
||||||
|
@ -401,7 +404,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
);
|
);
|
||||||
timer = Timer(pauseDuration, () async {
|
timer = Timer(pauseDuration, () async {
|
||||||
final ServerHostingDetails serverDetails = await repository.restart();
|
final ServerHostingDetails serverDetails = await repository.restart();
|
||||||
await repository.saveIsServerResetedFirstTime(true);
|
await repository.saveIsServerRebootedFirstTime(true);
|
||||||
await repository.saveServerDetails(serverDetails);
|
await repository.saveServerDetails(serverDetails);
|
||||||
|
|
||||||
final ServerInstallationNotFinished newState = dataState.copyWith(
|
final ServerInstallationNotFinished newState = dataState.copyWith(
|
||||||
|
@ -442,7 +445,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
);
|
);
|
||||||
timer = Timer(pauseDuration, () async {
|
timer = Timer(pauseDuration, () async {
|
||||||
final ServerHostingDetails serverDetails = await repository.restart();
|
final ServerHostingDetails serverDetails = await repository.restart();
|
||||||
await repository.saveIsServerResetedSecondTime(true);
|
await repository.saveIsServerRebootedSecondTime(true);
|
||||||
await repository.saveServerDetails(serverDetails);
|
await repository.saveServerDetails(serverDetails);
|
||||||
|
|
||||||
final ServerInstallationNotFinished newState = dataState.copyWith(
|
final ServerInstallationNotFinished newState = dataState.copyWith(
|
||||||
|
@ -577,10 +580,12 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
final ServerProviderType serverProvider = await ServerApi(
|
final ServerProviderType serverProvider = await ServerApi(
|
||||||
customToken: serverDetails.apiToken,
|
customToken: serverDetails.apiToken,
|
||||||
isWithToken: true,
|
isWithToken: true,
|
||||||
|
overrideDomain: serverDomain.domainName,
|
||||||
).getServerProviderType();
|
).getServerProviderType();
|
||||||
final dnsProvider = await ServerApi(
|
final dnsProvider = await ServerApi(
|
||||||
customToken: serverDetails.apiToken,
|
customToken: serverDetails.apiToken,
|
||||||
isWithToken: true,
|
isWithToken: true,
|
||||||
|
overrideDomain: serverDomain.domainName,
|
||||||
).getDnsProviderType();
|
).getDnsProviderType();
|
||||||
if (serverProvider == ServerProviderType.unknown ||
|
if (serverProvider == ServerProviderType.unknown ||
|
||||||
dnsProvider == DnsProviderType.unknown) {
|
dnsProvider == DnsProviderType.unknown) {
|
||||||
|
@ -762,6 +767,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
final dnsProviderType = await ServerApi(
|
final dnsProviderType = await ServerApi(
|
||||||
customToken: dataState.serverDetails!.apiToken,
|
customToken: dataState.serverDetails!.apiToken,
|
||||||
isWithToken: true,
|
isWithToken: true,
|
||||||
|
overrideDomain: serverDomain.domainName,
|
||||||
).getDnsProviderType();
|
).getDnsProviderType();
|
||||||
await repository.saveDomain(
|
await repository.saveDomain(
|
||||||
ServerDomain(
|
ServerDomain(
|
||||||
|
@ -769,6 +775,7 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
provider: dnsProviderType,
|
provider: dnsProviderType,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
await repository.setDnsApiToken(token);
|
||||||
emit(
|
emit(
|
||||||
dataState.copyWith(
|
dataState.copyWith(
|
||||||
serverDomain: ServerDomain(
|
serverDomain: ServerDomain(
|
||||||
|
@ -785,21 +792,18 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
final BackupsCredential backblazeCredential,
|
final BackupsCredential backblazeCredential,
|
||||||
) async {
|
) async {
|
||||||
await repository.saveIsServerStarted(true);
|
await repository.saveIsServerStarted(true);
|
||||||
await repository.saveIsServerResetedFirstTime(true);
|
await repository.saveIsServerRebootedFirstTime(true);
|
||||||
await repository.saveIsServerResetedSecondTime(true);
|
await repository.saveIsServerRebootedSecondTime(true);
|
||||||
await repository.saveHasFinalChecked(true);
|
|
||||||
await repository.saveIsRecoveringServer(false);
|
await repository.saveIsRecoveringServer(false);
|
||||||
final serverType = await ProvidersController.currentServerProvider!
|
final serverType = await ProvidersController.currentServerProvider!
|
||||||
.getServerType(state.serverDetails!.id);
|
.getServerType(state.serverDetails!.id);
|
||||||
await repository.saveServerType(serverType.data!);
|
await repository.saveServerType(serverType.data!);
|
||||||
await ProvidersController.currentServerProvider!
|
await ProvidersController.currentServerProvider!
|
||||||
.trySetServerLocation(serverType.data!.location.identifier);
|
.trySetServerLocation(serverType.data!.location.identifier);
|
||||||
final User mainUser = await repository.getMainUser();
|
await repository.saveHasFinalChecked(true);
|
||||||
await repository.saveRootUser(mainUser);
|
|
||||||
final ServerInstallationRecovery updatedState =
|
final ServerInstallationRecovery updatedState =
|
||||||
(state as ServerInstallationRecovery).copyWith(
|
(state as ServerInstallationRecovery).copyWith(
|
||||||
backblazeCredential: backblazeCredential,
|
backblazeCredential: backblazeCredential,
|
||||||
rootUser: mainUser,
|
|
||||||
serverTypeIdentificator: serverType.data!.identifier,
|
serverTypeIdentificator: serverType.data!.identifier,
|
||||||
);
|
);
|
||||||
emit(updatedState.finish());
|
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/graphql_maps/server_api/server_api.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/tls_options.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/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/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_details.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/server_domain.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/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/device_token.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
import 'package:selfprivacy/logic/models/json/dns_records.dart';
|
||||||
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
||||||
|
@ -34,22 +39,25 @@ class ServerAuthorizationException implements Exception {
|
||||||
|
|
||||||
class ServerInstallationRepository {
|
class ServerInstallationRepository {
|
||||||
Box box = Hive.box(BNames.serverInstallationBox);
|
Box box = Hive.box(BNames.serverInstallationBox);
|
||||||
Box<User> usersBox = Hive.box(BNames.usersBox);
|
|
||||||
|
|
||||||
Future<ServerInstallationState> load() async {
|
Future<ServerInstallationState> load() async {
|
||||||
final String? providerApiToken = getIt<ApiConfigModel>().serverProviderKey;
|
final ServerInstallationWizardData? wizardData =
|
||||||
final String? location = getIt<ApiConfigModel>().serverLocation;
|
getIt<WizardDataModel>().serverInstallation;
|
||||||
final String? dnsApiToken = getIt<ApiConfigModel>().dnsProviderKey;
|
final List<Server> servers = getIt<ResourcesModel>().servers;
|
||||||
final String? serverTypeIdentificator = getIt<ApiConfigModel>().serverType;
|
final String? providerApiToken = getIt<ResourcesModel>().serverProviderKey;
|
||||||
final ServerDomain? serverDomain = getIt<ApiConfigModel>().serverDomain;
|
final String? location = getIt<ResourcesModel>().serverLocation;
|
||||||
final DnsProviderType? dnsProvider = getIt<ApiConfigModel>().dnsProvider;
|
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 =
|
final ServerProviderType? serverProvider =
|
||||||
getIt<ApiConfigModel>().serverProvider;
|
getIt<ResourcesModel>().serverProvider;
|
||||||
final BackupsCredential? backblazeCredential =
|
final BackupsCredential? backblazeCredential =
|
||||||
getIt<ApiConfigModel>().backblazeCredential;
|
getIt<ResourcesModel>().backblazeCredential;
|
||||||
final ServerHostingDetails? serverDetails =
|
final ServerHostingDetails? serverDetails =
|
||||||
getIt<ApiConfigModel>().serverDetails;
|
getIt<ResourcesModel>().serverDetails;
|
||||||
|
|
||||||
|
// TODO: Init server providers in another place
|
||||||
if (serverProvider != null ||
|
if (serverProvider != null ||
|
||||||
(serverDetails != null &&
|
(serverDetails != null &&
|
||||||
serverDetails.provider != ServerProviderType.unknown)) {
|
serverDetails.provider != ServerProviderType.unknown)) {
|
||||||
|
@ -73,85 +81,48 @@ class ServerInstallationRepository {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (box.get(BNames.hasFinalChecked, defaultValue: false)) {
|
// If we don't have any wizard data, we either have a server set up, or we are starting from scratch
|
||||||
TlsOptions.verifyCertificate = true;
|
// This behaviour shall change when we introduce multitenancy
|
||||||
if (serverTypeIdentificator == null && serverDetails != null) {
|
if (wizardData == null) {
|
||||||
final finalServerType = await ProvidersController.currentServerProvider!
|
if (servers.isEmpty) {
|
||||||
.getServerType(serverDetails.id);
|
// We don't have anything set up, so we start from scratch
|
||||||
await saveServerType(finalServerType.data!);
|
return ServerInstallationNotFinished.fromWizardData(
|
||||||
await ProvidersController.currentServerProvider!
|
ServerInstallationWizardData.empty(),
|
||||||
.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),
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
// We have a server set up, so we load it
|
||||||
|
TlsOptions.verifyCertificate = true;
|
||||||
return ServerInstallationFinished(
|
return ServerInstallationFinished(
|
||||||
installationDialoguePopUp: null,
|
|
||||||
providerApiToken: providerApiToken!,
|
providerApiToken: providerApiToken!,
|
||||||
serverTypeIdentificator: serverTypeIdentificator!,
|
serverTypeIdentificator: serverTypeIdentificator!,
|
||||||
dnsApiToken: dnsApiToken!,
|
dnsApiToken: dnsApiToken!,
|
||||||
serverDomain: serverDomain!,
|
serverDomain: serverDomain!,
|
||||||
backblazeCredential: backblazeCredential!,
|
backblazeCredential: backblazeCredential!,
|
||||||
serverDetails: serverDetails!,
|
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) &&
|
if (wizardData.isRecoveringServer && wizardData.serverDomain != null) {
|
||||||
serverDomain != null) {
|
|
||||||
return ServerInstallationRecovery(
|
return ServerInstallationRecovery(
|
||||||
providerApiToken: providerApiToken,
|
providerApiToken: wizardData.serverProviderKey,
|
||||||
dnsApiToken: dnsApiToken,
|
dnsApiToken: wizardData.dnsProviderKey,
|
||||||
serverDomain: serverDomain,
|
serverDomain: wizardData.serverDomain,
|
||||||
serverTypeIdentificator: serverTypeIdentificator,
|
serverTypeIdentificator: wizardData.serverTypeIdentifier,
|
||||||
backblazeCredential: backblazeCredential,
|
backblazeCredential: wizardData.backupsCredential,
|
||||||
serverDetails: serverDetails,
|
serverDetails: wizardData.serverDetails,
|
||||||
rootUser: box.get(BNames.rootUser),
|
|
||||||
currentStep: _getCurrentRecoveryStep(
|
currentStep: _getCurrentRecoveryStep(
|
||||||
providerApiToken,
|
wizardData.serverProviderKey,
|
||||||
dnsApiToken,
|
wizardData.dnsProviderKey,
|
||||||
serverDomain,
|
wizardData.serverDomain!,
|
||||||
serverDetails,
|
wizardData.serverDetails,
|
||||||
),
|
),
|
||||||
recoveryCapabilities: await getRecoveryCapabilities(serverDomain),
|
recoveryCapabilities:
|
||||||
|
await getRecoveryCapabilities(wizardData.serverDomain!),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ServerInstallationNotFinished(
|
return ServerInstallationNotFinished.fromWizardData(wizardData);
|
||||||
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,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RecoveryStep _getCurrentRecoveryStep(
|
RecoveryStep _getCurrentRecoveryStep(
|
||||||
|
@ -177,7 +148,9 @@ class ServerInstallationRepository {
|
||||||
|
|
||||||
void clearAppConfig() {
|
void clearAppConfig() {
|
||||||
box.clear();
|
box.clear();
|
||||||
usersBox.clear();
|
getIt<ResourcesModel>().clear();
|
||||||
|
getIt<WizardDataModel>().clear();
|
||||||
|
getIt<ApiConnectionRepository>().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ServerHostingDetails> startServer(
|
Future<ServerHostingDetails> startServer(
|
||||||
|
@ -209,6 +182,9 @@ class ServerInstallationRepository {
|
||||||
if (!domainResult.success || domainResult.data.isEmpty) {
|
if (!domainResult.success || domainResult.data.isEmpty) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
await getIt<ResourcesModel>().removeDnsProviderToken(
|
||||||
|
getIt<ResourcesModel>().dnsProviderCredentials.first,
|
||||||
|
);
|
||||||
|
|
||||||
return domainResult.data.any(
|
return domainResult.data.any(
|
||||||
(final serverDomain) => serverDomain.domainName == domain,
|
(final serverDomain) => serverDomain.domainName == domain,
|
||||||
|
@ -216,7 +192,12 @@ class ServerInstallationRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> createDkimRecord(final ServerDomain domain) async {
|
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;
|
late DnsRecord record;
|
||||||
try {
|
try {
|
||||||
|
@ -233,14 +214,26 @@ class ServerInstallationRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> isHttpServerWorking() async {
|
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();
|
return api.isHttpServerWorking();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ServerHostingDetails> restart() async {
|
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) {
|
if (result.success && result.data != null) {
|
||||||
server.copyWith(startTime: result.data);
|
server.copyWith(startTime: result.data);
|
||||||
|
@ -252,7 +245,7 @@ class ServerInstallationRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ServerHostingDetails> powerOn() async {
|
Future<ServerHostingDetails> powerOn() async {
|
||||||
final server = getIt<ApiConfigModel>().serverDetails!;
|
final server = getIt<ResourcesModel>().serverDetails!;
|
||||||
return startServer(server);
|
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 =>
|
Future<List<ServerBasicInfo>> getServersOnProviderAccount() async =>
|
||||||
(await ProvidersController.currentServerProvider!.getServers()).data;
|
(await ProvidersController.currentServerProvider!.getServers()).data;
|
||||||
|
|
||||||
Future<void> saveServerDetails(
|
Future<void> saveServerDetails(
|
||||||
final ServerHostingDetails serverDetails,
|
final ServerHostingDetails serverDetails,
|
||||||
) async {
|
) async {
|
||||||
await getIt<ApiConfigModel>().setServerDetails(serverDetails);
|
await getIt<WizardDataModel>().setServerDetails(serverDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteServerDetails() async {
|
Future<void> deleteServerDetails() async {
|
||||||
await box.delete(BNames.serverDetails);
|
await getIt<WizardDataModel>().deleteServerDetails();
|
||||||
await getIt<ApiConfigModel>().init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveServerProviderType(final ServerProviderType type) async {
|
Future<void> saveServerProviderType(final ServerProviderType type) async {
|
||||||
await getIt<ApiConfigModel>().storeServerProviderType(type);
|
await getIt<WizardDataModel>().setServerProviderType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveDnsProviderType(final DnsProviderType type) async {
|
Future<void> saveDnsProviderType(final DnsProviderType type) async {
|
||||||
await getIt<ApiConfigModel>().setDnsProviderType(type);
|
await getIt<WizardDataModel>().setDnsProviderType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveServerProviderKey(final String key) async {
|
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 {
|
Future<void> saveServerType(final ServerType serverType) async {
|
||||||
await getIt<ApiConfigModel>().setServerTypeIdentifier(
|
await getIt<WizardDataModel>().setServerTypeIdentifier(
|
||||||
serverType.identifier,
|
serverType.identifier,
|
||||||
);
|
);
|
||||||
await getIt<ApiConfigModel>().setServerLocation(
|
await getIt<WizardDataModel>().setServerLocation(
|
||||||
serverType.location.identifier,
|
serverType.location.identifier,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteServerProviderKey() async {
|
Future<void> saveBackupsCredential(
|
||||||
await box.delete(BNames.hetznerKey);
|
final BackupsCredential backupsCredential,
|
||||||
await getIt<ApiConfigModel>().init();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> saveBackblazeKey(
|
|
||||||
final BackupsCredential backblazeCredential,
|
|
||||||
) async {
|
) async {
|
||||||
await getIt<ApiConfigModel>().setBackblazeCredential(backblazeCredential);
|
await getIt<WizardDataModel>().setBackupsCredential(backupsCredential);
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteBackblazeKey() async {
|
|
||||||
await box.delete(BNames.backblazeCredential);
|
|
||||||
await getIt<ApiConfigModel>().init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setDnsApiToken(final String key) async {
|
Future<void> setDnsApiToken(final String key) async {
|
||||||
await getIt<ApiConfigModel>().setDnsProviderKey(key);
|
await getIt<WizardDataModel>().setDnsProviderKey(key);
|
||||||
}
|
await getIt<ResourcesModel>().addDnsProviderToken(
|
||||||
|
DnsProviderCredential(
|
||||||
Future<void> deleteDnsProviderKey() async {
|
tokenId: null,
|
||||||
await box.delete(BNames.cloudFlareKey);
|
token: key,
|
||||||
await getIt<ApiConfigModel>().init();
|
provider: getIt<WizardDataModel>().serverInstallation!.dnsProviderType!,
|
||||||
|
associatedDomainNames: [],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveDomain(final ServerDomain serverDomain) async {
|
Future<void> saveDomain(final ServerDomain serverDomain) async {
|
||||||
await getIt<ApiConfigModel>().setServerDomain(serverDomain);
|
await getIt<WizardDataModel>().setServerDomain(serverDomain);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteDomain() async {
|
Future<void> deleteDomain() async {
|
||||||
await box.delete(BNames.serverDomain);
|
await getIt<WizardDataModel>().deleteServerDomain();
|
||||||
await getIt<ApiConfigModel>().init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveIsServerStarted(final bool value) async {
|
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 {
|
Future<void> saveIsServerRebootedFirstTime(final bool value) async {
|
||||||
await box.put(BNames.isServerResetedFirstTime, value);
|
await getIt<WizardDataModel>().setIsServerRebootedFirstTime(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveIsServerResetedSecondTime(final bool value) async {
|
Future<void> saveIsServerRebootedSecondTime(final bool value) async {
|
||||||
await box.put(BNames.isServerResetedSecondTime, value);
|
await getIt<WizardDataModel>().setIsServerRebootedSecondTime(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveRootUser(final User rootUser) async {
|
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 {
|
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 {
|
Future<void> saveHasFinalChecked(final bool value) async {
|
||||||
await box.put(BNames.hasFinalChecked, value);
|
// 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.
|
||||||
Future<bool> deleteServer(final ServerDomain serverDomain) async {
|
await getIt<WizardDataModel>().moveServerTypeToServerDetails();
|
||||||
final ServerApi api = ServerApi();
|
final ServerInstallationWizardData wizardData =
|
||||||
final dnsRecords = await api.getDnsRecords();
|
getIt<WizardDataModel>().serverInstallation!;
|
||||||
final GenericResult<void> removalResult =
|
await getIt<ResourcesModel>().addServer(
|
||||||
await ProvidersController.currentDnsProvider!.removeDomainRecords(
|
Server(
|
||||||
domain: serverDomain,
|
hostingDetails: wizardData.serverDetails!,
|
||||||
records: dnsRecords,
|
domain: wizardData.serverDomain!,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
await getIt<ResourcesModel>().associateServerWithToken(
|
||||||
if (!removalResult.success) {
|
wizardData.serverDetails!.id,
|
||||||
getIt<NavigationService>().showSnackBar(
|
wizardData.serverProviderKey!,
|
||||||
'modals.dns_removal_error'.tr(),
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final deletionResult =
|
|
||||||
await ProvidersController.currentServerProvider!.deleteServer(
|
|
||||||
serverDomain.domainName,
|
|
||||||
);
|
);
|
||||||
|
await getIt<ResourcesModel>().associateDomainWithToken(
|
||||||
if (!deletionResult.success) {
|
wizardData.serverDomain!.domainName,
|
||||||
getIt<NavigationService>().showSnackBar(
|
wizardData.dnsProviderKey!,
|
||||||
'modals.server_validators_error'.tr(),
|
);
|
||||||
);
|
await getIt<ResourcesModel>().addBackupsCredential(
|
||||||
return false;
|
wizardData.backupsCredential!,
|
||||||
}
|
);
|
||||||
|
await getIt<WizardDataModel>().clearServerInstallation();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ abstract class ServerInstallationState extends Equatable {
|
||||||
ServerSetupProgress get progress => ServerSetupProgress
|
ServerSetupProgress get progress => ServerSetupProgress
|
||||||
.values[_fulfillmentList.where((final el) => el!).length];
|
.values[_fulfillmentList.where((final el) => el!).length];
|
||||||
|
|
||||||
int get porgressBar {
|
int get progressBar {
|
||||||
if (progress.index < 6) {
|
if (progress.index < 6) {
|
||||||
return progress.index;
|
return progress.index;
|
||||||
} else if (progress.index < 10) {
|
} else if (progress.index < 10) {
|
||||||
|
@ -119,7 +119,7 @@ class TimerState extends ServerInstallationNotFinished {
|
||||||
enum ServerSetupProgress {
|
enum ServerSetupProgress {
|
||||||
nothingYet,
|
nothingYet,
|
||||||
serverProviderFilled,
|
serverProviderFilled,
|
||||||
servertTypeFilled,
|
serverTypeFilled,
|
||||||
dnsProviderFilled,
|
dnsProviderFilled,
|
||||||
backblazeFilled,
|
backblazeFilled,
|
||||||
domainFilled,
|
domainFilled,
|
||||||
|
@ -147,6 +147,26 @@ class ServerInstallationNotFinished extends ServerInstallationState {
|
||||||
super.serverDetails,
|
super.serverDetails,
|
||||||
super.installationDialoguePopUp,
|
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 bool isLoading;
|
||||||
final Map<String, DnsRecordStatus>? dnsMatches;
|
final Map<String, DnsRecordStatus>? dnsMatches;
|
||||||
final String? customSshKey;
|
final String? customSshKey;
|
||||||
|
@ -211,12 +231,7 @@ class ServerInstallationNotFinished extends ServerInstallationState {
|
||||||
dnsApiToken: dnsApiToken!,
|
dnsApiToken: dnsApiToken!,
|
||||||
backblazeCredential: backblazeCredential!,
|
backblazeCredential: backblazeCredential!,
|
||||||
serverDomain: serverDomain!,
|
serverDomain: serverDomain!,
|
||||||
rootUser: rootUser!,
|
|
||||||
serverDetails: serverDetails!,
|
serverDetails: serverDetails!,
|
||||||
isServerStarted: isServerStarted,
|
|
||||||
isServerResetedFirstTime: isServerResetedFirstTime,
|
|
||||||
isServerResetedSecondTime: isServerResetedSecondTime,
|
|
||||||
installationDialoguePopUp: installationDialoguePopUp,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,13 +262,14 @@ class ServerInstallationFinished extends ServerInstallationState {
|
||||||
required String super.dnsApiToken,
|
required String super.dnsApiToken,
|
||||||
required BackupsCredential super.backblazeCredential,
|
required BackupsCredential super.backblazeCredential,
|
||||||
required ServerDomain super.serverDomain,
|
required ServerDomain super.serverDomain,
|
||||||
required User super.rootUser,
|
|
||||||
required ServerHostingDetails super.serverDetails,
|
required ServerHostingDetails super.serverDetails,
|
||||||
required super.isServerStarted,
|
}) : super(
|
||||||
required super.isServerResetedFirstTime,
|
rootUser: null,
|
||||||
required super.isServerResetedSecondTime,
|
isServerStarted: true,
|
||||||
required super.installationDialoguePopUp,
|
isServerResetedFirstTime: true,
|
||||||
});
|
isServerResetedSecondTime: true,
|
||||||
|
installationDialoguePopUp: null,
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [
|
List<Object?> get props => [
|
||||||
|
@ -302,9 +318,9 @@ class ServerInstallationRecovery extends ServerInstallationState {
|
||||||
super.dnsApiToken,
|
super.dnsApiToken,
|
||||||
super.backblazeCredential,
|
super.backblazeCredential,
|
||||||
super.serverDomain,
|
super.serverDomain,
|
||||||
super.rootUser,
|
|
||||||
super.serverDetails,
|
super.serverDetails,
|
||||||
}) : super(
|
}) : super(
|
||||||
|
rootUser: null,
|
||||||
isServerStarted: true,
|
isServerStarted: true,
|
||||||
isServerResetedFirstTime: true,
|
isServerResetedFirstTime: true,
|
||||||
isServerResetedSecondTime: true,
|
isServerResetedSecondTime: true,
|
||||||
|
@ -334,7 +350,6 @@ class ServerInstallationRecovery extends ServerInstallationState {
|
||||||
final String? dnsApiToken,
|
final String? dnsApiToken,
|
||||||
final BackupsCredential? backblazeCredential,
|
final BackupsCredential? backblazeCredential,
|
||||||
final ServerDomain? serverDomain,
|
final ServerDomain? serverDomain,
|
||||||
final User? rootUser,
|
|
||||||
final ServerHostingDetails? serverDetails,
|
final ServerHostingDetails? serverDetails,
|
||||||
final RecoveryStep? currentStep,
|
final RecoveryStep? currentStep,
|
||||||
final ServerRecoveryCapabilities? recoveryCapabilities,
|
final ServerRecoveryCapabilities? recoveryCapabilities,
|
||||||
|
@ -346,7 +361,6 @@ class ServerInstallationRecovery extends ServerInstallationState {
|
||||||
dnsApiToken: dnsApiToken ?? this.dnsApiToken,
|
dnsApiToken: dnsApiToken ?? this.dnsApiToken,
|
||||||
backblazeCredential: backblazeCredential ?? this.backblazeCredential,
|
backblazeCredential: backblazeCredential ?? this.backblazeCredential,
|
||||||
serverDomain: serverDomain ?? this.serverDomain,
|
serverDomain: serverDomain ?? this.serverDomain,
|
||||||
rootUser: rootUser ?? this.rootUser,
|
|
||||||
serverDetails: serverDetails ?? this.serverDetails,
|
serverDetails: serverDetails ?? this.serverDetails,
|
||||||
currentStep: currentStep ?? this.currentStep,
|
currentStep: currentStep ?? this.currentStep,
|
||||||
recoveryCapabilities: recoveryCapabilities ?? this.recoveryCapabilities,
|
recoveryCapabilities: recoveryCapabilities ?? this.recoveryCapabilities,
|
||||||
|
@ -358,11 +372,6 @@ class ServerInstallationRecovery extends ServerInstallationState {
|
||||||
dnsApiToken: dnsApiToken!,
|
dnsApiToken: dnsApiToken!,
|
||||||
backblazeCredential: backblazeCredential!,
|
backblazeCredential: backblazeCredential!,
|
||||||
serverDomain: serverDomain!,
|
serverDomain: serverDomain!,
|
||||||
rootUser: rootUser!,
|
|
||||||
serverDetails: serverDetails!,
|
serverDetails: serverDetails!,
|
||||||
isServerStarted: true,
|
|
||||||
isServerResetedFirstTime: true,
|
|
||||||
isServerResetedSecondTime: true,
|
|
||||||
installationDialoguePopUp: null,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,115 +1,18 @@
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:selfprivacy/config/hive_config.dart';
|
import 'package:selfprivacy/config/hive_config.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/backblaze_bucket.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 {
|
class ApiConfigModel {
|
||||||
final Box _box = Hive.box(BNames.serverInstallationBox);
|
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';
|
static const localeCodeFallback = 'en';
|
||||||
String? _localeCode;
|
String? _localeCode;
|
||||||
|
|
||||||
String get localeCode => _localeCode ?? localeCodeFallback;
|
String get localeCode => _localeCode ?? localeCodeFallback;
|
||||||
Future<void> setLocaleCode(final String value) async => _localeCode = value;
|
Future<void> setLocaleCode(final String value) async => _localeCode = value;
|
||||||
Future<void> resetLocaleCode() async => _localeCode = null;
|
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 {
|
Future<void> setBackblazeBucket(final BackblazeBucket value) async {
|
||||||
await _box.put(BNames.backblazeBucket, value);
|
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/get_it_config.dart';
|
||||||
import 'package:selfprivacy/config/hive_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/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/auto_upgrade_settings.dart';
|
||||||
import 'package:selfprivacy/logic/models/backup.dart';
|
import 'package:selfprivacy/logic/models/backup.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||||
|
@ -246,14 +247,12 @@ class ApiConnectionRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerHostingDetails? get serverDetails =>
|
ServerHostingDetails? get serverDetails =>
|
||||||
getIt<ApiConfigModel>().serverDetails;
|
getIt<ResourcesModel>().serverDetails;
|
||||||
ServerDomain? get serverDomain => getIt<ApiConfigModel>().serverDomain;
|
ServerDomain? get serverDomain => getIt<ResourcesModel>().serverDomain;
|
||||||
|
|
||||||
void init() async {
|
void init() async {
|
||||||
final serverDetails = getIt<ApiConfigModel>().serverDetails;
|
final serverDetails = getIt<ResourcesModel>().serverDetails;
|
||||||
final hasFinalChecked =
|
if (serverDetails == null) {
|
||||||
box.get(BNames.hasFinalChecked, defaultValue: false);
|
|
||||||
if (serverDetails == null || !hasFinalChecked) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
connectionStatus = ConnectionStatus.reconnecting;
|
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 {
|
Future<void> _refetchEverything(final Version version) async {
|
||||||
await _apiData.serverJobs
|
await _apiData.serverJobs
|
||||||
.refetchData(version, () => _dataStream.add(_apiData));
|
.refetchData(version, () => _dataStream.add(_apiData));
|
||||||
|
@ -302,7 +307,7 @@ class ApiConnectionRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> reload(final Timer? timer) async {
|
Future<void> reload(final Timer? timer) async {
|
||||||
final serverDetails = getIt<ApiConfigModel>().serverDetails;
|
final serverDetails = getIt<ResourcesModel>().serverDetails;
|
||||||
if (serverDetails == null) {
|
if (serverDetails == null) {
|
||||||
return;
|
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
|
1. User
|
||||||
2. ServerHostingDetails
|
2. ServerHostingDetails
|
||||||
3. ServerDomain
|
3. ServerDomain
|
||||||
4. BackblazeCredential
|
4. BackupsCredential
|
||||||
5. ServerVolume
|
5. ServerProviderVolume
|
||||||
6. BackblazeBucket
|
6. BackblazeBucket
|
||||||
|
7. ServerProviderCredential
|
||||||
|
8. DnsProviderCredential
|
||||||
|
9. Server
|
||||||
|
|
||||||
|
## Wizards store
|
||||||
|
60. ServerInstallationWizardData
|
||||||
|
|
||||||
## Enums
|
## Enums
|
||||||
|
|
||||||
100. DnsProvider
|
100. DnsProvider
|
||||||
101. ServerProvider
|
101. ServerProvider
|
||||||
102. UserType
|
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';
|
part 'backups_credential.g.dart';
|
||||||
|
|
||||||
|
// TODO: Make a constant type.
|
||||||
@HiveType(typeId: 4)
|
@HiveType(typeId: 4)
|
||||||
class BackupsCredential {
|
class BackupsCredential {
|
||||||
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.volume,
|
||||||
required this.apiToken,
|
required this.apiToken,
|
||||||
required this.provider,
|
required this.provider,
|
||||||
|
this.serverLocation,
|
||||||
|
this.serverType,
|
||||||
this.startTime,
|
this.startTime,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -21,12 +23,13 @@ class ServerHostingDetails {
|
||||||
@HiveField(1)
|
@HiveField(1)
|
||||||
final int id;
|
final int id;
|
||||||
|
|
||||||
@HiveField(3)
|
// TODO: Check if it is still needed
|
||||||
final DateTime? createTime;
|
|
||||||
|
|
||||||
@HiveField(2)
|
@HiveField(2)
|
||||||
final DateTime? startTime;
|
final DateTime? startTime;
|
||||||
|
|
||||||
|
@HiveField(3)
|
||||||
|
final DateTime? createTime;
|
||||||
|
|
||||||
// TODO: Check if it is still needed
|
// TODO: Check if it is still needed
|
||||||
@HiveField(4)
|
@HiveField(4)
|
||||||
final ServerProviderVolume volume;
|
final ServerProviderVolume volume;
|
||||||
|
@ -37,9 +40,21 @@ class ServerHostingDetails {
|
||||||
@HiveField(6, defaultValue: ServerProviderType.hetzner)
|
@HiveField(6, defaultValue: ServerProviderType.hetzner)
|
||||||
final ServerProviderType provider;
|
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(
|
ServerHostingDetails(
|
||||||
startTime: startTime ?? this.startTime,
|
startTime: startTime ?? this.startTime,
|
||||||
|
serverLocation: serverLocation ?? this.serverLocation,
|
||||||
|
serverType: serverType ?? this.serverType,
|
||||||
createTime: createTime,
|
createTime: createTime,
|
||||||
id: id,
|
id: id,
|
||||||
ip4: ip4,
|
ip4: ip4,
|
||||||
|
@ -103,3 +118,7 @@ enum ServerProviderType {
|
||||||
unknown => 'Unknown',
|
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
|
provider: fields[6] == null
|
||||||
? ServerProviderType.hetzner
|
? ServerProviderType.hetzner
|
||||||
: fields[6] as ServerProviderType,
|
: fields[6] as ServerProviderType,
|
||||||
|
serverLocation: fields[7] as String?,
|
||||||
|
serverType: fields[8] as String?,
|
||||||
startTime: fields[2] as DateTime?,
|
startTime: fields[2] as DateTime?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -32,21 +34,25 @@ class ServerHostingDetailsAdapter extends TypeAdapter<ServerHostingDetails> {
|
||||||
@override
|
@override
|
||||||
void write(BinaryWriter writer, ServerHostingDetails obj) {
|
void write(BinaryWriter writer, ServerHostingDetails obj) {
|
||||||
writer
|
writer
|
||||||
..writeByte(7)
|
..writeByte(9)
|
||||||
..writeByte(0)
|
..writeByte(0)
|
||||||
..write(obj.ip4)
|
..write(obj.ip4)
|
||||||
..writeByte(1)
|
..writeByte(1)
|
||||||
..write(obj.id)
|
..write(obj.id)
|
||||||
..writeByte(3)
|
|
||||||
..write(obj.createTime)
|
|
||||||
..writeByte(2)
|
..writeByte(2)
|
||||||
..write(obj.startTime)
|
..write(obj.startTime)
|
||||||
|
..writeByte(3)
|
||||||
|
..write(obj.createTime)
|
||||||
..writeByte(4)
|
..writeByte(4)
|
||||||
..write(obj.volume)
|
..write(obj.volume)
|
||||||
..writeByte(5)
|
..writeByte(5)
|
||||||
..write(obj.apiToken)
|
..write(obj.apiToken)
|
||||||
..writeByte(6)
|
..writeByte(6)
|
||||||
..write(obj.provider);
|
..write(obj.provider)
|
||||||
|
..writeByte(7)
|
||||||
|
..write(obj.serverLocation)
|
||||||
|
..writeByte(8)
|
||||||
|
..write(obj.serverType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -57,3 +57,7 @@ enum DnsProviderType {
|
||||||
unknown => 'Unknown',
|
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 {
|
enum CurrencyType {
|
||||||
eur,
|
eur,
|
||||||
usd,
|
usd,
|
||||||
unkown,
|
unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
class Currency {
|
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/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/dns_records/dns_records_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_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/brand_icons/brand_icons.dart';
|
||||||
import 'package:selfprivacy/ui/components/cards/filled_card.dart';
|
import 'package:selfprivacy/ui/components/cards/filled_card.dart';
|
||||||
import 'package:selfprivacy/ui/layouts/brand_hero_screen.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
|
final bool isReady = context.watch<ServerInstallationCubit>().state
|
||||||
is ServerInstallationFinished;
|
is ServerInstallationFinished;
|
||||||
final String domain =
|
final String domain =
|
||||||
getIt<ApiConfigModel>().serverDomain?.domainName ?? '';
|
getIt<ResourcesModel>().serverDomain?.domainName ?? '';
|
||||||
final DnsRecordsState dnsCubit = context.watch<DnsRecordsCubit>().state;
|
final DnsRecordsState dnsCubit = context.watch<DnsRecordsCubit>().state;
|
||||||
|
|
||||||
print(dnsCubit.dnsState);
|
print(dnsCubit.dnsState);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:gap/gap.dart';
|
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/models/console_log.dart';
|
import 'package:selfprivacy/logic/models/console_log.dart';
|
||||||
import 'package:selfprivacy/ui/pages/more/console/console_log_item_widget.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> {
|
class _ConsolePageState extends State<ConsolePage> {
|
||||||
ConsoleModel get console => getIt<ConsoleModel>();
|
ConsoleModel get console => getIt<ConsoleModel>();
|
||||||
|
|
||||||
/// should freeze logs state to properly read logs
|
|
||||||
late final Future<void> future;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
future = getIt.allReady();
|
|
||||||
console.addListener(update);
|
console.addListener(update);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
console.removeListener(update);
|
console.removeListener(update);
|
||||||
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,66 +41,36 @@ class _ConsolePageState extends State<ConsolePage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(final BuildContext context) => SafeArea(
|
Widget build(final BuildContext context) {
|
||||||
child: Scaffold(
|
final List<ConsoleLog> logs = console.logs;
|
||||||
appBar: AppBar(
|
|
||||||
title: Text('console_page.title'.tr()),
|
return SafeArea(
|
||||||
leading: IconButton(
|
child: Scaffold(
|
||||||
icon: const Icon(Icons.arrow_back),
|
appBar: AppBar(
|
||||||
onPressed: () => Navigator.of(context).maybePop(),
|
title: Text('console_page.title'.tr()),
|
||||||
),
|
leading: IconButton(
|
||||||
actions: [
|
icon: const Icon(Icons.arrow_back),
|
||||||
IconButton(
|
onPressed: () => Navigator.of(context).maybePop(),
|
||||||
icon: Icon(
|
),
|
||||||
console.paused
|
actions: [
|
||||||
? Icons.play_arrow_outlined
|
IconButton(
|
||||||
: Icons.pause_outlined,
|
icon: Icon(
|
||||||
),
|
console.paused
|
||||||
onPressed: console.paused ? console.play : console.pause,
|
? Icons.play_arrow_outlined
|
||||||
|
: Icons.pause_outlined,
|
||||||
),
|
),
|
||||||
],
|
onPressed: console.paused ? console.play : console.pause,
|
||||||
),
|
|
||||||
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();
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
);
|
body: Scrollbar(
|
||||||
}
|
child: logs.isEmpty
|
||||||
|
? const _ConsoleViewEmpty()
|
||||||
class _ConsoleViewLoading extends StatelessWidget {
|
: _ConsoleViewLoaded(logs: logs),
|
||||||
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(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ConsoleViewEmpty extends StatelessWidget {
|
class _ConsoleViewEmpty extends StatelessWidget {
|
||||||
|
|
|
@ -112,7 +112,7 @@ class InitializingPage extends StatelessWidget {
|
||||||
'Server',
|
'Server',
|
||||||
'Installation',
|
'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 <connectivity_plus/connectivity_plus_windows_plugin.h>
|
||||||
#include <dynamic_color/dynamic_color_plugin_c_api.h>
|
#include <dynamic_color/dynamic_color_plugin_c_api.h>
|
||||||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.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>
|
#include <url_launcher_windows/url_launcher_windows.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
|
@ -18,6 +19,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
registry->GetRegistrarForPlugin("DynamicColorPluginCApi"));
|
registry->GetRegistrarForPlugin("DynamicColorPluginCApi"));
|
||||||
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
|
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
||||||
|
LocalAuthPluginRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("LocalAuthPlugin"));
|
||||||
UrlLauncherWindowsRegisterWithRegistrar(
|
UrlLauncherWindowsRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
connectivity_plus
|
connectivity_plus
|
||||||
dynamic_color
|
dynamic_color
|
||||||
flutter_secure_storage_windows
|
flutter_secure_storage_windows
|
||||||
|
local_auth_windows
|
||||||
url_launcher_windows
|
url_launcher_windows
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue