2021-01-21 21:01:42 +00:00
|
|
|
import 'dart:async';
|
|
|
|
|
2022-05-24 18:55:39 +00:00
|
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
2022-05-20 22:56:50 +00:00
|
|
|
import 'package:easy_localization/easy_localization.dart';
|
2021-01-06 17:35:57 +00:00
|
|
|
import 'package:equatable/equatable.dart';
|
2022-05-20 22:56:50 +00:00
|
|
|
import 'package:selfprivacy/config/get_it_config.dart';
|
2022-05-14 02:54:40 +00:00
|
|
|
import 'package:selfprivacy/logic/models/hive/backblaze_credential.dart';
|
|
|
|
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
2022-05-18 11:21:11 +00:00
|
|
|
import 'package:selfprivacy/logic/models/hive/server_domain.dart';
|
2022-05-14 02:54:40 +00:00
|
|
|
import 'package:selfprivacy/logic/models/hive/user.dart';
|
2022-05-20 22:56:50 +00:00
|
|
|
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
2021-01-21 07:35:38 +00:00
|
|
|
|
2022-05-17 13:31:34 +00:00
|
|
|
import '../server_installation/server_installation_repository.dart';
|
2022-02-08 06:59:19 +00:00
|
|
|
|
2021-03-18 00:55:38 +00:00
|
|
|
export 'package:provider/provider.dart';
|
2021-01-06 17:35:57 +00:00
|
|
|
|
2022-05-17 13:31:34 +00:00
|
|
|
part '../server_installation/server_installation_state.dart';
|
2021-01-06 17:35:57 +00:00
|
|
|
|
2022-05-17 13:31:34 +00:00
|
|
|
class ServerInstallationCubit extends Cubit<ServerInstallationState> {
|
2022-05-24 18:55:39 +00:00
|
|
|
ServerInstallationCubit() : super(const ServerInstallationEmpty());
|
2021-01-06 17:35:57 +00:00
|
|
|
|
2022-05-17 20:08:28 +00:00
|
|
|
final repository = ServerInstallationRepository();
|
2021-01-06 17:35:57 +00:00
|
|
|
|
2022-05-14 02:54:40 +00:00
|
|
|
Timer? timer;
|
|
|
|
|
2021-03-31 14:33:58 +00:00
|
|
|
Future<void> load() async {
|
|
|
|
var state = await repository.load();
|
2021-02-16 18:48:15 +00:00
|
|
|
|
2022-05-17 13:31:34 +00:00
|
|
|
if (state is ServerInstallationFinished) {
|
2021-02-16 18:48:15 +00:00
|
|
|
emit(state);
|
2022-05-17 13:31:34 +00:00
|
|
|
} else if (state is ServerInstallationNotFinished) {
|
2022-05-13 13:57:56 +00:00
|
|
|
if (state.progress == ServerSetupProgress.serverCreated) {
|
|
|
|
startServerIfDnsIsOkay(state: state);
|
|
|
|
} else if (state.progress == ServerSetupProgress.serverStarted) {
|
|
|
|
resetServerIfServerIsOkay(state: state);
|
|
|
|
} else if (state.progress == ServerSetupProgress.serverResetedFirstTime) {
|
|
|
|
oneMoreReset(state: state);
|
|
|
|
} else if (state.progress ==
|
|
|
|
ServerSetupProgress.serverResetedSecondTime) {
|
|
|
|
finishCheckIfServerIsOkay(state: state);
|
2021-10-13 21:49:24 +00:00
|
|
|
} else {
|
|
|
|
emit(state);
|
2021-09-29 13:08:19 +00:00
|
|
|
}
|
2022-05-17 13:31:34 +00:00
|
|
|
} else if (state is ServerInstallationRecovery) {
|
2022-05-13 13:57:56 +00:00
|
|
|
emit(state);
|
2021-09-29 13:08:19 +00:00
|
|
|
} else {
|
|
|
|
throw 'wrong state';
|
2021-02-16 18:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-14 02:54:40 +00:00
|
|
|
void setHetznerKey(String hetznerKey) async {
|
|
|
|
await repository.saveHetznerKey(hetznerKey);
|
2022-05-19 17:43:25 +00:00
|
|
|
|
|
|
|
if (state is ServerInstallationRecovery) {
|
|
|
|
emit((state as ServerInstallationRecovery).copyWith(
|
|
|
|
hetznerKey: hetznerKey,
|
2022-05-24 18:55:39 +00:00
|
|
|
currentStep: RecoveryStep.serverSelection,
|
2022-05-19 17:43:25 +00:00
|
|
|
));
|
2022-05-20 22:56:50 +00:00
|
|
|
return;
|
2022-05-19 17:43:25 +00:00
|
|
|
}
|
|
|
|
|
2022-05-17 13:31:34 +00:00
|
|
|
emit((state as ServerInstallationNotFinished)
|
|
|
|
.copyWith(hetznerKey: hetznerKey));
|
2022-05-14 02:54:40 +00:00
|
|
|
}
|
2021-02-16 18:48:15 +00:00
|
|
|
|
2022-05-14 02:54:40 +00:00
|
|
|
void setCloudflareKey(String cloudFlareKey) async {
|
2022-05-24 17:45:13 +00:00
|
|
|
if (state is ServerInstallationRecovery) {
|
|
|
|
setAndValidateCloudflareToken(cloudFlareKey);
|
|
|
|
return;
|
|
|
|
}
|
2022-05-14 02:54:40 +00:00
|
|
|
await repository.saveCloudFlareKey(cloudFlareKey);
|
2022-05-17 13:31:34 +00:00
|
|
|
emit((state as ServerInstallationNotFinished)
|
|
|
|
.copyWith(cloudFlareKey: cloudFlareKey));
|
2022-05-14 02:54:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void setBackblazeKey(String keyId, String applicationKey) async {
|
|
|
|
var backblazeCredential = BackblazeCredential(
|
|
|
|
keyId: keyId,
|
|
|
|
applicationKey: applicationKey,
|
|
|
|
);
|
|
|
|
await repository.saveBackblazeKey(backblazeCredential);
|
2022-05-23 14:21:34 +00:00
|
|
|
if (state is ServerInstallationRecovery) {
|
|
|
|
final mainUser = await repository.getMainUser();
|
|
|
|
final updatedState = (state as ServerInstallationRecovery).copyWith(
|
|
|
|
backblazeCredential: backblazeCredential,
|
|
|
|
rootUser: mainUser,
|
|
|
|
);
|
|
|
|
emit(updatedState.finish());
|
|
|
|
return;
|
|
|
|
}
|
2022-05-17 13:31:34 +00:00
|
|
|
emit((state as ServerInstallationNotFinished)
|
2022-05-14 02:54:40 +00:00
|
|
|
.copyWith(backblazeCredential: backblazeCredential));
|
|
|
|
}
|
|
|
|
|
|
|
|
void setDomain(ServerDomain serverDomain) async {
|
|
|
|
await repository.saveDomain(serverDomain);
|
2022-05-17 13:31:34 +00:00
|
|
|
emit((state as ServerInstallationNotFinished)
|
|
|
|
.copyWith(serverDomain: serverDomain));
|
2022-05-14 02:54:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void setRootUser(User rootUser) async {
|
|
|
|
await repository.saveRootUser(rootUser);
|
2022-05-17 13:31:34 +00:00
|
|
|
emit((state as ServerInstallationNotFinished).copyWith(rootUser: rootUser));
|
2022-05-14 02:54:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void createServerAndSetDnsRecords() async {
|
2022-05-24 18:55:39 +00:00
|
|
|
ServerInstallationNotFinished stateCopy =
|
2022-05-17 13:31:34 +00:00
|
|
|
state as ServerInstallationNotFinished;
|
2022-05-24 18:55:39 +00:00
|
|
|
onCancel() => emit(
|
2022-05-17 13:31:34 +00:00
|
|
|
(state as ServerInstallationNotFinished).copyWith(isLoading: false));
|
2022-05-16 22:15:16 +00:00
|
|
|
|
2022-05-24 18:55:39 +00:00
|
|
|
onSuccess(ServerHostingDetails serverDetails) async {
|
2022-05-14 02:54:40 +00:00
|
|
|
await repository.createDnsRecords(
|
|
|
|
serverDetails.ip4,
|
|
|
|
state.serverDomain!,
|
2022-05-16 22:15:16 +00:00
|
|
|
onCancel: onCancel,
|
2022-05-14 02:54:40 +00:00
|
|
|
);
|
|
|
|
|
2022-05-17 13:31:34 +00:00
|
|
|
emit((state as ServerInstallationNotFinished).copyWith(
|
2022-05-14 02:54:40 +00:00
|
|
|
isLoading: false,
|
|
|
|
serverDetails: serverDetails,
|
|
|
|
));
|
2022-05-24 18:55:39 +00:00
|
|
|
runDelayed(startServerIfDnsIsOkay, const Duration(seconds: 30), null);
|
|
|
|
}
|
2022-05-14 02:54:40 +00:00
|
|
|
|
|
|
|
try {
|
2022-05-17 13:31:34 +00:00
|
|
|
emit((state as ServerInstallationNotFinished).copyWith(isLoading: true));
|
2022-05-14 02:54:40 +00:00
|
|
|
await repository.createServer(
|
|
|
|
state.rootUser!,
|
|
|
|
state.serverDomain!.domainName,
|
|
|
|
state.cloudFlareKey!,
|
|
|
|
state.backblazeCredential!,
|
|
|
|
onCancel: onCancel,
|
|
|
|
onSuccess: onSuccess,
|
|
|
|
);
|
|
|
|
} catch (e) {
|
2022-05-24 18:55:39 +00:00
|
|
|
emit(stateCopy);
|
2022-05-14 02:54:40 +00:00
|
|
|
}
|
2022-05-13 13:57:56 +00:00
|
|
|
}
|
2021-02-16 18:48:15 +00:00
|
|
|
|
2022-05-17 13:31:34 +00:00
|
|
|
void startServerIfDnsIsOkay({ServerInstallationNotFinished? state}) async {
|
|
|
|
final dataState = state ?? this.state as ServerInstallationNotFinished;
|
2021-02-16 18:48:15 +00:00
|
|
|
|
2022-05-13 13:57:56 +00:00
|
|
|
emit(TimerState(dataState: dataState, isLoading: true));
|
2021-02-16 18:48:15 +00:00
|
|
|
|
2022-05-13 13:57:56 +00:00
|
|
|
var ip4 = dataState.serverDetails!.ip4;
|
|
|
|
var domainName = dataState.serverDomain!.domainName;
|
2021-03-25 08:32:00 +00:00
|
|
|
|
2022-05-13 13:57:56 +00:00
|
|
|
var matches = await repository.isDnsAddressesMatch(
|
|
|
|
domainName, ip4, dataState.dnsMatches);
|
|
|
|
|
|
|
|
if (matches.values.every((value) => value)) {
|
|
|
|
var server = await repository.startServer(
|
|
|
|
dataState.serverDetails!,
|
|
|
|
);
|
|
|
|
await repository.saveServerDetails(server);
|
|
|
|
await repository.saveIsServerStarted(true);
|
2021-02-16 18:48:15 +00:00
|
|
|
|
2022-05-13 13:57:56 +00:00
|
|
|
emit(
|
|
|
|
dataState.copyWith(
|
|
|
|
isServerStarted: true,
|
|
|
|
isLoading: false,
|
|
|
|
serverDetails: server,
|
|
|
|
),
|
|
|
|
);
|
2022-05-24 18:55:39 +00:00
|
|
|
runDelayed(
|
|
|
|
resetServerIfServerIsOkay, const Duration(seconds: 60), dataState);
|
2021-02-16 18:48:15 +00:00
|
|
|
} else {
|
2022-05-13 13:57:56 +00:00
|
|
|
emit(
|
|
|
|
dataState.copyWith(
|
|
|
|
isLoading: false,
|
|
|
|
dnsMatches: matches,
|
|
|
|
),
|
|
|
|
);
|
2022-05-24 18:55:39 +00:00
|
|
|
runDelayed(
|
|
|
|
startServerIfDnsIsOkay, const Duration(seconds: 30), dataState);
|
2021-02-16 18:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-17 13:31:34 +00:00
|
|
|
void oneMoreReset({ServerInstallationNotFinished? state}) async {
|
|
|
|
final dataState = state ?? this.state as ServerInstallationNotFinished;
|
2021-02-16 18:48:15 +00:00
|
|
|
|
2022-05-13 13:57:56 +00:00
|
|
|
emit(TimerState(dataState: dataState, isLoading: true));
|
2021-02-16 18:48:15 +00:00
|
|
|
|
2022-05-13 13:57:56 +00:00
|
|
|
var isServerWorking = await repository.isHttpServerWorking();
|
2021-02-16 18:48:15 +00:00
|
|
|
|
2022-05-13 13:57:56 +00:00
|
|
|
if (isServerWorking) {
|
2022-05-24 18:55:39 +00:00
|
|
|
var pauseDuration = const Duration(seconds: 30);
|
2022-05-13 13:57:56 +00:00
|
|
|
emit(TimerState(
|
|
|
|
dataState: dataState,
|
|
|
|
timerStart: DateTime.now(),
|
|
|
|
isLoading: false,
|
|
|
|
duration: pauseDuration,
|
|
|
|
));
|
|
|
|
timer = Timer(pauseDuration, () async {
|
|
|
|
var hetznerServerDetails = await repository.restart();
|
|
|
|
await repository.saveIsServerResetedSecondTime(true);
|
|
|
|
await repository.saveServerDetails(hetznerServerDetails);
|
|
|
|
|
|
|
|
emit(
|
|
|
|
dataState.copyWith(
|
|
|
|
isServerResetedSecondTime: true,
|
|
|
|
serverDetails: hetznerServerDetails,
|
|
|
|
isLoading: false,
|
|
|
|
),
|
|
|
|
);
|
2022-05-24 18:55:39 +00:00
|
|
|
runDelayed(
|
|
|
|
finishCheckIfServerIsOkay, const Duration(seconds: 60), dataState);
|
2022-05-13 13:57:56 +00:00
|
|
|
});
|
2021-03-31 11:37:39 +00:00
|
|
|
} else {
|
2022-05-24 18:55:39 +00:00
|
|
|
runDelayed(oneMoreReset, const Duration(seconds: 60), dataState);
|
2021-03-31 11:37:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void resetServerIfServerIsOkay({
|
2022-05-17 13:31:34 +00:00
|
|
|
ServerInstallationNotFinished? state,
|
2021-03-31 11:37:39 +00:00
|
|
|
}) async {
|
2022-05-17 13:31:34 +00:00
|
|
|
final dataState = state ?? this.state as ServerInstallationNotFinished;
|
2021-03-31 11:37:39 +00:00
|
|
|
|
2022-05-13 13:57:56 +00:00
|
|
|
emit(TimerState(dataState: dataState, isLoading: true));
|
2021-03-31 11:37:39 +00:00
|
|
|
|
2022-05-13 13:57:56 +00:00
|
|
|
var isServerWorking = await repository.isHttpServerWorking();
|
2021-03-31 11:37:39 +00:00
|
|
|
|
2022-05-13 13:57:56 +00:00
|
|
|
if (isServerWorking) {
|
2022-05-24 18:55:39 +00:00
|
|
|
var pauseDuration = const Duration(seconds: 30);
|
2022-05-13 13:57:56 +00:00
|
|
|
emit(TimerState(
|
|
|
|
dataState: dataState,
|
|
|
|
timerStart: DateTime.now(),
|
|
|
|
isLoading: false,
|
|
|
|
duration: pauseDuration,
|
|
|
|
));
|
|
|
|
timer = Timer(pauseDuration, () async {
|
|
|
|
var hetznerServerDetails = await repository.restart();
|
|
|
|
await repository.saveIsServerResetedFirstTime(true);
|
|
|
|
await repository.saveServerDetails(hetznerServerDetails);
|
|
|
|
|
|
|
|
emit(
|
|
|
|
dataState.copyWith(
|
|
|
|
isServerResetedFirstTime: true,
|
|
|
|
serverDetails: hetznerServerDetails,
|
|
|
|
isLoading: false,
|
|
|
|
),
|
|
|
|
);
|
2022-05-24 18:55:39 +00:00
|
|
|
runDelayed(oneMoreReset, const Duration(seconds: 60), dataState);
|
2022-05-13 13:57:56 +00:00
|
|
|
});
|
2021-02-16 18:48:15 +00:00
|
|
|
} else {
|
2022-05-24 18:55:39 +00:00
|
|
|
runDelayed(
|
|
|
|
resetServerIfServerIsOkay, const Duration(seconds: 60), dataState);
|
2021-02-16 18:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void finishCheckIfServerIsOkay({
|
2022-05-17 13:31:34 +00:00
|
|
|
ServerInstallationNotFinished? state,
|
2021-02-16 18:48:15 +00:00
|
|
|
}) async {
|
2022-05-17 13:31:34 +00:00
|
|
|
final dataState = state ?? this.state as ServerInstallationNotFinished;
|
2021-02-16 18:48:15 +00:00
|
|
|
|
2022-05-13 13:57:56 +00:00
|
|
|
emit(TimerState(dataState: dataState, isLoading: true));
|
2021-02-16 18:48:15 +00:00
|
|
|
|
2022-05-13 13:57:56 +00:00
|
|
|
var isServerWorking = await repository.isHttpServerWorking();
|
2021-02-16 18:48:15 +00:00
|
|
|
|
2022-05-13 13:57:56 +00:00
|
|
|
if (isServerWorking) {
|
|
|
|
await repository.createDkimRecord(dataState.serverDomain!);
|
|
|
|
await repository.saveHasFinalChecked(true);
|
2021-03-25 08:32:00 +00:00
|
|
|
|
2022-05-13 13:57:56 +00:00
|
|
|
emit(dataState.finish());
|
2021-02-16 18:48:15 +00:00
|
|
|
} else {
|
2022-05-24 18:55:39 +00:00
|
|
|
runDelayed(
|
|
|
|
finishCheckIfServerIsOkay, const Duration(seconds: 60), dataState);
|
2021-02-16 18:48:15 +00:00
|
|
|
}
|
2021-01-06 17:35:57 +00:00
|
|
|
}
|
|
|
|
|
2022-05-17 13:31:34 +00:00
|
|
|
void runDelayed(void Function() work, Duration delay,
|
|
|
|
ServerInstallationNotFinished? state) async {
|
|
|
|
final dataState = state ?? this.state as ServerInstallationNotFinished;
|
2022-05-14 02:54:40 +00:00
|
|
|
|
|
|
|
emit(TimerState(
|
|
|
|
dataState: dataState,
|
|
|
|
timerStart: DateTime.now(),
|
|
|
|
duration: delay,
|
|
|
|
isLoading: false,
|
|
|
|
));
|
|
|
|
timer = Timer(delay, work);
|
|
|
|
}
|
|
|
|
|
2022-05-18 11:21:11 +00:00
|
|
|
void submitDomainForAccessRecovery(String domain) async {
|
|
|
|
var serverDomain = ServerDomain(
|
|
|
|
domainName: domain,
|
2022-05-24 18:55:39 +00:00
|
|
|
provider: DnsProvider.unknown,
|
2022-05-18 11:21:11 +00:00
|
|
|
zoneId: '',
|
|
|
|
);
|
|
|
|
final recoveryCapabilities =
|
|
|
|
await repository.getRecoveryCapabilities(serverDomain);
|
|
|
|
|
2022-05-20 22:56:50 +00:00
|
|
|
await repository.saveDomain(serverDomain);
|
|
|
|
|
2022-05-18 11:21:11 +00:00
|
|
|
emit(ServerInstallationRecovery(
|
|
|
|
serverDomain: serverDomain,
|
|
|
|
recoveryCapabilities: recoveryCapabilities,
|
2022-05-24 18:55:39 +00:00
|
|
|
currentStep: RecoveryStep.selecting,
|
2022-05-18 11:21:11 +00:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
void tryToRecover(String token, ServerRecoveryMethods method) async {
|
2022-05-24 18:55:39 +00:00
|
|
|
final dataState = state as ServerInstallationRecovery;
|
2022-05-18 11:21:11 +00:00
|
|
|
final serverDomain = dataState.serverDomain;
|
|
|
|
if (serverDomain == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
Future<ServerHostingDetails> Function(ServerDomain, String)
|
|
|
|
recoveryFunction;
|
|
|
|
switch (method) {
|
|
|
|
case ServerRecoveryMethods.newDeviceKey:
|
|
|
|
recoveryFunction = repository.authorizeByNewDeviceKey;
|
|
|
|
break;
|
|
|
|
case ServerRecoveryMethods.recoveryKey:
|
|
|
|
recoveryFunction = repository.authorizeByRecoveryKey;
|
|
|
|
break;
|
|
|
|
case ServerRecoveryMethods.oldToken:
|
|
|
|
recoveryFunction = repository.authorizeByApiToken;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw Exception('Unknown recovery method');
|
|
|
|
}
|
|
|
|
final serverDetails = await recoveryFunction(
|
|
|
|
serverDomain,
|
|
|
|
token,
|
|
|
|
);
|
2022-05-20 22:56:50 +00:00
|
|
|
await repository.saveServerDetails(serverDetails);
|
2022-05-18 11:21:11 +00:00
|
|
|
emit(dataState.copyWith(
|
|
|
|
serverDetails: serverDetails,
|
2022-05-24 18:55:39 +00:00
|
|
|
currentStep: RecoveryStep.hetznerToken,
|
2022-05-18 11:21:11 +00:00
|
|
|
));
|
|
|
|
} on ServerAuthorizationException {
|
2022-05-20 22:56:50 +00:00
|
|
|
getIt<NavigationService>()
|
|
|
|
.showSnackBar('recovering.authorization_failed'.tr());
|
2022-05-18 11:21:11 +00:00
|
|
|
return;
|
|
|
|
} on IpNotFoundException {
|
2022-05-20 22:56:50 +00:00
|
|
|
getIt<NavigationService>()
|
|
|
|
.showSnackBar('recovering.domain_recover_error'.tr());
|
2022-05-18 11:21:11 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-19 14:26:57 +00:00
|
|
|
void revertRecoveryStep() {
|
2022-05-24 18:55:39 +00:00
|
|
|
final dataState = state as ServerInstallationRecovery;
|
2022-05-19 14:26:57 +00:00
|
|
|
switch (dataState.currentStep) {
|
2022-05-24 18:55:39 +00:00
|
|
|
case RecoveryStep.selecting:
|
2022-05-20 22:56:50 +00:00
|
|
|
repository.deleteDomain();
|
2022-05-24 18:55:39 +00:00
|
|
|
emit(const ServerInstallationEmpty());
|
2022-05-19 14:26:57 +00:00
|
|
|
break;
|
2022-05-24 18:55:39 +00:00
|
|
|
case RecoveryStep.recoveryKey:
|
|
|
|
case RecoveryStep.newDeviceKey:
|
|
|
|
case RecoveryStep.oldToken:
|
2022-05-19 14:26:57 +00:00
|
|
|
emit(dataState.copyWith(
|
2022-05-24 18:55:39 +00:00
|
|
|
currentStep: RecoveryStep.selecting,
|
2022-05-19 14:26:57 +00:00
|
|
|
));
|
|
|
|
break;
|
2022-05-24 18:55:39 +00:00
|
|
|
case RecoveryStep.serverSelection:
|
2022-05-20 22:56:50 +00:00
|
|
|
repository.deleteHetznerKey();
|
2022-05-19 17:43:25 +00:00
|
|
|
emit(dataState.copyWith(
|
2022-05-24 18:55:39 +00:00
|
|
|
currentStep: RecoveryStep.hetznerToken,
|
2022-05-19 17:43:25 +00:00
|
|
|
));
|
|
|
|
break;
|
2022-05-19 14:26:57 +00:00
|
|
|
// We won't revert steps after client is authorized
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void selectRecoveryMethod(ServerRecoveryMethods method) {
|
2022-05-24 18:55:39 +00:00
|
|
|
final dataState = state as ServerInstallationRecovery;
|
2022-05-19 14:26:57 +00:00
|
|
|
switch (method) {
|
|
|
|
case ServerRecoveryMethods.newDeviceKey:
|
|
|
|
emit(dataState.copyWith(
|
2022-05-24 18:55:39 +00:00
|
|
|
currentStep: RecoveryStep.newDeviceKey,
|
2022-05-19 14:26:57 +00:00
|
|
|
));
|
|
|
|
break;
|
|
|
|
case ServerRecoveryMethods.recoveryKey:
|
|
|
|
emit(dataState.copyWith(
|
2022-05-24 18:55:39 +00:00
|
|
|
currentStep: RecoveryStep.recoveryKey,
|
2022-05-19 14:26:57 +00:00
|
|
|
));
|
|
|
|
break;
|
|
|
|
case ServerRecoveryMethods.oldToken:
|
|
|
|
emit(dataState.copyWith(
|
2022-05-24 18:55:39 +00:00
|
|
|
currentStep: RecoveryStep.oldToken,
|
2022-05-19 14:26:57 +00:00
|
|
|
));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-20 22:56:50 +00:00
|
|
|
Future<List<ServerBasicInfoWithValidators>>
|
|
|
|
getServersOnHetznerAccount() async {
|
2022-05-24 18:55:39 +00:00
|
|
|
final dataState = state as ServerInstallationRecovery;
|
2022-05-20 22:56:50 +00:00
|
|
|
final servers = await repository.getServersOnHetznerAccount();
|
|
|
|
final validated = servers
|
|
|
|
.map((server) => ServerBasicInfoWithValidators.fromServerBasicInfo(
|
|
|
|
serverBasicInfo: server,
|
|
|
|
isIpValid: server.ip == dataState.serverDetails?.ip4,
|
|
|
|
isReverseDnsValid:
|
|
|
|
server.reverseDns == dataState.serverDomain?.domainName,
|
|
|
|
));
|
|
|
|
return validated.toList();
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> setServerId(ServerBasicInfo server) async {
|
2022-05-24 18:55:39 +00:00
|
|
|
final dataState = state as ServerInstallationRecovery;
|
2022-05-20 22:56:50 +00:00
|
|
|
final serverDomain = dataState.serverDomain;
|
|
|
|
if (serverDomain == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
final serverDetails = ServerHostingDetails(
|
|
|
|
ip4: server.ip,
|
|
|
|
id: server.id,
|
|
|
|
createTime: server.created,
|
|
|
|
volume: ServerVolume(
|
|
|
|
id: server.volumeId,
|
2022-05-24 18:55:39 +00:00
|
|
|
name: 'recovered_volume',
|
2022-05-20 22:56:50 +00:00
|
|
|
),
|
|
|
|
apiToken: dataState.serverDetails!.apiToken,
|
2022-05-24 18:55:39 +00:00
|
|
|
provider: ServerProvider.hetzner,
|
2022-05-20 22:56:50 +00:00
|
|
|
);
|
|
|
|
await repository.saveDomain(serverDomain);
|
|
|
|
await repository.saveServerDetails(serverDetails);
|
|
|
|
emit(dataState.copyWith(
|
|
|
|
serverDetails: serverDetails,
|
2022-05-24 18:55:39 +00:00
|
|
|
currentStep: RecoveryStep.cloudflareToken,
|
2022-05-20 22:56:50 +00:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2022-05-23 14:21:34 +00:00
|
|
|
Future<void> setAndValidateCloudflareToken(String token) async {
|
2022-05-24 18:55:39 +00:00
|
|
|
final dataState = state as ServerInstallationRecovery;
|
2022-05-23 14:21:34 +00:00
|
|
|
final serverDomain = dataState.serverDomain;
|
|
|
|
if (serverDomain == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
final zoneId = await repository.getDomainId(token, serverDomain.domainName);
|
|
|
|
if (zoneId == null) {
|
|
|
|
getIt<NavigationService>()
|
|
|
|
.showSnackBar('recovering.domain_not_available_on_token'.tr());
|
|
|
|
return;
|
|
|
|
}
|
2022-05-24 17:45:13 +00:00
|
|
|
await repository.saveDomain(ServerDomain(
|
|
|
|
domainName: serverDomain.domainName,
|
|
|
|
zoneId: zoneId,
|
2022-05-24 18:55:39 +00:00
|
|
|
provider: DnsProvider.cloudflare,
|
2022-05-24 17:45:13 +00:00
|
|
|
));
|
|
|
|
await repository.saveCloudFlareKey(token);
|
2022-05-23 14:21:34 +00:00
|
|
|
emit(dataState.copyWith(
|
|
|
|
serverDomain: ServerDomain(
|
|
|
|
domainName: serverDomain.domainName,
|
|
|
|
zoneId: zoneId,
|
2022-05-24 18:55:39 +00:00
|
|
|
provider: DnsProvider.cloudflare,
|
2022-05-23 14:21:34 +00:00
|
|
|
),
|
2022-05-24 17:45:13 +00:00
|
|
|
cloudFlareKey: token,
|
2022-05-24 18:55:39 +00:00
|
|
|
currentStep: RecoveryStep.backblazeToken,
|
2022-05-23 14:21:34 +00:00
|
|
|
));
|
|
|
|
}
|
2022-05-20 22:56:50 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
void onChange(Change<ServerInstallationState> change) {
|
|
|
|
super.onChange(change);
|
|
|
|
print('================================');
|
|
|
|
print('ServerInstallationState changed!');
|
|
|
|
print('Current type: ${change.nextState.runtimeType}');
|
|
|
|
print('Hetzner key: ${change.nextState.hetznerKey}');
|
|
|
|
print('Cloudflare key: ${change.nextState.cloudFlareKey}');
|
|
|
|
print('Domain: ${change.nextState.serverDomain}');
|
|
|
|
print('BackblazeCredential: ${change.nextState.backblazeCredential}');
|
|
|
|
if (change.nextState is ServerInstallationRecovery) {
|
|
|
|
print(
|
|
|
|
'Recovery Step: ${(change.nextState as ServerInstallationRecovery).currentStep}');
|
|
|
|
print(
|
|
|
|
'Recovery Capabilities: ${(change.nextState as ServerInstallationRecovery).recoveryCapabilities}');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-03 19:51:07 +00:00
|
|
|
void clearAppConfig() {
|
2021-03-30 17:38:40 +00:00
|
|
|
closeTimer();
|
2021-08-29 13:54:28 +00:00
|
|
|
|
2021-02-03 19:51:07 +00:00
|
|
|
repository.clearAppConfig();
|
2022-05-24 18:55:39 +00:00
|
|
|
emit(const ServerInstallationEmpty());
|
2021-01-06 17:35:57 +00:00
|
|
|
}
|
|
|
|
|
2021-04-22 18:04:24 +00:00
|
|
|
Future<void> serverDelete() async {
|
|
|
|
closeTimer();
|
2021-08-29 13:54:28 +00:00
|
|
|
|
2022-05-13 13:57:56 +00:00
|
|
|
if (state.serverDetails != null) {
|
|
|
|
await repository.deleteServer(state.serverDomain!);
|
2021-04-22 18:04:24 +00:00
|
|
|
}
|
|
|
|
await repository.deleteRecords();
|
2022-05-17 13:31:34 +00:00
|
|
|
emit(ServerInstallationNotFinished(
|
2021-10-11 21:10:04 +00:00
|
|
|
hetznerKey: state.hetznerKey,
|
2022-05-13 13:57:56 +00:00
|
|
|
serverDomain: state.serverDomain,
|
2021-10-11 21:10:04 +00:00
|
|
|
cloudFlareKey: state.cloudFlareKey,
|
|
|
|
backblazeCredential: state.backblazeCredential,
|
|
|
|
rootUser: state.rootUser,
|
2022-05-13 13:57:56 +00:00
|
|
|
serverDetails: null,
|
2021-10-11 21:10:04 +00:00
|
|
|
isServerStarted: false,
|
|
|
|
isServerResetedFirstTime: false,
|
|
|
|
isServerResetedSecondTime: false,
|
|
|
|
isLoading: false,
|
2022-02-08 06:59:19 +00:00
|
|
|
dnsMatches: null,
|
2021-10-11 21:10:04 +00:00
|
|
|
));
|
2021-04-22 18:04:24 +00:00
|
|
|
}
|
|
|
|
|
2022-05-24 18:55:39 +00:00
|
|
|
@override
|
2021-02-16 18:48:15 +00:00
|
|
|
close() {
|
2021-03-30 17:38:40 +00:00
|
|
|
closeTimer();
|
2021-02-16 18:48:15 +00:00
|
|
|
return super.close();
|
|
|
|
}
|
|
|
|
|
2021-03-30 17:38:40 +00:00
|
|
|
void closeTimer() {
|
2021-03-15 15:39:44 +00:00
|
|
|
if (timer != null && timer!.isActive) {
|
|
|
|
timer!.cancel();
|
2021-02-16 18:48:15 +00:00
|
|
|
}
|
2021-02-03 19:51:07 +00:00
|
|
|
}
|
2021-01-06 17:35:57 +00:00
|
|
|
}
|