2022-02-08 06:59:19 +00:00
|
|
|
import 'package:basic_utils/basic_utils.dart';
|
2021-02-15 18:58:29 +00:00
|
|
|
import 'package:dio/dio.dart';
|
2022-02-08 06:59:19 +00:00
|
|
|
import 'package:easy_localization/easy_localization.dart';
|
2021-01-21 07:35:38 +00:00
|
|
|
import 'package:hive/hive.dart';
|
2022-02-08 06:59:19 +00:00
|
|
|
import 'package:selfprivacy/config/get_it_config.dart';
|
2021-01-21 07:35:38 +00:00
|
|
|
import 'package:selfprivacy/config/hive_config.dart';
|
|
|
|
import 'package:selfprivacy/logic/api_maps/cloudflare.dart';
|
|
|
|
import 'package:selfprivacy/logic/api_maps/hetzner.dart';
|
2021-01-21 21:01:42 +00:00
|
|
|
import 'package:selfprivacy/logic/api_maps/server.dart';
|
2021-02-03 20:26:38 +00:00
|
|
|
import 'package:selfprivacy/logic/models/backblaze_credential.dart';
|
2021-01-21 07:35:38 +00:00
|
|
|
import 'package:selfprivacy/logic/models/cloudflare_domain.dart';
|
2022-02-08 06:59:19 +00:00
|
|
|
import 'package:selfprivacy/logic/models/message.dart';
|
2021-01-21 07:35:38 +00:00
|
|
|
import 'package:selfprivacy/logic/models/server_details.dart';
|
|
|
|
import 'package:selfprivacy/logic/models/user.dart';
|
2021-02-15 18:58:29 +00:00
|
|
|
import 'package:selfprivacy/ui/components/action_button/action_button.dart';
|
|
|
|
import 'package:selfprivacy/ui/components/brand_alert/brand_alert.dart';
|
2022-02-08 06:59:19 +00:00
|
|
|
|
2021-01-21 07:35:38 +00:00
|
|
|
import 'app_config_cubit.dart';
|
|
|
|
|
|
|
|
class AppConfigRepository {
|
|
|
|
Box box = Hive.box(BNames.appConfig);
|
|
|
|
|
2021-03-31 14:33:58 +00:00
|
|
|
Future<AppConfigState> load() async {
|
2021-09-29 13:08:19 +00:00
|
|
|
late AppConfigState res;
|
|
|
|
if (box.get(BNames.hasFinalChecked, defaultValue: false)) {
|
|
|
|
res = AppConfigFinished(
|
|
|
|
hetznerKey: getIt<ApiConfigModel>().hetznerKey!,
|
|
|
|
cloudFlareKey: getIt<ApiConfigModel>().cloudFlareKey!,
|
|
|
|
cloudFlareDomain: getIt<ApiConfigModel>().cloudFlareDomain!,
|
|
|
|
backblazeCredential: getIt<ApiConfigModel>().backblazeCredential!,
|
|
|
|
hetznerServer: getIt<ApiConfigModel>().hetznerServer!,
|
|
|
|
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 {
|
|
|
|
res = AppConfigNotFinished(
|
|
|
|
hetznerKey: getIt<ApiConfigModel>().hetznerKey,
|
|
|
|
cloudFlareKey: getIt<ApiConfigModel>().cloudFlareKey,
|
|
|
|
cloudFlareDomain: getIt<ApiConfigModel>().cloudFlareDomain,
|
|
|
|
backblazeCredential: getIt<ApiConfigModel>().backblazeCredential,
|
|
|
|
hetznerServer: getIt<ApiConfigModel>().hetznerServer,
|
|
|
|
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),
|
2022-02-08 06:59:19 +00:00
|
|
|
dnsMatches: null,
|
2021-09-29 13:08:19 +00:00
|
|
|
);
|
|
|
|
}
|
2021-03-25 23:30:34 +00:00
|
|
|
|
|
|
|
return res;
|
2021-01-21 07:35:38 +00:00
|
|
|
}
|
|
|
|
|
2021-02-03 19:51:07 +00:00
|
|
|
void clearAppConfig() {
|
2021-01-21 07:35:38 +00:00
|
|
|
box.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<HetznerServerDetails> startServer(
|
|
|
|
HetznerServerDetails hetznerServer,
|
|
|
|
) async {
|
2021-03-25 23:30:34 +00:00
|
|
|
var hetznerApi = HetznerApi();
|
2021-03-31 14:33:58 +00:00
|
|
|
var serverDetails = await hetznerApi.powerOn();
|
2021-01-21 07:35:38 +00:00
|
|
|
|
|
|
|
return serverDetails;
|
|
|
|
}
|
|
|
|
|
2022-02-08 06:59:19 +00:00
|
|
|
Future<Map<String, bool>> isDnsAddressesMatch(String? domainName, String? ip4,
|
|
|
|
Map<String, bool>? skippedMatches) async {
|
2021-01-21 07:35:38 +00:00
|
|
|
var addresses = <String>[
|
|
|
|
'$domainName',
|
|
|
|
'api.$domainName',
|
|
|
|
'cloud.$domainName',
|
|
|
|
'meet.$domainName',
|
|
|
|
'password.$domainName'
|
|
|
|
];
|
|
|
|
|
2022-02-08 06:59:19 +00:00
|
|
|
var matches = <String, bool>{};
|
|
|
|
|
2021-01-21 07:35:38 +00:00
|
|
|
for (var address in addresses) {
|
2022-02-08 06:59:19 +00:00
|
|
|
if (skippedMatches != null && skippedMatches[address] == true) {
|
|
|
|
matches[address] = true;
|
|
|
|
continue;
|
|
|
|
}
|
2021-01-21 07:35:38 +00:00
|
|
|
var lookupRecordRes = await DnsUtils.lookupRecord(
|
|
|
|
address,
|
|
|
|
RRecordType.A,
|
|
|
|
provider: DnsApiProvider.CLOUDFLARE,
|
|
|
|
);
|
|
|
|
getIt.get<ConsoleModel>().addMessage(
|
|
|
|
Message(
|
|
|
|
text:
|
|
|
|
'DnsLookup: address: $address, $RRecordType, provider: CLOUDFLARE, ip4: $ip4',
|
|
|
|
),
|
|
|
|
);
|
|
|
|
getIt.get<ConsoleModel>().addMessage(
|
|
|
|
Message(
|
|
|
|
text:
|
2021-01-27 18:33:00 +00:00
|
|
|
'DnsLookup: ${lookupRecordRes == null ? 'empty' : (lookupRecordRes[0].data != ip4 ? 'wrong ip4' : 'right ip4')}',
|
2021-01-21 07:35:38 +00:00
|
|
|
),
|
|
|
|
);
|
2021-01-27 18:33:00 +00:00
|
|
|
if (lookupRecordRes == null ||
|
|
|
|
lookupRecordRes.isEmpty ||
|
|
|
|
lookupRecordRes[0].data != ip4) {
|
2022-02-08 06:59:19 +00:00
|
|
|
matches[address] = false;
|
|
|
|
} else {
|
|
|
|
matches[address] = true;
|
2021-01-21 07:35:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-08 06:59:19 +00:00
|
|
|
return matches;
|
2021-01-21 07:35:38 +00:00
|
|
|
}
|
|
|
|
|
2021-02-15 18:58:29 +00:00
|
|
|
Future<void> createServer(
|
|
|
|
User rootUser,
|
2021-03-25 23:30:34 +00:00
|
|
|
String domainName,
|
2021-11-18 19:10:40 +00:00
|
|
|
String cloudFlareKey,
|
|
|
|
BackblazeCredential backblazeCredential, {
|
2021-03-25 23:30:34 +00:00
|
|
|
required void Function() onCancel,
|
2021-03-23 19:21:42 +00:00
|
|
|
required Future<void> Function(HetznerServerDetails serverDetails)
|
|
|
|
onSuccess,
|
2021-02-15 18:58:29 +00:00
|
|
|
}) async {
|
2021-03-25 23:30:34 +00:00
|
|
|
var hetznerApi = HetznerApi();
|
2021-10-11 21:10:04 +00:00
|
|
|
late HetznerDataBase dataBase;
|
2021-01-21 07:35:38 +00:00
|
|
|
|
2021-02-15 18:58:29 +00:00
|
|
|
try {
|
2021-10-11 21:10:04 +00:00
|
|
|
dataBase = await hetznerApi.createVolume();
|
|
|
|
|
2021-02-15 18:58:29 +00:00
|
|
|
var serverDetails = await hetznerApi.createServer(
|
|
|
|
cloudFlareKey: cloudFlareKey,
|
|
|
|
rootUser: rootUser,
|
|
|
|
domainName: domainName,
|
2021-10-11 21:10:04 +00:00
|
|
|
dataBase: dataBase,
|
2021-02-15 18:58:29 +00:00
|
|
|
);
|
2021-03-25 08:32:00 +00:00
|
|
|
saveServerDetails(serverDetails);
|
2021-02-15 18:58:29 +00:00
|
|
|
onSuccess(serverDetails);
|
|
|
|
} on DioError catch (e) {
|
2021-03-15 15:39:44 +00:00
|
|
|
if (e.response!.data['error']['code'] == 'uniqueness_error') {
|
2021-02-15 18:58:29 +00:00
|
|
|
var nav = getIt.get<NavigationService>();
|
|
|
|
nav.showPopUpDialog(
|
|
|
|
BrandAlert(
|
2021-03-23 19:21:42 +00:00
|
|
|
title: 'modals.1'.tr(),
|
|
|
|
contentText: 'modals.2'.tr(),
|
2021-12-06 18:31:19 +00:00
|
|
|
actions: [
|
2021-02-15 18:58:29 +00:00
|
|
|
ActionButton(
|
2021-03-23 20:00:17 +00:00
|
|
|
text: 'basis.delete'.tr(),
|
2021-02-15 18:58:29 +00:00
|
|
|
isRed: true,
|
|
|
|
onPressed: () async {
|
2021-03-31 11:37:39 +00:00
|
|
|
await hetznerApi.deleteSelfprivacyServerAndAllVolumes(
|
|
|
|
domainName: domainName);
|
2021-02-15 18:58:29 +00:00
|
|
|
|
|
|
|
var serverDetails = await hetznerApi.createServer(
|
|
|
|
cloudFlareKey: cloudFlareKey,
|
|
|
|
rootUser: rootUser,
|
|
|
|
domainName: domainName,
|
2021-10-11 21:10:04 +00:00
|
|
|
dataBase: dataBase,
|
2021-02-15 18:58:29 +00:00
|
|
|
);
|
|
|
|
|
2021-03-25 08:32:00 +00:00
|
|
|
await saveServerDetails(serverDetails);
|
2021-02-15 18:58:29 +00:00
|
|
|
onSuccess(serverDetails);
|
|
|
|
},
|
|
|
|
),
|
|
|
|
ActionButton(
|
2021-03-23 20:00:17 +00:00
|
|
|
text: 'basis.cancel'.tr(),
|
2021-02-15 18:58:29 +00:00
|
|
|
onPressed: () {
|
2021-03-25 23:30:34 +00:00
|
|
|
onCancel();
|
2021-02-15 18:58:29 +00:00
|
|
|
},
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2021-01-21 07:35:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> createDnsRecords(
|
2021-05-17 12:38:38 +00:00
|
|
|
String ip4,
|
2021-01-21 07:35:38 +00:00
|
|
|
CloudFlareDomain cloudFlareDomain,
|
|
|
|
) async {
|
2021-03-25 23:30:34 +00:00
|
|
|
var cloudflareApi = CloudflareApi();
|
2021-01-21 07:35:38 +00:00
|
|
|
|
2021-01-27 18:33:00 +00:00
|
|
|
await cloudflareApi.removeSimilarRecords(
|
|
|
|
ip4: ip4,
|
|
|
|
cloudFlareDomain: cloudFlareDomain,
|
|
|
|
);
|
|
|
|
|
2021-01-21 07:35:38 +00:00
|
|
|
await cloudflareApi.createMultipleDnsRecords(
|
|
|
|
ip4: ip4,
|
|
|
|
cloudFlareDomain: cloudFlareDomain,
|
|
|
|
);
|
2021-05-17 12:38:38 +00:00
|
|
|
|
|
|
|
await HetznerApi().createReverseDns(
|
|
|
|
ip4: ip4,
|
2021-05-17 12:40:06 +00:00
|
|
|
domainName: cloudFlareDomain.domainName,
|
2021-05-17 12:38:38 +00:00
|
|
|
);
|
2021-01-21 21:01:42 +00:00
|
|
|
}
|
|
|
|
|
2022-02-01 01:56:05 +00:00
|
|
|
Future<void> createDkimRecord(CloudFlareDomain cloudFlareDomain) async {
|
|
|
|
var cloudflareApi = CloudflareApi();
|
|
|
|
var api = ServerApi();
|
|
|
|
|
|
|
|
var dkimRecordString = await api.getDkim();
|
|
|
|
|
|
|
|
await cloudflareApi.setDkim(dkimRecordString, cloudFlareDomain);
|
|
|
|
}
|
|
|
|
|
2021-03-25 23:30:34 +00:00
|
|
|
Future<bool> isHttpServerWorking() async {
|
|
|
|
var api = ServerApi();
|
2021-01-21 21:01:42 +00:00
|
|
|
var isHttpServerWorking = await api.isHttpServerWorking();
|
2022-02-01 01:56:05 +00:00
|
|
|
try {
|
|
|
|
await api.getDkim();
|
|
|
|
} catch (e) {
|
|
|
|
return false;
|
|
|
|
}
|
2021-01-21 21:01:42 +00:00
|
|
|
return isHttpServerWorking;
|
|
|
|
}
|
|
|
|
|
2021-03-31 14:33:58 +00:00
|
|
|
Future<HetznerServerDetails> restart() async {
|
|
|
|
var hetznerApi = HetznerApi();
|
|
|
|
return await hetznerApi.reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<HetznerServerDetails> powerOn() async {
|
2021-03-25 23:30:34 +00:00
|
|
|
var hetznerApi = HetznerApi();
|
2021-03-31 14:33:58 +00:00
|
|
|
return await hetznerApi.powerOn();
|
2021-02-03 19:51:07 +00:00
|
|
|
}
|
2021-03-25 08:32:00 +00:00
|
|
|
|
|
|
|
Future<void> saveServerDetails(HetznerServerDetails serverDetails) async {
|
2021-03-25 20:09:56 +00:00
|
|
|
await getIt<ApiConfigModel>().storeServerDetails(serverDetails);
|
2021-03-25 08:32:00 +00:00
|
|
|
}
|
|
|
|
|
2021-03-25 20:09:56 +00:00
|
|
|
Future<void> saveHetznerKey(String key) async {
|
2021-10-13 21:49:24 +00:00
|
|
|
print('saved');
|
2021-03-25 20:09:56 +00:00
|
|
|
await getIt<ApiConfigModel>().storeHetznerKey(key);
|
2021-03-25 08:32:00 +00:00
|
|
|
}
|
|
|
|
|
2021-03-25 20:09:56 +00:00
|
|
|
Future<void> saveBackblazeKey(BackblazeCredential backblazeCredential) async {
|
|
|
|
await getIt<ApiConfigModel>().storeBackblazeCredential(backblazeCredential);
|
2021-03-25 08:32:00 +00:00
|
|
|
}
|
|
|
|
|
2021-03-25 20:09:56 +00:00
|
|
|
Future<void> saveCloudFlareKey(String key) async {
|
|
|
|
await getIt<ApiConfigModel>().storeCloudFlareKey(key);
|
2021-03-25 08:32:00 +00:00
|
|
|
}
|
|
|
|
|
2021-03-25 20:09:56 +00:00
|
|
|
Future<void> saveDomain(CloudFlareDomain cloudFlareDomain) async {
|
|
|
|
await getIt<ApiConfigModel>().storeCloudFlareDomain(cloudFlareDomain);
|
2021-03-25 08:32:00 +00:00
|
|
|
}
|
|
|
|
|
2021-03-25 20:09:56 +00:00
|
|
|
Future<void> saveIsServerStarted(bool value) async {
|
|
|
|
await box.put(BNames.isServerStarted, value);
|
2021-03-25 08:32:00 +00:00
|
|
|
}
|
|
|
|
|
2021-03-31 11:37:39 +00:00
|
|
|
Future<void> saveIsServerResetedFirstTime(bool value) async {
|
|
|
|
await box.put(BNames.isServerResetedFirstTime, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> saveIsServerResetedSecondTime(bool value) async {
|
|
|
|
await box.put(BNames.isServerResetedSecondTime, value);
|
2021-03-25 08:32:00 +00:00
|
|
|
}
|
|
|
|
|
2021-03-31 14:33:58 +00:00
|
|
|
Future<void> saveRootUser(User rootUser) async {
|
2021-03-25 08:32:00 +00:00
|
|
|
await box.put(BNames.rootUser, rootUser);
|
|
|
|
}
|
|
|
|
|
2021-03-31 14:33:58 +00:00
|
|
|
Future<void> saveHasFinalChecked(bool value) async {
|
2021-03-25 08:32:00 +00:00
|
|
|
await box.put(BNames.hasFinalChecked, value);
|
|
|
|
}
|
2021-04-22 18:04:24 +00:00
|
|
|
|
|
|
|
Future<void> deleteServer(CloudFlareDomain cloudFlareDomain) async {
|
|
|
|
var hetznerApi = HetznerApi();
|
|
|
|
var cloudFlare = CloudflareApi();
|
|
|
|
|
2021-10-11 21:10:04 +00:00
|
|
|
await hetznerApi.deleteSelfprivacyServerAndAllVolumes(
|
2021-04-22 18:04:24 +00:00
|
|
|
domainName: cloudFlareDomain.domainName,
|
|
|
|
);
|
2021-10-11 21:10:04 +00:00
|
|
|
|
2021-10-13 21:49:24 +00:00
|
|
|
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.hetznerServer, null);
|
|
|
|
|
2021-10-11 21:10:04 +00:00
|
|
|
await cloudFlare.removeSimilarRecords(cloudFlareDomain: cloudFlareDomain);
|
2021-04-22 18:04:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> deleteRecords() async {
|
|
|
|
await box.deleteAll([
|
|
|
|
BNames.hetznerServer,
|
|
|
|
BNames.isServerStarted,
|
|
|
|
BNames.isServerResetedFirstTime,
|
|
|
|
BNames.isServerResetedSecondTime,
|
|
|
|
BNames.hasFinalChecked,
|
|
|
|
BNames.isLoading,
|
|
|
|
]);
|
|
|
|
getIt<ApiConfigModel>().init();
|
|
|
|
}
|
2021-01-21 07:35:38 +00:00
|
|
|
}
|