mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-02-04 23:40:38 +00:00
- Refactor Hive boxes
- Delete SSH generation leftovers - Migrate users box to an encrypted box
This commit is contained in:
parent
19bc780db1
commit
bf79fb1adf
|
@ -27,7 +27,7 @@ class BlocAndProviderConfig extends StatelessWidget {
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (_) => AppSettingsCubit(
|
create: (_) => AppSettingsCubit(
|
||||||
isDarkModeOn: isDark,
|
isDarkModeOn: isDark,
|
||||||
isOnbordingShowing: true,
|
isOnboardingShowing: true,
|
||||||
)..load(),
|
)..load(),
|
||||||
),
|
),
|
||||||
BlocProvider(create: (_) => serverInstallationCubit, lazy: false),
|
BlocProvider(create: (_) => serverInstallationCubit, lazy: false),
|
||||||
|
|
|
@ -2,7 +2,6 @@ import 'package:get_it/get_it.dart';
|
||||||
import 'package:selfprivacy/logic/get_it/api_config.dart';
|
import 'package:selfprivacy/logic/get_it/api_config.dart';
|
||||||
import 'package:selfprivacy/logic/get_it/console.dart';
|
import 'package:selfprivacy/logic/get_it/console.dart';
|
||||||
import 'package:selfprivacy/logic/get_it/navigation.dart';
|
import 'package:selfprivacy/logic/get_it/navigation.dart';
|
||||||
import 'package:selfprivacy/logic/get_it/ssh.dart';
|
|
||||||
import 'package:selfprivacy/logic/get_it/timer.dart';
|
import 'package:selfprivacy/logic/get_it/timer.dart';
|
||||||
|
|
||||||
export 'package:selfprivacy/logic/get_it/api_config.dart';
|
export 'package:selfprivacy/logic/get_it/api_config.dart';
|
||||||
|
@ -17,7 +16,6 @@ Future<void> getItSetup() async {
|
||||||
|
|
||||||
getIt.registerSingleton<ConsoleModel>(ConsoleModel());
|
getIt.registerSingleton<ConsoleModel>(ConsoleModel());
|
||||||
getIt.registerSingleton<TimerModel>(TimerModel());
|
getIt.registerSingleton<TimerModel>(TimerModel());
|
||||||
getIt.registerSingleton<SSHModel>(SSHModel()..init());
|
|
||||||
getIt.registerSingleton<ApiConfigModel>(ApiConfigModel()..init());
|
getIt.registerSingleton<ApiConfigModel>(ApiConfigModel()..init());
|
||||||
|
|
||||||
await getIt.allReady();
|
await getIt.allReady();
|
||||||
|
|
|
@ -19,15 +19,22 @@ class HiveConfig {
|
||||||
Hive.registerAdapter(BackblazeBucketAdapter());
|
Hive.registerAdapter(BackblazeBucketAdapter());
|
||||||
Hive.registerAdapter(ServerVolumeAdapter());
|
Hive.registerAdapter(ServerVolumeAdapter());
|
||||||
|
|
||||||
await Hive.openBox(BNames.appSettings);
|
await Hive.openBox(BNames.appSettingsBox);
|
||||||
await Hive.openBox<User>(BNames.users);
|
|
||||||
await Hive.openBox(BNames.servicesState);
|
|
||||||
|
|
||||||
var cipher = HiveAesCipher(await getEncryptedKey(BNames.key));
|
var cipher = HiveAesCipher(
|
||||||
await Hive.openBox(BNames.appConfig, encryptionCipher: cipher);
|
await getEncryptedKey(BNames.serverInstallationEncryptionKey));
|
||||||
|
|
||||||
var sshCipher = HiveAesCipher(await getEncryptedKey(BNames.sshEnckey));
|
await Hive.openBox<User>(BNames.usersDeprecated);
|
||||||
await Hive.openBox(BNames.sshConfig, encryptionCipher: sshCipher);
|
await Hive.openBox<User>(BNames.users, encryptionCipher: cipher);
|
||||||
|
|
||||||
|
Box<User> deprecatedUsers = Hive.box<User>(BNames.usersDeprecated);
|
||||||
|
if (deprecatedUsers.isNotEmpty) {
|
||||||
|
Box<User> users = Hive.box<User>(BNames.users);
|
||||||
|
users.addAll(deprecatedUsers.values.toList());
|
||||||
|
deprecatedUsers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
await Hive.openBox(BNames.serverInstallation, encryptionCipher: cipher);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<Uint8List> getEncryptedKey(String encKey) async {
|
static Future<Uint8List> getEncryptedKey(String encKey) async {
|
||||||
|
@ -43,33 +50,65 @@ class HiveConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mappings for the different boxes and their keys
|
||||||
class BNames {
|
class BNames {
|
||||||
static String appConfig = 'appConfig';
|
/// App settings box. Contains app settings like [isDarkModeOn], [isOnboardingShowing]
|
||||||
|
static String appSettingsBox = 'appSettings';
|
||||||
|
|
||||||
|
/// A boolean field of [appSettingsBox] box.
|
||||||
static String isDarkModeOn = 'isDarkModeOn';
|
static String isDarkModeOn = 'isDarkModeOn';
|
||||||
static String isOnbordingShowing = 'isOnbordingShowing';
|
|
||||||
static String users = 'users';
|
/// A boolean field of [appSettingsBox] box.
|
||||||
|
static String isOnboardingShowing = 'isOnboardingShowing';
|
||||||
|
|
||||||
|
/// Encryption key to decrypt [serverInstallation] and [users] box.
|
||||||
|
static String serverInstallationEncryptionKey = 'key';
|
||||||
|
|
||||||
|
/// Server installation box. Contains server details and provider tokens.
|
||||||
|
static String serverInstallation = 'appConfig';
|
||||||
|
|
||||||
|
/// A List<String> field of [serverInstallation] box.
|
||||||
static String rootKeys = 'rootKeys';
|
static String rootKeys = 'rootKeys';
|
||||||
|
|
||||||
static String appSettings = 'appSettings';
|
/// A boolean field of [serverInstallation] box.
|
||||||
static String servicesState = 'servicesState';
|
|
||||||
|
|
||||||
static String key = 'key';
|
|
||||||
static String sshEnckey = 'sshEngkey';
|
|
||||||
|
|
||||||
static String hasFinalChecked = 'hasFinalChecked';
|
static String hasFinalChecked = 'hasFinalChecked';
|
||||||
|
|
||||||
|
/// A boolean field of [serverInstallation] box.
|
||||||
static String isServerStarted = 'isServerStarted';
|
static String isServerStarted = 'isServerStarted';
|
||||||
|
|
||||||
|
/// A [ServerDomain] field of [serverInstallation] box.
|
||||||
static String serverDomain = 'cloudFlareDomain';
|
static String serverDomain = 'cloudFlareDomain';
|
||||||
|
|
||||||
|
/// A String field of [serverInstallation] box.
|
||||||
static String hetznerKey = 'hetznerKey';
|
static String hetznerKey = 'hetznerKey';
|
||||||
|
|
||||||
|
/// A String field of [serverInstallation] box.
|
||||||
static String cloudFlareKey = 'cloudFlareKey';
|
static String cloudFlareKey = 'cloudFlareKey';
|
||||||
|
|
||||||
|
/// A [User] field of [serverInstallation] box.
|
||||||
static String rootUser = 'rootUser';
|
static String rootUser = 'rootUser';
|
||||||
|
|
||||||
|
/// A [ServerHostingDetails] field of [serverInstallation] box.
|
||||||
static String serverDetails = 'hetznerServer';
|
static String serverDetails = 'hetznerServer';
|
||||||
static String backblazeKey = 'backblazeKey';
|
|
||||||
|
/// A [BackblazeCredential] field of [serverInstallation] box.
|
||||||
|
static String backblazeCredential = 'backblazeKey';
|
||||||
|
|
||||||
|
/// A [BackblazeBucket] field of [serverInstallation] box.
|
||||||
static String backblazeBucket = 'backblazeBucket';
|
static String backblazeBucket = 'backblazeBucket';
|
||||||
|
|
||||||
|
/// A boolean field of [serverInstallation] box.
|
||||||
static String isLoading = 'isLoading';
|
static String isLoading = 'isLoading';
|
||||||
|
|
||||||
|
/// A boolean field of [serverInstallation] box.
|
||||||
static String isServerResetedFirstTime = 'isServerResetedFirstTime';
|
static String isServerResetedFirstTime = 'isServerResetedFirstTime';
|
||||||
|
|
||||||
|
/// A boolean field of [serverInstallation] box.
|
||||||
static String isServerResetedSecondTime = 'isServerResetedSecondTime';
|
static String isServerResetedSecondTime = 'isServerResetedSecondTime';
|
||||||
static String sshConfig = 'sshConfig';
|
|
||||||
static String sshPrivateKey = "sshPrivateKey";
|
/// Deprecated users box as it is unencrypted
|
||||||
static String sshPublicKey = "sshPublicKey";
|
static String usersDeprecated = 'users';
|
||||||
|
|
||||||
|
/// Box with users
|
||||||
|
static String users = 'usersEncrypted';
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,12 @@ part 'authentication_dependend_state.dart';
|
||||||
abstract class ServerInstallationDependendCubit<
|
abstract class ServerInstallationDependendCubit<
|
||||||
T extends ServerInstallationDependendState> extends Cubit<T> {
|
T extends ServerInstallationDependendState> extends Cubit<T> {
|
||||||
ServerInstallationDependendCubit(
|
ServerInstallationDependendCubit(
|
||||||
this.appConfigCubit,
|
this.serverInstallationCubit,
|
||||||
T initState,
|
T initState,
|
||||||
) : super(initState) {
|
) : super(initState) {
|
||||||
authCubitSubscription = appConfigCubit.stream.listen(checkAuthStatus);
|
authCubitSubscription =
|
||||||
checkAuthStatus(appConfigCubit.state);
|
serverInstallationCubit.stream.listen(checkAuthStatus);
|
||||||
|
checkAuthStatus(serverInstallationCubit.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkAuthStatus(ServerInstallationState state) {
|
void checkAuthStatus(ServerInstallationState state) {
|
||||||
|
@ -26,7 +27,7 @@ abstract class ServerInstallationDependendCubit<
|
||||||
}
|
}
|
||||||
|
|
||||||
late StreamSubscription authCubitSubscription;
|
late StreamSubscription authCubitSubscription;
|
||||||
final ServerInstallationCubit appConfigCubit;
|
final ServerInstallationCubit serverInstallationCubit;
|
||||||
|
|
||||||
void load();
|
void load();
|
||||||
void clear();
|
void clear();
|
||||||
|
|
|
@ -9,22 +9,22 @@ part 'app_settings_state.dart';
|
||||||
class AppSettingsCubit extends Cubit<AppSettingsState> {
|
class AppSettingsCubit extends Cubit<AppSettingsState> {
|
||||||
AppSettingsCubit({
|
AppSettingsCubit({
|
||||||
required bool isDarkModeOn,
|
required bool isDarkModeOn,
|
||||||
required bool isOnbordingShowing,
|
required bool isOnboardingShowing,
|
||||||
}) : super(
|
}) : super(
|
||||||
AppSettingsState(
|
AppSettingsState(
|
||||||
isDarkModeOn: isDarkModeOn,
|
isDarkModeOn: isDarkModeOn,
|
||||||
isOnbordingShowing: isOnbordingShowing,
|
isOnboardingShowing: isOnboardingShowing,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
Box box = Hive.box(BNames.appSettings);
|
Box box = Hive.box(BNames.appSettingsBox);
|
||||||
|
|
||||||
void load() {
|
void load() {
|
||||||
bool? isDarkModeOn = box.get(BNames.isDarkModeOn);
|
bool? isDarkModeOn = box.get(BNames.isDarkModeOn);
|
||||||
bool? isOnbordingShowing = box.get(BNames.isOnbordingShowing);
|
bool? isOnboardingShowing = box.get(BNames.isOnboardingShowing);
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
isDarkModeOn: isDarkModeOn,
|
isDarkModeOn: isDarkModeOn,
|
||||||
isOnbordingShowing: isOnbordingShowing,
|
isOnboardingShowing: isOnboardingShowing,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,8 +34,8 @@ class AppSettingsCubit extends Cubit<AppSettingsState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void turnOffOnboarding() {
|
void turnOffOnboarding() {
|
||||||
box.put(BNames.isOnbordingShowing, false);
|
box.put(BNames.isOnboardingShowing, false);
|
||||||
|
|
||||||
emit(state.copyWith(isOnbordingShowing: false));
|
emit(state.copyWith(isOnboardingShowing: false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,18 +3,18 @@ part of 'app_settings_cubit.dart';
|
||||||
class AppSettingsState extends Equatable {
|
class AppSettingsState extends Equatable {
|
||||||
const AppSettingsState({
|
const AppSettingsState({
|
||||||
required this.isDarkModeOn,
|
required this.isDarkModeOn,
|
||||||
required this.isOnbordingShowing,
|
required this.isOnboardingShowing,
|
||||||
});
|
});
|
||||||
|
|
||||||
final bool isDarkModeOn;
|
final bool isDarkModeOn;
|
||||||
final bool isOnbordingShowing;
|
final bool isOnboardingShowing;
|
||||||
|
|
||||||
AppSettingsState copyWith({isDarkModeOn, isOnbordingShowing}) =>
|
AppSettingsState copyWith({isDarkModeOn, isOnboardingShowing}) =>
|
||||||
AppSettingsState(
|
AppSettingsState(
|
||||||
isDarkModeOn: isDarkModeOn ?? this.isDarkModeOn,
|
isDarkModeOn: isDarkModeOn ?? this.isDarkModeOn,
|
||||||
isOnbordingShowing: isOnbordingShowing ?? this.isOnbordingShowing,
|
isOnboardingShowing: isOnboardingShowing ?? this.isOnboardingShowing,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [isDarkModeOn, isOnbordingShowing];
|
List<Object> get props => [isDarkModeOn, isOnboardingShowing];
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,14 +11,14 @@ import 'package:selfprivacy/logic/models/json/backup.dart';
|
||||||
part 'backups_state.dart';
|
part 'backups_state.dart';
|
||||||
|
|
||||||
class BackupsCubit extends ServerInstallationDependendCubit<BackupsState> {
|
class BackupsCubit extends ServerInstallationDependendCubit<BackupsState> {
|
||||||
BackupsCubit(ServerInstallationCubit appConfigCubit)
|
BackupsCubit(ServerInstallationCubit serverInstallationCubit)
|
||||||
: super(appConfigCubit, BackupsState(preventActions: true));
|
: super(serverInstallationCubit, BackupsState(preventActions: true));
|
||||||
|
|
||||||
final api = ServerApi();
|
final api = ServerApi();
|
||||||
final backblaze = BackblazeApi();
|
final backblaze = BackblazeApi();
|
||||||
|
|
||||||
Future<void> load() async {
|
Future<void> load() async {
|
||||||
if (appConfigCubit.state is ServerInstallationFinished) {
|
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||||
final bucket = getIt<ApiConfigModel>().backblazeBucket;
|
final bucket = getIt<ApiConfigModel>().backblazeBucket;
|
||||||
if (bucket == null) {
|
if (bucket == null) {
|
||||||
emit(BackupsState(
|
emit(BackupsState(
|
||||||
|
@ -85,9 +85,9 @@ class BackupsCubit extends ServerInstallationDependendCubit<BackupsState> {
|
||||||
|
|
||||||
Future<void> createBucket() async {
|
Future<void> createBucket() async {
|
||||||
emit(state.copyWith(preventActions: true));
|
emit(state.copyWith(preventActions: true));
|
||||||
final domain = appConfigCubit.state.serverDomain!.domainName
|
final domain = serverInstallationCubit.state.serverDomain!.domainName
|
||||||
.replaceAll(RegExp(r'[^a-zA-Z0-9]'), '-');
|
.replaceAll(RegExp(r'[^a-zA-Z0-9]'), '-');
|
||||||
final serverId = appConfigCubit.state.serverDetails!.id;
|
final serverId = serverInstallationCubit.state.serverDetails!.id;
|
||||||
var bucketName = 'selfprivacy-$domain-$serverId';
|
var bucketName = 'selfprivacy-$domain-$serverId';
|
||||||
// If bucket name is too long, shorten it
|
// If bucket name is too long, shorten it
|
||||||
if (bucketName.length > 49) {
|
if (bucketName.length > 49) {
|
||||||
|
|
|
@ -10,8 +10,8 @@ part 'dns_records_state.dart';
|
||||||
|
|
||||||
class DnsRecordsCubit
|
class DnsRecordsCubit
|
||||||
extends ServerInstallationDependendCubit<DnsRecordsState> {
|
extends ServerInstallationDependendCubit<DnsRecordsState> {
|
||||||
DnsRecordsCubit(ServerInstallationCubit appConfigCubit)
|
DnsRecordsCubit(ServerInstallationCubit serverInstallationCubit)
|
||||||
: super(appConfigCubit,
|
: super(serverInstallationCubit,
|
||||||
DnsRecordsState(dnsState: DnsRecordsStatus.refreshing));
|
DnsRecordsState(dnsState: DnsRecordsStatus.refreshing));
|
||||||
|
|
||||||
final api = ServerApi();
|
final api = ServerApi();
|
||||||
|
@ -21,11 +21,12 @@ class DnsRecordsCubit
|
||||||
emit(DnsRecordsState(
|
emit(DnsRecordsState(
|
||||||
dnsState: DnsRecordsStatus.refreshing,
|
dnsState: DnsRecordsStatus.refreshing,
|
||||||
dnsRecords: _getDesiredDnsRecords(
|
dnsRecords: _getDesiredDnsRecords(
|
||||||
appConfigCubit.state.serverDomain?.domainName, "", "")));
|
serverInstallationCubit.state.serverDomain?.domainName, "", "")));
|
||||||
print('Loading DNS status');
|
print('Loading DNS status');
|
||||||
if (appConfigCubit.state is ServerInstallationFinished) {
|
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||||
final ServerDomain? domain = appConfigCubit.state.serverDomain;
|
final ServerDomain? domain = serverInstallationCubit.state.serverDomain;
|
||||||
final String? ipAddress = appConfigCubit.state.serverDetails?.ip4;
|
final String? ipAddress =
|
||||||
|
serverInstallationCubit.state.serverDetails?.ip4;
|
||||||
if (domain != null && ipAddress != null) {
|
if (domain != null && ipAddress != null) {
|
||||||
final List<DnsRecord> records =
|
final List<DnsRecord> records =
|
||||||
await cloudflare.getDnsRecords(cloudFlareDomain: domain);
|
await cloudflare.getDnsRecords(cloudFlareDomain: domain);
|
||||||
|
@ -96,8 +97,8 @@ class DnsRecordsCubit
|
||||||
|
|
||||||
Future<void> fix() async {
|
Future<void> fix() async {
|
||||||
emit(state.copyWith(dnsState: DnsRecordsStatus.refreshing));
|
emit(state.copyWith(dnsState: DnsRecordsStatus.refreshing));
|
||||||
final ServerDomain? domain = appConfigCubit.state.serverDomain;
|
final ServerDomain? domain = serverInstallationCubit.state.serverDomain;
|
||||||
final String? ipAddress = appConfigCubit.state.serverDetails?.ip4;
|
final String? ipAddress = serverInstallationCubit.state.serverDetails?.ip4;
|
||||||
final String? dkimPublicKey = await api.getDkim();
|
final String? dkimPublicKey = await api.getDkim();
|
||||||
await cloudflare.removeSimilarRecords(cloudFlareDomain: domain!);
|
await cloudflare.removeSimilarRecords(cloudFlareDomain: domain!);
|
||||||
await cloudflare.createMultipleDnsRecords(
|
await cloudflare.createMultipleDnsRecords(
|
||||||
|
|
|
@ -2,8 +2,6 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
|
||||||
import 'package:selfprivacy/logic/get_it/ssh.dart';
|
|
||||||
import 'package:selfprivacy/logic/models/hive/backblaze_credential.dart';
|
import 'package:selfprivacy/logic/models/hive/backblaze_credential.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_details.dart';
|
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||||
|
@ -18,7 +16,7 @@ part '../server_installation/server_installation_state.dart';
|
||||||
class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
ServerInstallationCubit() : super(ServerInstallationEmpty());
|
ServerInstallationCubit() : super(ServerInstallationEmpty());
|
||||||
|
|
||||||
final repository = AppConfigRepository();
|
final repository = ServerInstallationRepository();
|
||||||
|
|
||||||
Timer? timer;
|
Timer? timer;
|
||||||
|
|
||||||
|
@ -266,7 +264,6 @@ class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
||||||
|
|
||||||
if (state.serverDetails != null) {
|
if (state.serverDetails != null) {
|
||||||
await repository.deleteServer(state.serverDomain!);
|
await repository.deleteServer(state.serverDomain!);
|
||||||
await getIt<SSHModel>().clear();
|
|
||||||
}
|
}
|
||||||
await repository.deleteRecords();
|
await repository.deleteRecords();
|
||||||
emit(ServerInstallationNotFinished(
|
emit(ServerInstallationNotFinished(
|
||||||
|
|
|
@ -17,8 +17,8 @@ import 'package:selfprivacy/ui/components/brand_alert/brand_alert.dart';
|
||||||
|
|
||||||
import '../server_installation/server_installation_cubit.dart';
|
import '../server_installation/server_installation_cubit.dart';
|
||||||
|
|
||||||
class AppConfigRepository {
|
class ServerInstallationRepository {
|
||||||
Box box = Hive.box(BNames.appConfig);
|
Box box = Hive.box(BNames.serverInstallation);
|
||||||
|
|
||||||
Future<ServerInstallationState> load() async {
|
Future<ServerInstallationState> load() async {
|
||||||
final hetznerToken = getIt<ApiConfigModel>().hetznerKey;
|
final hetznerToken = getIt<ApiConfigModel>().hetznerKey;
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import 'package:hive/hive.dart';
|
|
||||||
import 'package:selfprivacy/config/hive_config.dart';
|
|
||||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||||
|
@ -7,13 +5,11 @@ import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_depe
|
||||||
part 'services_state.dart';
|
part 'services_state.dart';
|
||||||
|
|
||||||
class ServicesCubit extends ServerInstallationDependendCubit<ServicesState> {
|
class ServicesCubit extends ServerInstallationDependendCubit<ServicesState> {
|
||||||
ServicesCubit(ServerInstallationCubit appConfigCubit)
|
ServicesCubit(ServerInstallationCubit serverInstallationCubit)
|
||||||
: super(appConfigCubit, ServicesState.allOff());
|
: super(serverInstallationCubit, ServicesState.allOff());
|
||||||
|
|
||||||
Box box = Hive.box(BNames.servicesState);
|
|
||||||
final api = ServerApi();
|
final api = ServerApi();
|
||||||
Future<void> load() async {
|
Future<void> load() async {
|
||||||
if (appConfigCubit.state is ServerInstallationFinished) {
|
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||||
var statuses = await api.servicesPowerCheck();
|
var statuses = await api.servicesPowerCheck();
|
||||||
emit(
|
emit(
|
||||||
ServicesState(
|
ServicesState(
|
||||||
|
@ -29,7 +25,6 @@ class ServicesCubit extends ServerInstallationDependendCubit<ServicesState> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void clear() async {
|
void clear() async {
|
||||||
box.clear();
|
|
||||||
emit(ServicesState.allOff());
|
emit(ServicesState.allOff());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:bloc/bloc.dart';
|
|
||||||
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/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||||
|
@ -11,23 +10,23 @@ export 'package:provider/provider.dart';
|
||||||
part 'users_state.dart';
|
part 'users_state.dart';
|
||||||
|
|
||||||
class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
||||||
UsersCubit(ServerInstallationCubit appConfigCubit)
|
UsersCubit(ServerInstallationCubit serverInstallationCubit)
|
||||||
: super(
|
: super(
|
||||||
appConfigCubit,
|
serverInstallationCubit,
|
||||||
UsersState(
|
UsersState(
|
||||||
<User>[], User(login: 'root'), User(login: 'loading...')));
|
<User>[], User(login: 'root'), User(login: 'loading...')));
|
||||||
Box<User> box = Hive.box<User>(BNames.users);
|
Box<User> box = Hive.box<User>(BNames.users);
|
||||||
Box configBox = Hive.box(BNames.appConfig);
|
Box serverInstallationBox = Hive.box(BNames.serverInstallation);
|
||||||
|
|
||||||
final api = ServerApi();
|
final api = ServerApi();
|
||||||
|
|
||||||
Future<void> load() async {
|
Future<void> load() async {
|
||||||
if (appConfigCubit.state is ServerInstallationFinished) {
|
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||||
var loadedUsers = box.values.toList();
|
var loadedUsers = box.values.toList();
|
||||||
final primaryUser = configBox.get(BNames.rootUser,
|
final primaryUser = serverInstallationBox.get(BNames.rootUser,
|
||||||
defaultValue: User(login: 'loading...'));
|
defaultValue: User(login: 'loading...'));
|
||||||
List<String> rootKeys = [
|
List<String> rootKeys = [
|
||||||
...configBox.get(BNames.rootKeys, defaultValue: [])
|
...serverInstallationBox.get(BNames.rootKeys, defaultValue: [])
|
||||||
];
|
];
|
||||||
if (loadedUsers.isNotEmpty) {
|
if (loadedUsers.isNotEmpty) {
|
||||||
emit(UsersState(
|
emit(UsersState(
|
||||||
|
@ -48,10 +47,10 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
||||||
box.addAll(usersWithSshKeys);
|
box.addAll(usersWithSshKeys);
|
||||||
|
|
||||||
final rootUserWithSshKeys = (await loadSshKeys([state.rootUser])).first;
|
final rootUserWithSshKeys = (await loadSshKeys([state.rootUser])).first;
|
||||||
configBox.put(BNames.rootKeys, rootUserWithSshKeys.sshKeys);
|
serverInstallationBox.put(BNames.rootKeys, rootUserWithSshKeys.sshKeys);
|
||||||
final primaryUserWithSshKeys =
|
final primaryUserWithSshKeys =
|
||||||
(await loadSshKeys([state.primaryUser])).first;
|
(await loadSshKeys([state.primaryUser])).first;
|
||||||
configBox.put(BNames.rootUser, primaryUserWithSshKeys);
|
serverInstallationBox.put(BNames.rootUser, primaryUserWithSshKeys);
|
||||||
emit(UsersState(
|
emit(UsersState(
|
||||||
usersWithSshKeys, rootUserWithSshKeys, primaryUserWithSshKeys));
|
usersWithSshKeys, rootUserWithSshKeys, primaryUserWithSshKeys));
|
||||||
}
|
}
|
||||||
|
@ -142,10 +141,10 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
||||||
box.clear();
|
box.clear();
|
||||||
box.addAll(usersWithSshKeys);
|
box.addAll(usersWithSshKeys);
|
||||||
final rootUserWithSshKeys = (await loadSshKeys([state.rootUser])).first;
|
final rootUserWithSshKeys = (await loadSshKeys([state.rootUser])).first;
|
||||||
configBox.put(BNames.rootKeys, rootUserWithSshKeys.sshKeys);
|
serverInstallationBox.put(BNames.rootKeys, rootUserWithSshKeys.sshKeys);
|
||||||
final primaryUserWithSshKeys =
|
final primaryUserWithSshKeys =
|
||||||
(await loadSshKeys([state.primaryUser])).first;
|
(await loadSshKeys([state.primaryUser])).first;
|
||||||
configBox.put(BNames.rootUser, primaryUserWithSshKeys);
|
serverInstallationBox.put(BNames.rootUser, primaryUserWithSshKeys);
|
||||||
emit(UsersState(
|
emit(UsersState(
|
||||||
usersWithSshKeys, rootUserWithSshKeys, primaryUserWithSshKeys));
|
usersWithSshKeys, rootUserWithSshKeys, primaryUserWithSshKeys));
|
||||||
return;
|
return;
|
||||||
|
@ -195,10 +194,10 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
||||||
final result = await api.addRootSshKey(publicKey);
|
final result = await api.addRootSshKey(publicKey);
|
||||||
if (result.isSuccess) {
|
if (result.isSuccess) {
|
||||||
// Add ssh key to the array of root keys
|
// Add ssh key to the array of root keys
|
||||||
final rootKeys =
|
final rootKeys = serverInstallationBox
|
||||||
configBox.get(BNames.rootKeys, defaultValue: []) as List<String>;
|
.get(BNames.rootKeys, defaultValue: []) as List<String>;
|
||||||
rootKeys.add(publicKey);
|
rootKeys.add(publicKey);
|
||||||
configBox.put(BNames.rootKeys, rootKeys);
|
serverInstallationBox.put(BNames.rootKeys, rootKeys);
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
rootUser: User(
|
rootUser: User(
|
||||||
login: state.rootUser.login,
|
login: state.rootUser.login,
|
||||||
|
@ -224,7 +223,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
||||||
sshKeys: primaryUserKeys,
|
sshKeys: primaryUserKeys,
|
||||||
note: state.primaryUser.note,
|
note: state.primaryUser.note,
|
||||||
);
|
);
|
||||||
configBox.put(BNames.rootUser, updatedUser);
|
serverInstallationBox.put(BNames.rootUser, updatedUser);
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
primaryUser: updatedUser,
|
primaryUser: updatedUser,
|
||||||
));
|
));
|
||||||
|
@ -258,10 +257,10 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
||||||
// If it is not primary user, update user
|
// If it is not primary user, update user
|
||||||
|
|
||||||
if (user.login == 'root') {
|
if (user.login == 'root') {
|
||||||
final rootKeys =
|
final rootKeys = serverInstallationBox
|
||||||
configBox.get(BNames.rootKeys, defaultValue: []) as List<String>;
|
.get(BNames.rootKeys, defaultValue: []) as List<String>;
|
||||||
rootKeys.remove(publicKey);
|
rootKeys.remove(publicKey);
|
||||||
configBox.put(BNames.rootKeys, rootKeys);
|
serverInstallationBox.put(BNames.rootKeys, rootKeys);
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
rootUser: User(
|
rootUser: User(
|
||||||
login: state.rootUser.login,
|
login: state.rootUser.login,
|
||||||
|
@ -284,7 +283,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
|
||||||
sshKeys: primaryUserKeys,
|
sshKeys: primaryUserKeys,
|
||||||
note: state.primaryUser.note,
|
note: state.primaryUser.note,
|
||||||
);
|
);
|
||||||
configBox.put(BNames.rootUser, updatedUser);
|
serverInstallationBox.put(BNames.rootUser, updatedUser);
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
primaryUser: updatedUser,
|
primaryUser: updatedUser,
|
||||||
));
|
));
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||||
|
|
||||||
class ApiConfigModel {
|
class ApiConfigModel {
|
||||||
Box _box = Hive.box(BNames.appConfig);
|
Box _box = Hive.box(BNames.serverInstallation);
|
||||||
|
|
||||||
ServerHostingDetails? get serverDetails => _serverDetails;
|
ServerHostingDetails? get serverDetails => _serverDetails;
|
||||||
String? get hetznerKey => _hetznerKey;
|
String? get hetznerKey => _hetznerKey;
|
||||||
|
@ -33,7 +33,7 @@ class ApiConfigModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> storeBackblazeCredential(BackblazeCredential value) async {
|
Future<void> storeBackblazeCredential(BackblazeCredential value) async {
|
||||||
await _box.put(BNames.backblazeKey, value);
|
await _box.put(BNames.backblazeCredential, value);
|
||||||
|
|
||||||
_backblazeCredential = value;
|
_backblazeCredential = value;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ class ApiConfigModel {
|
||||||
_hetznerKey = _box.get(BNames.hetznerKey);
|
_hetznerKey = _box.get(BNames.hetznerKey);
|
||||||
|
|
||||||
_cloudFlareKey = _box.get(BNames.cloudFlareKey);
|
_cloudFlareKey = _box.get(BNames.cloudFlareKey);
|
||||||
_backblazeCredential = _box.get(BNames.backblazeKey);
|
_backblazeCredential = _box.get(BNames.backblazeCredential);
|
||||||
_serverDomain = _box.get(BNames.serverDomain);
|
_serverDomain = _box.get(BNames.serverDomain);
|
||||||
_serverDetails = _box.get(BNames.serverDetails);
|
_serverDetails = _box.get(BNames.serverDetails);
|
||||||
_backblazeBucket = _box.get(BNames.backblazeBucket);
|
_backblazeBucket = _box.get(BNames.backblazeBucket);
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
import 'package:hive/hive.dart';
|
|
||||||
import 'package:pointycastle/pointycastle.dart';
|
|
||||||
import 'package:rsa_encrypt/rsa_encrypt.dart';
|
|
||||||
import 'package:selfprivacy/config/hive_config.dart';
|
|
||||||
import 'package:pointycastle/api.dart' as crypto;
|
|
||||||
import 'package:ssh_key/ssh_key.dart' as ssh_key;
|
|
||||||
|
|
||||||
class SSHModel {
|
|
||||||
Box _box = Hive.box(BNames.sshConfig);
|
|
||||||
String? savedPrivateKey;
|
|
||||||
String? savedPubKey;
|
|
||||||
|
|
||||||
Future<void> generateKeys() async {
|
|
||||||
var helper = RsaKeyHelper();
|
|
||||||
crypto.AsymmetricKeyPair pair =
|
|
||||||
await helper.computeRSAKeyPair(helper.getSecureRandom());
|
|
||||||
var privateKey = pair.privateKey as RSAPrivateKey;
|
|
||||||
var publicKey = pair.publicKey as RSAPublicKey;
|
|
||||||
|
|
||||||
savedPrivateKey = helper.encodePrivateKeyToPemPKCS1(privateKey);
|
|
||||||
savedPubKey = publicKey.encode(ssh_key.PubKeyEncoding.openSsh);
|
|
||||||
|
|
||||||
await _box.put(BNames.sshPrivateKey, savedPrivateKey);
|
|
||||||
await _box.put(BNames.sshPublicKey, savedPubKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
void init() async {
|
|
||||||
savedPrivateKey = _box.get(BNames.sshPrivateKey);
|
|
||||||
savedPubKey = _box.get(BNames.sshPublicKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool get isSSHKeyGenerated => savedPrivateKey != null && savedPubKey != null;
|
|
||||||
|
|
||||||
Future<void> clear() async {
|
|
||||||
savedPrivateKey = null;
|
|
||||||
savedPubKey = null;
|
|
||||||
await _box.clear();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
import 'package:json_annotation/json_annotation.dart';
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
part 'api_token.g.dart';
|
part 'api_token.g.dart';
|
||||||
|
|
|
@ -83,7 +83,7 @@ class MyApp extends StatelessWidget {
|
||||||
darkTheme: darkThemeData,
|
darkTheme: darkThemeData,
|
||||||
themeMode:
|
themeMode:
|
||||||
appSettings.isDarkModeOn ? ThemeMode.dark : ThemeMode.light,
|
appSettings.isDarkModeOn ? ThemeMode.dark : ThemeMode.light,
|
||||||
home: appSettings.isOnbordingShowing
|
home: appSettings.isOnboardingShowing
|
||||||
? OnboardingPage(nextPage: InitializingPage())
|
? OnboardingPage(nextPage: InitializingPage())
|
||||||
: RootPage(),
|
: RootPage(),
|
||||||
builder: (BuildContext context, Widget? widget) {
|
builder: (BuildContext context, Widget? widget) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'package:flutter/services.dart' show rootBundle;
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:selfprivacy/config/brand_colors.dart';
|
import 'package:selfprivacy/config/brand_colors.dart';
|
||||||
import 'package:selfprivacy/config/text_themes.dart';
|
import 'package:selfprivacy/config/text_themes.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
class BrandMarkdown extends StatefulWidget {
|
class BrandMarkdown extends StatefulWidget {
|
||||||
const BrandMarkdown({
|
const BrandMarkdown({
|
||||||
|
@ -60,9 +60,9 @@ class _BrandMarkdownState extends State<BrandMarkdown> {
|
||||||
styleSheet: markdown,
|
styleSheet: markdown,
|
||||||
onTapLink: (String text, String? href, String title) {
|
onTapLink: (String text, String? href, String title) {
|
||||||
if (href != null) {
|
if (href != null) {
|
||||||
canLaunch(href).then((canLaunchURL) {
|
canLaunchUrlString(href).then((canLaunchURL) {
|
||||||
if (canLaunchURL) {
|
if (canLaunchURL) {
|
||||||
launch(href);
|
launchUrlString(href);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,8 @@ class BrandSpanButton extends TextSpan {
|
||||||
);
|
);
|
||||||
|
|
||||||
static _launchURL(String link) async {
|
static _launchURL(String link) async {
|
||||||
if (await canLaunch(link)) {
|
if (await canLaunchUrl(Uri.parse(link))) {
|
||||||
await launch(link);
|
await launchUrl(Uri.parse(link));
|
||||||
} else {
|
} else {
|
||||||
throw 'Could not launch $link';
|
throw 'Could not launch $link';
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart
|
||||||
import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart';
|
import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:selfprivacy/utils/ui_helpers.dart';
|
import 'package:selfprivacy/utils/ui_helpers.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
import '../rootRoute.dart';
|
import '../rootRoute.dart';
|
||||||
|
|
||||||
|
@ -39,13 +39,12 @@ class ServicesPage extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _launchURL(url) async {
|
void _launchURL(url) async {
|
||||||
var _possible = await canLaunch(url);
|
var _possible = await canLaunchUrlString(url);
|
||||||
|
|
||||||
if (_possible) {
|
if (_possible) {
|
||||||
try {
|
try {
|
||||||
await launch(
|
await launchUrlString(
|
||||||
url,
|
url,
|
||||||
enableJavaScript: true,
|
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
|
@ -151,11 +150,9 @@ class _Card extends StatelessWidget {
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
late bool isActive;
|
late bool isActive;
|
||||||
if (hasSwitchJob) {
|
if (hasSwitchJob) {
|
||||||
isActive = ((jobState as JobsStateWithJobs)
|
isActive = ((jobState).jobList.firstWhere((el) =>
|
||||||
.jobList
|
el is ServiceToggleJob &&
|
||||||
.firstWhere((el) =>
|
el.type == serviceType) as ServiceToggleJob)
|
||||||
el is ServiceToggleJob &&
|
|
||||||
el.type == serviceType) as ServiceToggleJob)
|
|
||||||
.needToTurnOn;
|
.needToTurnOn;
|
||||||
} else {
|
} else {
|
||||||
isActive = serviceState.isEnableByType(serviceType);
|
isActive = serviceState.isEnableByType(serviceType);
|
||||||
|
|
|
@ -10,11 +10,11 @@ import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.da
|
||||||
class RecoveryDomain extends StatelessWidget {
|
class RecoveryDomain extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var appConfig = context.watch<ServerInstallationCubit>();
|
var serverInstallation = context.watch<ServerInstallationCubit>();
|
||||||
|
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) =>
|
create: (context) => RecoveryDomainFormCubit(
|
||||||
RecoveryDomainFormCubit(appConfig, FieldCubitFactory(context)),
|
serverInstallation, FieldCubitFactory(context)),
|
||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
var formCubitState = context.watch<RecoveryDomainFormCubit>().state;
|
var formCubitState = context.watch<RecoveryDomainFormCubit>().state;
|
||||||
|
|
|
@ -715,7 +715,7 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.2"
|
||||||
pointycastle:
|
pointycastle:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: pointycastle
|
name: pointycastle
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
|
@ -770,13 +770,6 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.0"
|
version: "3.1.0"
|
||||||
rsa_encrypt:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: rsa_encrypt
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.0"
|
|
||||||
share_plus:
|
share_plus:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -34,10 +34,8 @@ dependencies:
|
||||||
modal_bottom_sheet: ^2.0.1
|
modal_bottom_sheet: ^2.0.1
|
||||||
nanoid: ^1.0.0
|
nanoid: ^1.0.0
|
||||||
package_info: ^2.0.2
|
package_info: ^2.0.2
|
||||||
pointycastle: ^3.5.1
|
|
||||||
pretty_dio_logger: ^1.2.0-beta-1
|
pretty_dio_logger: ^1.2.0-beta-1
|
||||||
provider: ^6.0.2
|
provider: ^6.0.2
|
||||||
rsa_encrypt: ^2.0.0
|
|
||||||
share_plus: ^4.0.4
|
share_plus: ^4.0.4
|
||||||
ssh_key: ^0.7.1
|
ssh_key: ^0.7.1
|
||||||
system_theme: ^2.0.0
|
system_theme: ^2.0.0
|
||||||
|
|
Loading…
Reference in a new issue