Refactor infrastructure: cubits and endpoints

Co-authored-by: Inex Code <inex.code@selfprivacy.org>
pull/90/head
NaiJi ✨ 2022-05-13 16:57:56 +03:00
parent 01b1f7462d
commit 4a42733d31
25 changed files with 569 additions and 571 deletions

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -5,7 +5,7 @@ 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/backblaze_bucket.dart'; import 'package:selfprivacy/logic/models/backblaze_bucket.dart';
import 'package:selfprivacy/logic/models/backblaze_credential.dart'; import 'package:selfprivacy/logic/models/backblaze_credential.dart';
import 'package:selfprivacy/logic/models/cloudflare_domain.dart'; import 'package:selfprivacy/logic/models/server_domain.dart';
import 'package:selfprivacy/logic/models/server_details.dart'; import 'package:selfprivacy/logic/models/server_details.dart';
import 'package:selfprivacy/logic/models/user.dart'; import 'package:selfprivacy/logic/models/user.dart';
@ -14,7 +14,7 @@ class HiveConfig {
await Hive.initFlutter(); await Hive.initFlutter();
Hive.registerAdapter(UserAdapter()); Hive.registerAdapter(UserAdapter());
Hive.registerAdapter(HetznerServerDetailsAdapter()); Hive.registerAdapter(HetznerServerDetailsAdapter());
Hive.registerAdapter(CloudFlareDomainAdapter()); Hive.registerAdapter(ServerDomainAdapter());
Hive.registerAdapter(BackblazeCredentialAdapter()); Hive.registerAdapter(BackblazeCredentialAdapter());
Hive.registerAdapter(BackblazeBucketAdapter()); Hive.registerAdapter(BackblazeBucketAdapter());
Hive.registerAdapter(HetznerDataBaseAdapter()); Hive.registerAdapter(HetznerDataBaseAdapter());
@ -56,13 +56,14 @@ class BNames {
static String key = 'key'; static String key = 'key';
static String sshEnckey = 'sshEngkey'; static String sshEnckey = 'sshEngkey';
static String cloudFlareDomain = 'cloudFlareDomain'; static String hasFinalChecked = 'hasFinalChecked';
static String isServerStarted = 'isServerStarted';
static String serverDomain = 'cloudFlareDomain';
static String hetznerKey = 'hetznerKey'; static String hetznerKey = 'hetznerKey';
static String cloudFlareKey = 'cloudFlareKey'; static String cloudFlareKey = 'cloudFlareKey';
static String rootUser = 'rootUser'; static String rootUser = 'rootUser';
static String hetznerServer = 'hetznerServer'; static String serverDetails = 'hetznerServer';
static String hasFinalChecked = 'hasFinalChecked';
static String isServerStarted = 'isServerStarted';
static String backblazeKey = 'backblazeKey'; static String backblazeKey = 'backblazeKey';
static String backblazeBucket = 'backblazeBucket'; static String backblazeBucket = 'backblazeBucket';
static String isLoading = 'isLoading'; static String isLoading = 'isLoading';
@ -71,5 +72,4 @@ class BNames {
static String sshConfig = 'sshConfig'; static String sshConfig = 'sshConfig';
static String sshPrivateKey = "sshPrivateKey"; static String sshPrivateKey = "sshPrivateKey";
static String sshPublicKey = "sshPublicKey"; static String sshPublicKey = "sshPublicKey";
static String serverDomain = "serverDomain";
} }

View File

@ -3,7 +3,7 @@ import 'dart:io';
import 'package:dio/dio.dart'; 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/api_map.dart'; import 'package:selfprivacy/logic/api_maps/api_map.dart';
import 'package:selfprivacy/logic/models/cloudflare_domain.dart'; import 'package:selfprivacy/logic/models/server_domain.dart';
import 'package:selfprivacy/logic/models/dns_records.dart'; import 'package:selfprivacy/logic/models/dns_records.dart';
class CloudflareApi extends ApiMap { class CloudflareApi extends ApiMap {
@ -63,7 +63,7 @@ class CloudflareApi extends ApiMap {
Future<void> removeSimilarRecords({ Future<void> removeSimilarRecords({
String? ip4, String? ip4,
required CloudFlareDomain cloudFlareDomain, required ServerDomain cloudFlareDomain,
}) async { }) async {
var domainName = cloudFlareDomain.domainName; var domainName = cloudFlareDomain.domainName;
var domainZoneId = cloudFlareDomain.zoneId; var domainZoneId = cloudFlareDomain.zoneId;
@ -89,7 +89,7 @@ class CloudflareApi extends ApiMap {
} }
Future<List<DnsRecord>> getDnsRecords({ Future<List<DnsRecord>> getDnsRecords({
required CloudFlareDomain cloudFlareDomain, required ServerDomain cloudFlareDomain,
}) async { }) async {
var domainName = cloudFlareDomain.domainName; var domainName = cloudFlareDomain.domainName;
var domainZoneId = cloudFlareDomain.zoneId; var domainZoneId = cloudFlareDomain.zoneId;
@ -120,7 +120,7 @@ class CloudflareApi extends ApiMap {
Future<void> createMultipleDnsRecords({ Future<void> createMultipleDnsRecords({
String? ip4, String? ip4,
required CloudFlareDomain cloudFlareDomain, required ServerDomain cloudFlareDomain,
}) async { }) async {
var domainName = cloudFlareDomain.domainName; var domainName = cloudFlareDomain.domainName;
var domainZoneId = cloudFlareDomain.zoneId; var domainZoneId = cloudFlareDomain.zoneId;
@ -186,7 +186,7 @@ class CloudflareApi extends ApiMap {
} }
Future<void> setDkim( Future<void> setDkim(
String dkimRecordString, CloudFlareDomain cloudFlareDomain) async { String dkimRecordString, ServerDomain cloudFlareDomain) async {
final domainZoneId = cloudFlareDomain.zoneId; final domainZoneId = cloudFlareDomain.zoneId;
final url = '$rootAddress/zones/$domainZoneId/dns_records'; final url = '$rootAddress/zones/$domainZoneId/dns_records';

View File

@ -68,7 +68,7 @@ class HetznerApi extends ApiMap {
return server == null; return server == null;
} }
Future<HetznerDataBase> createVolume() async { Future<ServerVolume> createVolume() async {
var client = await getClient(); var client = await getClient();
Response dbCreateResponse = await client.post( Response dbCreateResponse = await client.post(
'/volumes', '/volumes',
@ -82,17 +82,17 @@ class HetznerApi extends ApiMap {
}, },
); );
var dbId = dbCreateResponse.data['volume']['id']; var dbId = dbCreateResponse.data['volume']['id'];
return HetznerDataBase( return ServerVolume(
id: dbId, id: dbId,
name: dbCreateResponse.data['volume']['name'], name: dbCreateResponse.data['volume']['name'],
); );
} }
Future<HetznerServerDetails> createServer({ Future<ServerHostingDetails> createServer({
required String cloudFlareKey, required String cloudFlareKey,
required User rootUser, required User rootUser,
required String domainName, required String domainName,
required HetznerDataBase dataBase, required ServerVolume dataBase,
}) async { }) async {
var client = await getClient(); var client = await getClient();
@ -136,7 +136,7 @@ class HetznerApi extends ApiMap {
print(serverCreateResponse.data); print(serverCreateResponse.data);
client.close(); client.close();
return HetznerServerDetails( return ServerHostingDetails(
id: serverCreateResponse.data['server']['id'], id: serverCreateResponse.data['server']['id'],
ip4: serverCreateResponse.data['server']['public_net']['ipv4']['ip'], ip4: serverCreateResponse.data['server']['public_net']['ipv4']['ip'],
createTime: DateTime.now(), createTime: DateTime.now(),
@ -189,8 +189,8 @@ class HetznerApi extends ApiMap {
close(client); close(client);
} }
Future<HetznerServerDetails> reset() async { Future<ServerHostingDetails> reset() async {
var server = getIt<ApiConfigModel>().hetznerServer!; var server = getIt<ApiConfigModel>().serverDetails!;
var client = await getClient(); var client = await getClient();
await client.post('/servers/${server.id}/actions/reset'); await client.post('/servers/${server.id}/actions/reset');
@ -199,8 +199,8 @@ class HetznerApi extends ApiMap {
return server.copyWith(startTime: DateTime.now()); return server.copyWith(startTime: DateTime.now());
} }
Future<HetznerServerDetails> powerOn() async { Future<ServerHostingDetails> powerOn() async {
var server = getIt<ApiConfigModel>().hetznerServer!; var server = getIt<ApiConfigModel>().serverDetails!;
var client = await getClient(); var client = await getClient();
await client.post('/servers/${server.id}/actions/poweron'); await client.post('/servers/${server.id}/actions/poweron');
@ -211,7 +211,7 @@ class HetznerApi extends ApiMap {
Future<Map<String, dynamic>> getMetrics( Future<Map<String, dynamic>> getMetrics(
DateTime start, DateTime end, String type) async { DateTime start, DateTime end, String type) async {
var hetznerServer = getIt<ApiConfigModel>().hetznerServer; var hetznerServer = getIt<ApiConfigModel>().serverDetails;
var client = await getClient(); var client = await getClient();
Map<String, dynamic> queryParameters = { Map<String, dynamic> queryParameters = {
@ -228,7 +228,7 @@ class HetznerApi extends ApiMap {
} }
Future<HetznerServerInfo> getInfo() async { Future<HetznerServerInfo> getInfo() async {
var hetznerServer = getIt<ApiConfigModel>().hetznerServer; var hetznerServer = getIt<ApiConfigModel>().serverDetails;
var client = await getClient(); var client = await getClient();
Response response = await client.get('/servers/${hetznerServer!.id}'); Response response = await client.get('/servers/${hetznerServer!.id}');
close(client); close(client);
@ -240,7 +240,7 @@ class HetznerApi extends ApiMap {
required String ip4, required String ip4,
required String domainName, required String domainName,
}) async { }) async {
var hetznerServer = getIt<ApiConfigModel>().hetznerServer; var hetznerServer = getIt<ApiConfigModel>().serverDetails;
var client = await getClient(); var client = await getClient();
await client.post( await client.post(
'/servers/${hetznerServer!.id}/actions/change_dns_ptr', '/servers/${hetznerServer!.id}/actions/change_dns_ptr',

View File

@ -33,65 +33,68 @@ class ApiResponse<D> {
class ServerApi extends ApiMap { class ServerApi extends ApiMap {
bool hasLogger; bool hasLogger;
bool isWithToken; bool isWithToken;
String? overrideDomain;
ServerApi({this.hasLogger = false, this.isWithToken = true}); ServerApi(
{this.hasLogger = false, this.isWithToken = true, this.overrideDomain});
BaseOptions get options { BaseOptions get options {
var options = BaseOptions(); var options = BaseOptions();
if (isWithToken) { if (isWithToken) {
var cloudFlareDomain = getIt<ApiConfigModel>().cloudFlareDomain; var cloudFlareDomain = getIt<ApiConfigModel>().serverDomain;
var domainName = cloudFlareDomain!.domainName; var domainName = cloudFlareDomain!.domainName;
var apiToken = getIt<ApiConfigModel>().hetznerServer?.apiToken; var apiToken = getIt<ApiConfigModel>().serverDetails?.apiToken;
options = BaseOptions(baseUrl: 'https://api.$domainName', headers: { options = BaseOptions(baseUrl: 'https://api.$domainName', headers: {
'Authorization': 'Bearer $apiToken', 'Authorization': 'Bearer $apiToken',
}); });
} }
if (overrideDomain != null) {
options = BaseOptions(baseUrl: 'https://api.$overrideDomain');
}
return options; return options;
} }
Future<String?> getApiVersion() async {
Response response;
var client = await getClient();
String? apiVersion = null;
try {
response = await client.get('/api/version');
apiVersion = response.data['version'];
} on DioError catch (e) {
print(e.message);
} finally {
close(client);
return apiVersion;
}
}
Future<bool> isHttpServerWorking() async { Future<bool> isHttpServerWorking() async {
bool res; bool res = false;
Response response; Response response;
var client = await getClient(); var client = await getClient();
try { try {
response = await client.get( response = await client.get('/services/status');
'/services/status',
options: Options(
contentType: 'application/json',
receiveDataWhenStatusError: true,
followRedirects: false,
validateStatus: (status) {
return (status != null) &&
(status < HttpStatus.internalServerError);
}),
);
res = response.statusCode == HttpStatus.ok; res = response.statusCode == HttpStatus.ok;
} catch (e) { } on DioError catch (e) {
res = false; print(e.message);
} finally {
close(client);
return res;
} }
close(client);
return res;
} }
Future<ApiResponse<User>> createUser(User user) async { Future<ApiResponse<User>> createUser(User user) async {
var client = await getClient(); var client = await getClient();
var makeErrorApiReponse = (int status) { Response response;
return ApiResponse(
statusCode: status,
data: User(
login: user.login,
password: user.password,
isFoundOnServer: false,
),
);
};
late Response<dynamic> response;
try { try {
response = await client.post( response = await client.post(
@ -100,68 +103,75 @@ class ServerApi extends ApiMap {
'username': user.login, 'username': user.login,
'password': user.password, 'password': user.password,
}, },
options: Options(
contentType: 'application/json',
receiveDataWhenStatusError: true,
followRedirects: false,
validateStatus: (status) {
return (status != null) &&
(status < HttpStatus.internalServerError);
}),
); );
} catch (e) { } on DioError catch (e) {
return makeErrorApiReponse(HttpStatus.internalServerError); print(e.message);
return ApiResponse(
errorMessage: e.error.toString(),
statusCode: e.response?.statusCode ?? HttpStatus.internalServerError,
data: User(
login: user.login,
password: user.password,
isFoundOnServer: false,
),
);
} finally { } finally {
close(client); close(client);
} }
if ((response.statusCode != null) && bool isFoundOnServer = false;
(response.statusCode == HttpStatus.created)) { int statusCode = 0;
return ApiResponse(
statusCode: response.statusCode!, final bool isUserCreated = (response.statusCode != null) &&
data: User( (response.statusCode == HttpStatus.created);
login: user.login,
password: user.password, if (isUserCreated) {
isFoundOnServer: true, isFoundOnServer = true;
), statusCode = response.statusCode!;
);
} else { } else {
print(response.statusCode.toString() + isFoundOnServer = false;
": " + statusCode = HttpStatus.notAcceptable;
(response.statusMessage ?? ""));
return makeErrorApiReponse(
response.statusCode ?? HttpStatus.internalServerError);
} }
return ApiResponse(
statusCode: statusCode,
data: User(
login: user.login,
password: user.password,
isFoundOnServer: isFoundOnServer,
),
);
} }
Future<ApiResponse<List<String>>> getUsersList() async { Future<ApiResponse<List<String>>> getUsersList() async {
List<String> res = []; List<String> res = [];
Response response; Response response;
String? message;
int code = 0;
var client = await getClient(); var client = await getClient();
response = await client.get(
'/users',
options: Options(
contentType: 'application/json',
receiveDataWhenStatusError: true,
followRedirects: false,
validateStatus: (status) {
return (status != null) &&
(status < HttpStatus.internalServerError);
}),
);
try { try {
response = await client.get('/users');
for (var user in response.data) { for (var user in response.data) {
res.add(user.toString()); res.add(user.toString());
} }
} on DioError catch (e) {
print(e.message);
message = e.message;
code = e.response?.statusCode ?? HttpStatus.internalServerError;
res = [];
} catch (e) { } catch (e) {
print(e); print(e);
message = e.toString();
code = HttpStatus.internalServerError;
res = []; res = [];
} finally {
close(client);
} }
close(client); return ApiResponse(
return ApiResponse<List<String>>( errorMessage: message,
statusCode: response.statusCode ?? HttpStatus.internalServerError, statusCode: code,
data: res, data: res,
); );
} }
@ -170,22 +180,23 @@ class ServerApi extends ApiMap {
Response response; Response response;
var client = await getClient(); var client = await getClient();
response = await client.post( try {
'/services/ssh/keys/${user.login}', response = await client.post(
data: { '/services/ssh/keys/${user.login}',
'public_key': sshKey, data: {
}, 'public_key': sshKey,
options: Options( },
contentType: 'application/json', );
receiveDataWhenStatusError: true, } on DioError catch (e) {
followRedirects: false, print(e.message);
validateStatus: (status) { return ApiResponse(
return (status != null) && data: null,
(status < HttpStatus.internalServerError); errorMessage: e.message,
}), statusCode: e.response?.statusCode ?? HttpStatus.internalServerError);
); } finally {
close(client);
}
close(client);
return ApiResponse<void>( return ApiResponse<void>(
statusCode: response.statusCode ?? HttpStatus.internalServerError, statusCode: response.statusCode ?? HttpStatus.internalServerError,
data: null, data: null,

View File

@ -5,7 +5,7 @@ import 'package:equatable/equatable.dart';
import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/config/get_it_config.dart';
import 'package:selfprivacy/logic/get_it/ssh.dart'; import 'package:selfprivacy/logic/get_it/ssh.dart';
import 'package:selfprivacy/logic/models/backblaze_credential.dart'; import 'package:selfprivacy/logic/models/backblaze_credential.dart';
import 'package:selfprivacy/logic/models/cloudflare_domain.dart'; import 'package:selfprivacy/logic/models/server_domain.dart';
import 'package:selfprivacy/logic/models/server_details.dart'; import 'package:selfprivacy/logic/models/server_details.dart';
import 'package:selfprivacy/logic/models/user.dart'; import 'package:selfprivacy/logic/models/user.dart';
@ -15,35 +15,6 @@ export 'package:provider/provider.dart';
part 'app_config_state.dart'; part 'app_config_state.dart';
/// Initializing steps:
///
/// The set phase.
/// 1.1. Hetzner key |setHetznerKey
/// 1.2. Cloudflare key |setCloudflareKey
/// 1.3. Backblaze Id + Key |setBackblazeKey
/// 1.4. Set Domain address |setDomain
/// 1.5. Set Root user name password |setRootUser
/// 1.6. Set Create server ans set DNS-Records |createServerAndSetDnsRecords
/// (without start)
///
/// The check phase.
///
/// 2.1. a. wait 60sec checkDnsAndStartServer |startServerIfDnsIsOkay
/// b. checkDns
/// c. if dns is okay start server
///
/// 2.2. a. wait 60sec |resetServerIfServerIsOkay
/// b. checkServer
/// c. if server is ok wait 30 sec
/// d. reset server
///
/// 2.3. a. wait 60sec |oneMoreReset()
/// d. reset server
///
/// 2.4. a. wait 30sec |finishCheckIfServerIsOkay
/// b. checkServer
/// c. if server is okay set that fully checked
class AppConfigCubit extends Cubit<AppConfigState> { class AppConfigCubit extends Cubit<AppConfigState> {
AppConfigCubit() : super(AppConfigEmpty()); AppConfigCubit() : super(AppConfigEmpty());
@ -55,180 +26,142 @@ class AppConfigCubit extends Cubit<AppConfigState> {
if (state is AppConfigFinished) { if (state is AppConfigFinished) {
emit(state); emit(state);
} else if (state is AppConfigNotFinished) { } else if (state is AppConfigNotFinished) {
if (state.progress == 6) { if (state.progress == ServerSetupProgress.serverCreated) {
startServerIfDnsIsOkay(state: state, isImmediate: true); startServerIfDnsIsOkay(state: state);
} else if (state.progress == 7) { } else if (state.progress == ServerSetupProgress.serverStarted) {
resetServerIfServerIsOkay(state: state, isImmediate: true); resetServerIfServerIsOkay(state: state);
} else if (state.progress == 8) { } else if (state.progress == ServerSetupProgress.serverResetedFirstTime) {
oneMoreReset(state: state, isImmediate: true); oneMoreReset(state: state);
} else if (state.progress == 9) { } else if (state.progress ==
finishCheckIfServerIsOkay(state: state, isImmediate: true); ServerSetupProgress.serverResetedSecondTime) {
finishCheckIfServerIsOkay(state: state);
} else { } else {
emit(state); emit(state);
} }
} else if (state is AppConfigRecovery) {
emit(state);
} else { } else {
throw 'wrong state'; throw 'wrong state';
} }
} }
void startServerIfDnsIsOkay({ void runDelayed(
AppConfigNotFinished? state, void Function() work, Duration delay, AppConfigNotFinished? state) async {
bool isImmediate = false, final dataState = state ?? this.state as AppConfigNotFinished;
}) async {
state = state ?? this.state as AppConfigNotFinished;
final work = () async { emit(TimerState(
emit(TimerState(dataState: state!, isLoading: true)); dataState: dataState,
timerStart: DateTime.now(),
duration: delay,
isLoading: false,
));
timer = Timer(delay, work);
}
var ip4 = state.hetznerServer!.ip4; void startServerIfDnsIsOkay({AppConfigNotFinished? state}) async {
var domainName = state.cloudFlareDomain!.domainName; final dataState = state ?? this.state as AppConfigNotFinished;
var matches = await repository.isDnsAddressesMatch( emit(TimerState(dataState: dataState, isLoading: true));
domainName, ip4, state.dnsMatches);
if (matches.values.every((value) => value)) { var ip4 = dataState.serverDetails!.ip4;
var server = await repository.startServer( var domainName = dataState.serverDomain!.domainName;
state.hetznerServer!,
);
await repository.saveServerDetails(server);
await repository.saveIsServerStarted(true);
emit( var matches = await repository.isDnsAddressesMatch(
state.copyWith( domainName, ip4, dataState.dnsMatches);
isServerStarted: true,
isLoading: false,
hetznerServer: server,
),
);
resetServerIfServerIsOkay();
} else {
emit(
state.copyWith(
isLoading: false,
dnsMatches: matches,
),
);
startServerIfDnsIsOkay();
}
};
if (isImmediate) { if (matches.values.every((value) => value)) {
work(); var server = await repository.startServer(
dataState.serverDetails!,
);
await repository.saveServerDetails(server);
await repository.saveIsServerStarted(true);
emit(
dataState.copyWith(
isServerStarted: true,
isLoading: false,
serverDetails: server,
),
);
runDelayed(resetServerIfServerIsOkay, Duration(seconds: 60), dataState);
} else { } else {
var pauseDuration = Duration(seconds: 30); emit(
emit(TimerState( dataState.copyWith(
dataState: state, isLoading: false,
timerStart: DateTime.now(), dnsMatches: matches,
duration: pauseDuration, ),
isLoading: false, );
)); runDelayed(startServerIfDnsIsOkay, Duration(seconds: 30), dataState);
timer = Timer(pauseDuration, work);
} }
} }
void oneMoreReset({ void oneMoreReset({AppConfigNotFinished? state}) async {
AppConfigNotFinished? state, final dataState = state ?? this.state as AppConfigNotFinished;
bool isImmediate = false,
}) async {
var dataState = state ?? this.state as AppConfigNotFinished;
var work = () async { emit(TimerState(dataState: dataState, isLoading: true));
emit(TimerState(dataState: dataState, isLoading: true));
var isServerWorking = await repository.isHttpServerWorking(); var isServerWorking = await repository.isHttpServerWorking();
if (isServerWorking) { if (isServerWorking) {
var pauseDuration = Duration(seconds: 30); var pauseDuration = Duration(seconds: 30);
emit(TimerState( emit(TimerState(
dataState: dataState, dataState: dataState,
timerStart: DateTime.now(), timerStart: DateTime.now(),
isLoading: false, isLoading: false,
duration: pauseDuration, duration: pauseDuration,
)); ));
timer = Timer(pauseDuration, () async { timer = Timer(pauseDuration, () async {
var hetznerServerDetails = await repository.restart(); var hetznerServerDetails = await repository.restart();
await repository.saveIsServerResetedSecondTime(true); await repository.saveIsServerResetedSecondTime(true);
await repository.saveServerDetails(hetznerServerDetails); await repository.saveServerDetails(hetznerServerDetails);
emit( emit(
dataState.copyWith( dataState.copyWith(
isServerResetedSecondTime: true, isServerResetedSecondTime: true,
hetznerServer: hetznerServerDetails, serverDetails: hetznerServerDetails,
isLoading: false, isLoading: false,
), ),
); );
finishCheckIfServerIsOkay(); runDelayed(finishCheckIfServerIsOkay, Duration(seconds: 60), dataState);
}); });
} else {
oneMoreReset();
}
};
if (isImmediate) {
work();
} else { } else {
var pauseDuration = Duration(seconds: 60); runDelayed(oneMoreReset, Duration(seconds: 60), dataState);
emit(
TimerState(
dataState: dataState,
timerStart: DateTime.now(),
duration: pauseDuration,
isLoading: false,
),
);
timer = Timer(pauseDuration, work);
} }
} }
void resetServerIfServerIsOkay({ void resetServerIfServerIsOkay({
AppConfigNotFinished? state, AppConfigNotFinished? state,
bool isImmediate = false,
}) async { }) async {
var dataState = state ?? this.state as AppConfigNotFinished; final dataState = state ?? this.state as AppConfigNotFinished;
var work = () async { emit(TimerState(dataState: dataState, isLoading: true));
emit(TimerState(dataState: dataState, isLoading: true));
var isServerWorking = await repository.isHttpServerWorking(); var isServerWorking = await repository.isHttpServerWorking();
if (isServerWorking) { if (isServerWorking) {
var pauseDuration = Duration(seconds: 30); var pauseDuration = Duration(seconds: 30);
emit(TimerState( emit(TimerState(
dataState: dataState, dataState: dataState,
timerStart: DateTime.now(), timerStart: DateTime.now(),
isLoading: false, isLoading: false,
duration: pauseDuration, duration: pauseDuration,
)); ));
timer = Timer(pauseDuration, () async { timer = Timer(pauseDuration, () async {
var hetznerServerDetails = await repository.restart(); var hetznerServerDetails = await repository.restart();
await repository.saveIsServerResetedFirstTime(true); await repository.saveIsServerResetedFirstTime(true);
await repository.saveServerDetails(hetznerServerDetails); await repository.saveServerDetails(hetznerServerDetails);
emit( emit(
dataState.copyWith( dataState.copyWith(
isServerResetedFirstTime: true, isServerResetedFirstTime: true,
hetznerServer: hetznerServerDetails, serverDetails: hetznerServerDetails,
isLoading: false, isLoading: false,
), ),
); );
oneMoreReset(); runDelayed(oneMoreReset, Duration(seconds: 60), dataState);
}); });
} else {
resetServerIfServerIsOkay();
}
};
if (isImmediate) {
work();
} else { } else {
var pauseDuration = Duration(seconds: 60); runDelayed(resetServerIfServerIsOkay, Duration(seconds: 60), dataState);
emit(
TimerState(
dataState: dataState,
timerStart: DateTime.now(),
duration: pauseDuration,
isLoading: false,
),
);
timer = Timer(pauseDuration, work);
} }
} }
@ -236,37 +169,20 @@ class AppConfigCubit extends Cubit<AppConfigState> {
void finishCheckIfServerIsOkay({ void finishCheckIfServerIsOkay({
AppConfigNotFinished? state, AppConfigNotFinished? state,
bool isImmediate = false,
}) async { }) async {
state = state ?? this.state as AppConfigNotFinished; final dataState = state ?? this.state as AppConfigNotFinished;
var work = () async { emit(TimerState(dataState: dataState, isLoading: true));
emit(TimerState(dataState: state!, isLoading: true));
var isServerWorking = await repository.isHttpServerWorking(); var isServerWorking = await repository.isHttpServerWorking();
if (isServerWorking) { if (isServerWorking) {
await repository.createDkimRecord(state.cloudFlareDomain!); await repository.createDkimRecord(dataState.serverDomain!);
await repository.saveHasFinalChecked(true); await repository.saveHasFinalChecked(true);
emit(state.finish()); emit(dataState.finish());
} else {
finishCheckIfServerIsOkay();
}
};
if (isImmediate) {
work();
} else { } else {
var pauseDuration = Duration(seconds: 60); runDelayed(finishCheckIfServerIsOkay, Duration(seconds: 60), dataState);
emit(
TimerState(
dataState: state,
timerStart: DateTime.now(),
duration: pauseDuration,
isLoading: false,
),
);
timer = Timer(pauseDuration, work);
} }
} }
@ -280,18 +196,18 @@ class AppConfigCubit extends Cubit<AppConfigState> {
Future<void> serverDelete() async { Future<void> serverDelete() async {
closeTimer(); closeTimer();
if (state.hetznerServer != null) { if (state.serverDetails != null) {
await repository.deleteServer(state.cloudFlareDomain!); await repository.deleteServer(state.serverDomain!);
await getIt<SSHModel>().clear(); await getIt<SSHModel>().clear();
} }
await repository.deleteRecords(); await repository.deleteRecords();
emit(AppConfigNotFinished( emit(AppConfigNotFinished(
hetznerKey: state.hetznerKey, hetznerKey: state.hetznerKey,
cloudFlareDomain: state.cloudFlareDomain, serverDomain: state.serverDomain,
cloudFlareKey: state.cloudFlareKey, cloudFlareKey: state.cloudFlareKey,
backblazeCredential: state.backblazeCredential, backblazeCredential: state.backblazeCredential,
rootUser: state.rootUser, rootUser: state.rootUser,
hetznerServer: null, serverDetails: null,
isServerStarted: false, isServerStarted: false,
isServerResetedFirstTime: false, isServerResetedFirstTime: false,
isServerResetedSecondTime: false, isServerResetedSecondTime: false,
@ -321,10 +237,9 @@ class AppConfigCubit extends Cubit<AppConfigState> {
.copyWith(backblazeCredential: backblazeCredential)); .copyWith(backblazeCredential: backblazeCredential));
} }
void setDomain(CloudFlareDomain cloudFlareDomain) async { void setDomain(ServerDomain serverDomain) async {
await repository.saveDomain(cloudFlareDomain); await repository.saveDomain(serverDomain);
emit((state as AppConfigNotFinished) emit((state as AppConfigNotFinished).copyWith(serverDomain: serverDomain));
.copyWith(cloudFlareDomain: cloudFlareDomain));
} }
void setRootUser(User rootUser) async { void setRootUser(User rootUser) async {
@ -334,17 +249,17 @@ class AppConfigCubit extends Cubit<AppConfigState> {
void createServerAndSetDnsRecords() async { void createServerAndSetDnsRecords() async {
AppConfigNotFinished _stateCopy = state as AppConfigNotFinished; AppConfigNotFinished _stateCopy = state as AppConfigNotFinished;
var onSuccess = (HetznerServerDetails serverDetails) async { var onSuccess = (ServerHostingDetails serverDetails) async {
await repository.createDnsRecords( await repository.createDnsRecords(
serverDetails.ip4, serverDetails.ip4,
state.cloudFlareDomain!, state.serverDomain!,
); );
emit((state as AppConfigNotFinished).copyWith( emit((state as AppConfigNotFinished).copyWith(
isLoading: false, isLoading: false,
hetznerServer: serverDetails, serverDetails: serverDetails,
)); ));
startServerIfDnsIsOkay(); runDelayed(startServerIfDnsIsOkay, Duration(seconds: 30), null);
}; };
var onCancel = var onCancel =
@ -354,7 +269,7 @@ class AppConfigCubit extends Cubit<AppConfigState> {
emit((state as AppConfigNotFinished).copyWith(isLoading: true)); emit((state as AppConfigNotFinished).copyWith(isLoading: true));
await repository.createServer( await repository.createServer(
state.rootUser!, state.rootUser!,
state.cloudFlareDomain!.domainName, state.serverDomain!.domainName,
state.cloudFlareKey!, state.cloudFlareKey!,
state.backblazeCredential!, state.backblazeCredential!,
onCancel: onCancel, onCancel: onCancel,

View File

@ -8,7 +8,7 @@ import 'package:selfprivacy/logic/api_maps/cloudflare.dart';
import 'package:selfprivacy/logic/api_maps/hetzner.dart'; import 'package:selfprivacy/logic/api_maps/hetzner.dart';
import 'package:selfprivacy/logic/api_maps/server.dart'; import 'package:selfprivacy/logic/api_maps/server.dart';
import 'package:selfprivacy/logic/models/backblaze_credential.dart'; import 'package:selfprivacy/logic/models/backblaze_credential.dart';
import 'package:selfprivacy/logic/models/cloudflare_domain.dart'; import 'package:selfprivacy/logic/models/server_domain.dart';
import 'package:selfprivacy/logic/models/message.dart'; import 'package:selfprivacy/logic/models/message.dart';
import 'package:selfprivacy/logic/models/server_details.dart'; import 'package:selfprivacy/logic/models/server_details.dart';
import 'package:selfprivacy/logic/models/user.dart'; import 'package:selfprivacy/logic/models/user.dart';
@ -21,14 +21,19 @@ class AppConfigRepository {
Box box = Hive.box(BNames.appConfig); Box box = Hive.box(BNames.appConfig);
Future<AppConfigState> load() async { Future<AppConfigState> load() async {
late AppConfigState res; final hetznerToken = getIt<ApiConfigModel>().hetznerKey;
final cloudflareToken = getIt<ApiConfigModel>().cloudFlareKey;
final serverDomain = getIt<ApiConfigModel>().serverDomain;
final backblazeCredential = getIt<ApiConfigModel>().backblazeCredential;
final serverDetails = getIt<ApiConfigModel>().serverDetails;
if (box.get(BNames.hasFinalChecked, defaultValue: false)) { if (box.get(BNames.hasFinalChecked, defaultValue: false)) {
res = AppConfigFinished( return AppConfigFinished(
hetznerKey: getIt<ApiConfigModel>().hetznerKey!, hetznerKey: hetznerToken!,
cloudFlareKey: getIt<ApiConfigModel>().cloudFlareKey!, cloudFlareKey: cloudflareToken!,
cloudFlareDomain: getIt<ApiConfigModel>().cloudFlareDomain!, serverDomain: serverDomain!,
backblazeCredential: getIt<ApiConfigModel>().backblazeCredential!, backblazeCredential: backblazeCredential!,
hetznerServer: getIt<ApiConfigModel>().hetznerServer!, serverDetails: serverDetails!,
rootUser: box.get(BNames.rootUser), rootUser: box.get(BNames.rootUser),
isServerStarted: box.get(BNames.isServerStarted, defaultValue: false), isServerStarted: box.get(BNames.isServerStarted, defaultValue: false),
isServerResetedFirstTime: isServerResetedFirstTime:
@ -36,33 +41,62 @@ class AppConfigRepository {
isServerResetedSecondTime: isServerResetedSecondTime:
box.get(BNames.isServerResetedSecondTime, defaultValue: false), 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),
dnsMatches: null,
);
} }
return res; if (getIt<ApiConfigModel>().serverDomain?.provider == DnsProvider.Unknown) {
return AppConfigRecovery(
hetznerKey: hetznerToken,
cloudFlareKey: cloudflareToken,
serverDomain: serverDomain,
backblazeCredential: backblazeCredential,
serverDetails: serverDetails,
rootUser: box.get(BNames.rootUser),
currentStep: getCurrentRecoveryStep(
hetznerToken, cloudflareToken, serverDomain!, serverDetails),
);
}
return AppConfigNotFinished(
hetznerKey: hetznerToken,
cloudFlareKey: cloudflareToken,
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),
isLoading: box.get(BNames.isLoading, defaultValue: false),
dnsMatches: null,
);
}
RecoveryStep getCurrentRecoveryStep(
String? hetznerToken,
String? cloudflareToken,
ServerDomain serverDomain,
ServerHostingDetails? serverDetails,
) {
if (serverDetails != null) {
if (hetznerToken != null) {
if (cloudflareToken != null) {
return RecoveryStep.BackblazeToken;
}
return RecoveryStep.CloudflareToken;
}
return RecoveryStep.HetznerToken;
}
return RecoveryStep.Selecting;
} }
void clearAppConfig() { void clearAppConfig() {
box.clear(); box.clear();
} }
Future<HetznerServerDetails> startServer( Future<ServerHostingDetails> startServer(
HetznerServerDetails hetznerServer, ServerHostingDetails hetznerServer,
) async { ) async {
var hetznerApi = HetznerApi(); var hetznerApi = HetznerApi();
var serverDetails = await hetznerApi.powerOn(); var serverDetails = await hetznerApi.powerOn();
@ -122,11 +156,11 @@ class AppConfigRepository {
String cloudFlareKey, String cloudFlareKey,
BackblazeCredential backblazeCredential, { BackblazeCredential backblazeCredential, {
required void Function() onCancel, required void Function() onCancel,
required Future<void> Function(HetznerServerDetails serverDetails) required Future<void> Function(ServerHostingDetails serverDetails)
onSuccess, onSuccess,
}) async { }) async {
var hetznerApi = HetznerApi(); var hetznerApi = HetznerApi();
late HetznerDataBase dataBase; late ServerVolume dataBase;
try { try {
dataBase = await hetznerApi.createVolume(); dataBase = await hetznerApi.createVolume();
@ -180,7 +214,7 @@ class AppConfigRepository {
Future<void> createDnsRecords( Future<void> createDnsRecords(
String ip4, String ip4,
CloudFlareDomain cloudFlareDomain, ServerDomain cloudFlareDomain,
) async { ) async {
var cloudflareApi = CloudflareApi(); var cloudflareApi = CloudflareApi();
@ -200,7 +234,7 @@ class AppConfigRepository {
); );
} }
Future<void> createDkimRecord(CloudFlareDomain cloudFlareDomain) async { Future<void> createDkimRecord(ServerDomain cloudFlareDomain) async {
var cloudflareApi = CloudflareApi(); var cloudflareApi = CloudflareApi();
var api = ServerApi(); var api = ServerApi();
@ -220,17 +254,17 @@ class AppConfigRepository {
return isHttpServerWorking; return isHttpServerWorking;
} }
Future<HetznerServerDetails> restart() async { Future<ServerHostingDetails> restart() async {
var hetznerApi = HetznerApi(); var hetznerApi = HetznerApi();
return await hetznerApi.reset(); return await hetznerApi.reset();
} }
Future<HetznerServerDetails> powerOn() async { Future<ServerHostingDetails> powerOn() async {
var hetznerApi = HetznerApi(); var hetznerApi = HetznerApi();
return await hetznerApi.powerOn(); return await hetznerApi.powerOn();
} }
Future<void> saveServerDetails(HetznerServerDetails serverDetails) async { Future<void> saveServerDetails(ServerHostingDetails serverDetails) async {
await getIt<ApiConfigModel>().storeServerDetails(serverDetails); await getIt<ApiConfigModel>().storeServerDetails(serverDetails);
} }
@ -239,10 +273,6 @@ class AppConfigRepository {
await getIt<ApiConfigModel>().storeHetznerKey(key); await getIt<ApiConfigModel>().storeHetznerKey(key);
} }
Future<void> saveServerDomain(String domain) async {
await getIt<ApiConfigModel>().storeServerDomain(domain);
}
Future<void> saveBackblazeKey(BackblazeCredential backblazeCredential) async { Future<void> saveBackblazeKey(BackblazeCredential backblazeCredential) async {
await getIt<ApiConfigModel>().storeBackblazeCredential(backblazeCredential); await getIt<ApiConfigModel>().storeBackblazeCredential(backblazeCredential);
} }
@ -251,8 +281,8 @@ class AppConfigRepository {
await getIt<ApiConfigModel>().storeCloudFlareKey(key); await getIt<ApiConfigModel>().storeCloudFlareKey(key);
} }
Future<void> saveDomain(CloudFlareDomain cloudFlareDomain) async { Future<void> saveDomain(ServerDomain serverDomain) async {
await getIt<ApiConfigModel>().storeCloudFlareDomain(cloudFlareDomain); await getIt<ApiConfigModel>().storeServerDomain(serverDomain);
} }
Future<void> saveIsServerStarted(bool value) async { Future<void> saveIsServerStarted(bool value) async {
@ -275,12 +305,12 @@ class AppConfigRepository {
await box.put(BNames.hasFinalChecked, value); await box.put(BNames.hasFinalChecked, value);
} }
Future<void> deleteServer(CloudFlareDomain cloudFlareDomain) async { Future<void> deleteServer(ServerDomain serverDomain) async {
var hetznerApi = HetznerApi(); var hetznerApi = HetznerApi();
var cloudFlare = CloudflareApi(); var cloudFlare = CloudflareApi();
await hetznerApi.deleteSelfprivacyServerAndAllVolumes( await hetznerApi.deleteSelfprivacyServerAndAllVolumes(
domainName: cloudFlareDomain.domainName, domainName: serverDomain.domainName,
); );
await box.put(BNames.hasFinalChecked, false); await box.put(BNames.hasFinalChecked, false);
@ -288,14 +318,14 @@ class AppConfigRepository {
await box.put(BNames.isServerResetedFirstTime, false); await box.put(BNames.isServerResetedFirstTime, false);
await box.put(BNames.isServerResetedSecondTime, false); await box.put(BNames.isServerResetedSecondTime, false);
await box.put(BNames.isLoading, false); await box.put(BNames.isLoading, false);
await box.put(BNames.hetznerServer, null); await box.put(BNames.serverDetails, null);
await cloudFlare.removeSimilarRecords(cloudFlareDomain: cloudFlareDomain); await cloudFlare.removeSimilarRecords(cloudFlareDomain: serverDomain);
} }
Future<void> deleteRecords() async { Future<void> deleteRecords() async {
await box.deleteAll([ await box.deleteAll([
BNames.hetznerServer, BNames.serverDetails,
BNames.isServerStarted, BNames.isServerStarted,
BNames.isServerResetedFirstTime, BNames.isServerResetedFirstTime,
BNames.isServerResetedSecondTime, BNames.isServerResetedSecondTime,

View File

@ -5,9 +5,9 @@ abstract class AppConfigState extends Equatable {
required this.hetznerKey, required this.hetznerKey,
required this.cloudFlareKey, required this.cloudFlareKey,
required this.backblazeCredential, required this.backblazeCredential,
required this.cloudFlareDomain, required this.serverDomain,
required this.rootUser, required this.rootUser,
required this.hetznerServer, required this.serverDetails,
required this.isServerStarted, required this.isServerStarted,
required this.isServerResetedFirstTime, required this.isServerResetedFirstTime,
required this.isServerResetedSecondTime, required this.isServerResetedSecondTime,
@ -18,9 +18,9 @@ abstract class AppConfigState extends Equatable {
hetznerKey, hetznerKey,
cloudFlareKey, cloudFlareKey,
backblazeCredential, backblazeCredential,
cloudFlareDomain, serverDomain,
rootUser, rootUser,
hetznerServer, serverDetails,
isServerStarted, isServerStarted,
isServerResetedFirstTime, isServerResetedFirstTime,
]; ];
@ -28,9 +28,9 @@ abstract class AppConfigState extends Equatable {
final String? hetznerKey; final String? hetznerKey;
final String? cloudFlareKey; final String? cloudFlareKey;
final BackblazeCredential? backblazeCredential; final BackblazeCredential? backblazeCredential;
final CloudFlareDomain? cloudFlareDomain; final ServerDomain? serverDomain;
final User? rootUser; final User? rootUser;
final HetznerServerDetails? hetznerServer; final ServerHostingDetails? serverDetails;
final bool isServerStarted; final bool isServerStarted;
final bool isServerResetedFirstTime; final bool isServerResetedFirstTime;
final bool isServerResetedSecondTime; final bool isServerResetedSecondTime;
@ -38,17 +38,18 @@ abstract class AppConfigState extends Equatable {
bool get isHetznerFilled => hetznerKey != null; bool get isHetznerFilled => hetznerKey != null;
bool get isCloudFlareFilled => cloudFlareKey != null; bool get isCloudFlareFilled => cloudFlareKey != null;
bool get isBackblazeFilled => backblazeCredential != null; bool get isBackblazeFilled => backblazeCredential != null;
bool get isDomainFilled => cloudFlareDomain != null; bool get isDomainFilled => serverDomain != null;
bool get isUserFilled => rootUser != null; bool get isUserFilled => rootUser != null;
bool get isServerCreated => hetznerServer != null; bool get isServerCreated => serverDetails != null;
bool get isFullyInitilized => _fulfilementList.every((el) => el!); bool get isFullyInitilized => _fulfilementList.every((el) => el!);
int get progress => _fulfilementList.where((el) => el!).length; ServerSetupProgress get progress =>
ServerSetupProgress.values[_fulfilementList.where((el) => el!).length];
int get porgressBar { int get porgressBar {
if (progress < 6) { if (progress.index < 6) {
return progress; return progress.index;
} else if (progress < 10) { } else if (progress.index < 10) {
return 6; return 6;
} else { } else {
return 7; return 7;
@ -82,9 +83,9 @@ class TimerState extends AppConfigNotFinished {
hetznerKey: dataState.hetznerKey, hetznerKey: dataState.hetznerKey,
cloudFlareKey: dataState.cloudFlareKey, cloudFlareKey: dataState.cloudFlareKey,
backblazeCredential: dataState.backblazeCredential, backblazeCredential: dataState.backblazeCredential,
cloudFlareDomain: dataState.cloudFlareDomain, serverDomain: dataState.serverDomain,
rootUser: dataState.rootUser, rootUser: dataState.rootUser,
hetznerServer: dataState.hetznerServer, serverDetails: dataState.serverDetails,
isServerStarted: dataState.isServerStarted, isServerStarted: dataState.isServerStarted,
isServerResetedFirstTime: dataState.isServerResetedFirstTime, isServerResetedFirstTime: dataState.isServerResetedFirstTime,
isServerResetedSecondTime: dataState.isServerResetedSecondTime, isServerResetedSecondTime: dataState.isServerResetedSecondTime,
@ -104,6 +105,19 @@ class TimerState extends AppConfigNotFinished {
]; ];
} }
enum ServerSetupProgress {
nothingYet,
hetznerFilled,
cloudFlareFilled,
backblazeFilled,
domainFilled,
userFilled,
serverCreated,
serverStarted,
serverResetedFirstTime,
serverResetedSecondTime,
}
class AppConfigNotFinished extends AppConfigState { class AppConfigNotFinished extends AppConfigState {
final bool isLoading; final bool isLoading;
final Map<String, bool>? dnsMatches; final Map<String, bool>? dnsMatches;
@ -112,9 +126,9 @@ class AppConfigNotFinished extends AppConfigState {
String? hetznerKey, String? hetznerKey,
String? cloudFlareKey, String? cloudFlareKey,
BackblazeCredential? backblazeCredential, BackblazeCredential? backblazeCredential,
CloudFlareDomain? cloudFlareDomain, ServerDomain? serverDomain,
User? rootUser, User? rootUser,
HetznerServerDetails? hetznerServer, ServerHostingDetails? serverDetails,
required bool isServerStarted, required bool isServerStarted,
required bool isServerResetedFirstTime, required bool isServerResetedFirstTime,
required bool isServerResetedSecondTime, required bool isServerResetedSecondTime,
@ -124,9 +138,9 @@ class AppConfigNotFinished extends AppConfigState {
hetznerKey: hetznerKey, hetznerKey: hetznerKey,
cloudFlareKey: cloudFlareKey, cloudFlareKey: cloudFlareKey,
backblazeCredential: backblazeCredential, backblazeCredential: backblazeCredential,
cloudFlareDomain: cloudFlareDomain, serverDomain: serverDomain,
rootUser: rootUser, rootUser: rootUser,
hetznerServer: hetznerServer, serverDetails: serverDetails,
isServerStarted: isServerStarted, isServerStarted: isServerStarted,
isServerResetedFirstTime: isServerResetedFirstTime, isServerResetedFirstTime: isServerResetedFirstTime,
isServerResetedSecondTime: isServerResetedSecondTime, isServerResetedSecondTime: isServerResetedSecondTime,
@ -137,9 +151,9 @@ class AppConfigNotFinished extends AppConfigState {
hetznerKey, hetznerKey,
cloudFlareKey, cloudFlareKey,
backblazeCredential, backblazeCredential,
cloudFlareDomain, serverDomain,
rootUser, rootUser,
hetznerServer, serverDetails,
isServerStarted, isServerStarted,
isServerResetedFirstTime, isServerResetedFirstTime,
isLoading, isLoading,
@ -150,9 +164,9 @@ class AppConfigNotFinished extends AppConfigState {
String? hetznerKey, String? hetznerKey,
String? cloudFlareKey, String? cloudFlareKey,
BackblazeCredential? backblazeCredential, BackblazeCredential? backblazeCredential,
CloudFlareDomain? cloudFlareDomain, ServerDomain? serverDomain,
User? rootUser, User? rootUser,
HetznerServerDetails? hetznerServer, ServerHostingDetails? serverDetails,
bool? isServerStarted, bool? isServerStarted,
bool? isServerResetedFirstTime, bool? isServerResetedFirstTime,
bool? isServerResetedSecondTime, bool? isServerResetedSecondTime,
@ -163,9 +177,9 @@ class AppConfigNotFinished extends AppConfigState {
hetznerKey: hetznerKey ?? this.hetznerKey, hetznerKey: hetznerKey ?? this.hetznerKey,
cloudFlareKey: cloudFlareKey ?? this.cloudFlareKey, cloudFlareKey: cloudFlareKey ?? this.cloudFlareKey,
backblazeCredential: backblazeCredential ?? this.backblazeCredential, backblazeCredential: backblazeCredential ?? this.backblazeCredential,
cloudFlareDomain: cloudFlareDomain ?? this.cloudFlareDomain, serverDomain: serverDomain ?? this.serverDomain,
rootUser: rootUser ?? this.rootUser, rootUser: rootUser ?? this.rootUser,
hetznerServer: hetznerServer ?? this.hetznerServer, serverDetails: serverDetails ?? this.serverDetails,
isServerStarted: isServerStarted ?? this.isServerStarted, isServerStarted: isServerStarted ?? this.isServerStarted,
isServerResetedFirstTime: isServerResetedFirstTime:
isServerResetedFirstTime ?? this.isServerResetedFirstTime, isServerResetedFirstTime ?? this.isServerResetedFirstTime,
@ -179,9 +193,9 @@ class AppConfigNotFinished extends AppConfigState {
hetznerKey: hetznerKey!, hetznerKey: hetznerKey!,
cloudFlareKey: cloudFlareKey!, cloudFlareKey: cloudFlareKey!,
backblazeCredential: backblazeCredential!, backblazeCredential: backblazeCredential!,
cloudFlareDomain: cloudFlareDomain!, serverDomain: serverDomain!,
rootUser: rootUser!, rootUser: rootUser!,
hetznerServer: hetznerServer!, serverDetails: serverDetails!,
isServerStarted: isServerStarted, isServerStarted: isServerStarted,
isServerResetedFirstTime: isServerResetedFirstTime, isServerResetedFirstTime: isServerResetedFirstTime,
isServerResetedSecondTime: isServerResetedSecondTime, isServerResetedSecondTime: isServerResetedSecondTime,
@ -194,9 +208,9 @@ class AppConfigEmpty extends AppConfigNotFinished {
hetznerKey: null, hetznerKey: null,
cloudFlareKey: null, cloudFlareKey: null,
backblazeCredential: null, backblazeCredential: null,
cloudFlareDomain: null, serverDomain: null,
rootUser: null, rootUser: null,
hetznerServer: null, serverDetails: null,
isServerStarted: false, isServerStarted: false,
isServerResetedFirstTime: false, isServerResetedFirstTime: false,
isServerResetedSecondTime: false, isServerResetedSecondTime: false,
@ -210,9 +224,9 @@ class AppConfigFinished extends AppConfigState {
required String hetznerKey, required String hetznerKey,
required String cloudFlareKey, required String cloudFlareKey,
required BackblazeCredential backblazeCredential, required BackblazeCredential backblazeCredential,
required CloudFlareDomain cloudFlareDomain, required ServerDomain serverDomain,
required User rootUser, required User rootUser,
required HetznerServerDetails hetznerServer, required ServerHostingDetails serverDetails,
required bool isServerStarted, required bool isServerStarted,
required bool isServerResetedFirstTime, required bool isServerResetedFirstTime,
required bool isServerResetedSecondTime, required bool isServerResetedSecondTime,
@ -220,9 +234,9 @@ class AppConfigFinished extends AppConfigState {
hetznerKey: hetznerKey, hetznerKey: hetznerKey,
cloudFlareKey: cloudFlareKey, cloudFlareKey: cloudFlareKey,
backblazeCredential: backblazeCredential, backblazeCredential: backblazeCredential,
cloudFlareDomain: cloudFlareDomain, serverDomain: serverDomain,
rootUser: rootUser, rootUser: rootUser,
hetznerServer: hetznerServer, serverDetails: serverDetails,
isServerStarted: isServerStarted, isServerStarted: isServerStarted,
isServerResetedFirstTime: isServerResetedFirstTime, isServerResetedFirstTime: isServerResetedFirstTime,
isServerResetedSecondTime: isServerResetedSecondTime, isServerResetedSecondTime: isServerResetedSecondTime,
@ -233,35 +247,45 @@ class AppConfigFinished extends AppConfigState {
hetznerKey, hetznerKey,
cloudFlareKey, cloudFlareKey,
backblazeCredential, backblazeCredential,
cloudFlareDomain, serverDomain,
rootUser, rootUser,
hetznerServer, serverDetails,
isServerStarted, isServerStarted,
isServerResetedFirstTime, isServerResetedFirstTime,
]; ];
} }
class AppRecovery extends AppConfigState { enum RecoveryStep {
const AppRecovery({ Selecting,
required String hetznerKey, RecoveryKey,
required String cloudFlareKey, NewDeviceKey,
required BackblazeCredential backblazeCredential, OldToken,
required CloudFlareDomain cloudFlareDomain, HetznerToken,
required User rootUser, CloudflareToken,
required HetznerServerDetails hetznerServer, BackblazeToken,
required bool isServerStarted, }
required bool isServerResetedFirstTime,
required bool isServerResetedSecondTime, class AppConfigRecovery extends AppConfigState {
final RecoveryStep currentStep;
const AppConfigRecovery({
String? hetznerKey,
String? cloudFlareKey,
BackblazeCredential? backblazeCredential,
ServerDomain? serverDomain,
User? rootUser,
ServerHostingDetails? serverDetails,
required RecoveryStep this.currentStep,
}) : super( }) : super(
hetznerKey: hetznerKey, hetznerKey: hetznerKey,
cloudFlareKey: cloudFlareKey, cloudFlareKey: cloudFlareKey,
backblazeCredential: backblazeCredential, backblazeCredential: backblazeCredential,
cloudFlareDomain: cloudFlareDomain, serverDomain: serverDomain,
rootUser: rootUser, rootUser: rootUser,
hetznerServer: hetznerServer, serverDetails: serverDetails,
isServerStarted: isServerStarted, isServerStarted: true,
isServerResetedFirstTime: isServerResetedFirstTime, isServerResetedFirstTime: true,
isServerResetedSecondTime: isServerResetedSecondTime, isServerResetedSecondTime: true,
); );
@override @override
@ -269,10 +293,29 @@ class AppRecovery extends AppConfigState {
hetznerKey, hetznerKey,
cloudFlareKey, cloudFlareKey,
backblazeCredential, backblazeCredential,
cloudFlareDomain, serverDomain,
rootUser, rootUser,
hetznerServer, serverDetails,
isServerStarted, isServerStarted,
isServerResetedFirstTime, isServerResetedFirstTime,
currentStep
]; ];
AppConfigRecovery copyWith({
String? hetznerKey,
String? cloudFlareKey,
BackblazeCredential? backblazeCredential,
ServerDomain? serverDomain,
User? rootUser,
ServerHostingDetails? serverDetails,
RecoveryStep? currentStep,
}) =>
AppConfigRecovery(
hetznerKey: hetznerKey ?? this.hetznerKey,
cloudFlareKey: cloudFlareKey ?? this.cloudFlareKey,
backblazeCredential: backblazeCredential ?? this.backblazeCredential,
serverDomain: serverDomain ?? this.serverDomain,
rootUser: rootUser ?? this.rootUser,
serverDetails: serverDetails ?? this.serverDetails,
currentStep: currentStep ?? this.currentStep);
} }

View File

@ -85,9 +85,9 @@ class BackupsCubit extends AppConfigDependendCubit<BackupsState> {
Future<void> createBucket() async { Future<void> createBucket() async {
emit(state.copyWith(preventActions: true)); emit(state.copyWith(preventActions: true));
final domain = appConfigCubit.state.cloudFlareDomain!.domainName final domain = appConfigCubit.state.serverDomain!.domainName
.replaceAll(RegExp(r'[^a-zA-Z0-9]'), '-'); .replaceAll(RegExp(r'[^a-zA-Z0-9]'), '-');
final serverId = appConfigCubit.state.hetznerServer!.id; final serverId = appConfigCubit.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) {

View File

@ -1,6 +1,6 @@
import 'package:cubit_form/cubit_form.dart'; import 'package:cubit_form/cubit_form.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';
import 'package:selfprivacy/logic/models/cloudflare_domain.dart'; import 'package:selfprivacy/logic/models/server_domain.dart';
import 'package:selfprivacy/logic/models/dns_records.dart'; import 'package:selfprivacy/logic/models/dns_records.dart';
import '../../api_maps/cloudflare.dart'; import '../../api_maps/cloudflare.dart';
@ -20,11 +20,11 @@ class DnsRecordsCubit extends AppConfigDependendCubit<DnsRecordsState> {
emit(DnsRecordsState( emit(DnsRecordsState(
dnsState: DnsRecordsStatus.refreshing, dnsState: DnsRecordsStatus.refreshing,
dnsRecords: _getDesiredDnsRecords( dnsRecords: _getDesiredDnsRecords(
appConfigCubit.state.cloudFlareDomain?.domainName, "", ""))); appConfigCubit.state.serverDomain?.domainName, "", "")));
print('Loading DNS status'); print('Loading DNS status');
if (appConfigCubit.state is AppConfigFinished) { if (appConfigCubit.state is AppConfigFinished) {
final CloudFlareDomain? domain = appConfigCubit.state.cloudFlareDomain; final ServerDomain? domain = appConfigCubit.state.serverDomain;
final String? ipAddress = appConfigCubit.state.hetznerServer?.ip4; final String? ipAddress = appConfigCubit.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);
@ -95,8 +95,8 @@ class DnsRecordsCubit extends AppConfigDependendCubit<DnsRecordsState> {
Future<void> fix() async { Future<void> fix() async {
emit(state.copyWith(dnsState: DnsRecordsStatus.refreshing)); emit(state.copyWith(dnsState: DnsRecordsStatus.refreshing));
final CloudFlareDomain? domain = appConfigCubit.state.cloudFlareDomain; final ServerDomain? domain = appConfigCubit.state.serverDomain;
final String? ipAddress = appConfigCubit.state.hetznerServer?.ip4; final String? ipAddress = appConfigCubit.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(

View File

@ -52,5 +52,14 @@ class FieldCubitFactory {
); );
} }
FieldCubit<String> createServerDomainField() {
return FieldCubit(
initalValue: '',
validations: [
RequiredStringValidation('validations.required'.tr()),
],
);
}
final BuildContext context; final BuildContext context;
} }

View File

@ -1,7 +1,7 @@
import 'package:cubit_form/cubit_form.dart'; import 'package:cubit_form/cubit_form.dart';
import 'package:selfprivacy/logic/api_maps/cloudflare.dart'; import 'package:selfprivacy/logic/api_maps/cloudflare.dart';
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart'; import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
import 'package:selfprivacy/logic/models/cloudflare_domain.dart'; import 'package:selfprivacy/logic/models/server_domain.dart';
class DomainSetupCubit extends Cubit<DomainSetupState> { class DomainSetupCubit extends Cubit<DomainSetupState> {
DomainSetupCubit(this.initializingCubit) : super(Initial()); DomainSetupCubit(this.initializingCubit) : super(Initial());
@ -36,9 +36,10 @@ class DomainSetupCubit extends Cubit<DomainSetupState> {
var zoneId = await api.getZoneId(domainName); var zoneId = await api.getZoneId(domainName);
var domain = CloudFlareDomain( var domain = ServerDomain(
domainName: domainName, domainName: domainName,
zoneId: zoneId, zoneId: zoneId,
provider: DnsProvider.Cloudflare,
); );
initializingCubit.setDomain(domain); initializingCubit.setDomain(domain);

View File

@ -1,51 +1,32 @@
import 'dart:async'; import 'dart:async';
import 'package:cubit_form/cubit_form.dart'; import 'package:cubit_form/cubit_form.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:selfprivacy/logic/api_maps/server.dart';
import 'package:selfprivacy/logic/api_maps/hetzner.dart';
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart'; import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/validations/validations.dart'; import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
import 'package:selfprivacy/logic/models/server_domain.dart';
class RecoveryDomainFormCubit extends FormCubit { class RecoveryDomainFormCubit extends FormCubit {
RecoveryDomainFormCubit(this.initializingCubit) { RecoveryDomainFormCubit(
var regExp = RegExp(r"\s+|[-!$%^&*()@+|~=`{}\[\]:<>?,.\/]"); this.initializingCubit, final FieldCubitFactory fieldFactory) {
apiKey = FieldCubit( serverDomainField = fieldFactory.createServerDomainField();
initalValue: '',
validations: [
RequiredStringValidation('validations.required'.tr()),
ValidationModel<String>(
(s) => regExp.hasMatch(s), 'validations.key_format'.tr()),
LengthStringNotEqualValidation(64)
],
);
super.addFields([apiKey]); super.addFields([serverDomainField]);
} }
@override @override
FutureOr<void> onSubmit() async { FutureOr<void> onSubmit() async {
initializingCubit.setHetznerKey(apiKey.state.value); initializingCubit.setDomain(ServerDomain(
domainName: serverDomainField.state.value,
provider: DnsProvider.Unknown,
zoneId: ""));
} }
// @override
// FutureOr<bool> asyncValidation() async {
// ; //var client =
// }
final AppConfigCubit initializingCubit; final AppConfigCubit initializingCubit;
late final FieldCubit<String> serverDomainField;
late final FieldCubit<String> apiKey;
@override
FutureOr<bool> asyncValidation() async {
late bool isKeyValid;
HetznerApi apiClient = HetznerApi(isWithToken: false);
try {
isKeyValid = await apiClient.isValid(apiKey.state.value);
} catch (e) {
addError(e);
}
if (!isKeyValid) {
apiKey.setError('bad key');
return false;
}
return true;
}
} }

View File

@ -14,7 +14,7 @@ class ServerDetailsCubit extends Cubit<ServerDetailsState> {
ServerDetailsRepository repository = ServerDetailsRepository(); ServerDetailsRepository repository = ServerDetailsRepository();
void check() async { void check() async {
var isReadyToCheck = getIt<ApiConfigModel>().hetznerServer != null; var isReadyToCheck = getIt<ApiConfigModel>().serverDetails != null;
if (isReadyToCheck) { if (isReadyToCheck) {
emit(ServerDetailsLoading()); emit(ServerDetailsLoading());
var data = await repository.load(); var data = await repository.load();

View File

@ -2,26 +2,24 @@ import 'package:hive/hive.dart';
import 'package:selfprivacy/config/hive_config.dart'; import 'package:selfprivacy/config/hive_config.dart';
import 'package:selfprivacy/logic/models/backblaze_bucket.dart'; import 'package:selfprivacy/logic/models/backblaze_bucket.dart';
import 'package:selfprivacy/logic/models/backblaze_credential.dart'; import 'package:selfprivacy/logic/models/backblaze_credential.dart';
import 'package:selfprivacy/logic/models/cloudflare_domain.dart'; import 'package:selfprivacy/logic/models/server_domain.dart';
import 'package:selfprivacy/logic/models/server_details.dart'; import 'package:selfprivacy/logic/models/server_details.dart';
class ApiConfigModel { class ApiConfigModel {
Box _box = Hive.box(BNames.appConfig); Box _box = Hive.box(BNames.appConfig);
HetznerServerDetails? get hetznerServer => _hetznerServer; ServerHostingDetails? get serverDetails => _serverDetails;
String? get hetznerKey => _hetznerKey; String? get hetznerKey => _hetznerKey;
String? get cloudFlareKey => _cloudFlareKey; String? get cloudFlareKey => _cloudFlareKey;
String? get serverDomain => _serverDomain;
BackblazeCredential? get backblazeCredential => _backblazeCredential; BackblazeCredential? get backblazeCredential => _backblazeCredential;
CloudFlareDomain? get cloudFlareDomain => _cloudFlareDomain; ServerDomain? get serverDomain => _serverDomain;
BackblazeBucket? get backblazeBucket => _backblazeBucket; BackblazeBucket? get backblazeBucket => _backblazeBucket;
String? _hetznerKey; String? _hetznerKey;
String? _cloudFlareKey; String? _cloudFlareKey;
String? _serverDomain; ServerHostingDetails? _serverDetails;
HetznerServerDetails? _hetznerServer;
BackblazeCredential? _backblazeCredential; BackblazeCredential? _backblazeCredential;
CloudFlareDomain? _cloudFlareDomain; ServerDomain? _serverDomain;
BackblazeBucket? _backblazeBucket; BackblazeBucket? _backblazeBucket;
Future<void> storeHetznerKey(String value) async { Future<void> storeHetznerKey(String value) async {
@ -34,25 +32,20 @@ class ApiConfigModel {
_cloudFlareKey = value; _cloudFlareKey = value;
} }
Future<void> storeServerDomain(String value) async {
await _box.put(BNames.serverDomain, value);
_serverDomain = value;
}
Future<void> storeBackblazeCredential(BackblazeCredential value) async { Future<void> storeBackblazeCredential(BackblazeCredential value) async {
await _box.put(BNames.backblazeKey, value); await _box.put(BNames.backblazeKey, value);
_backblazeCredential = value; _backblazeCredential = value;
} }
Future<void> storeCloudFlareDomain(CloudFlareDomain value) async { Future<void> storeServerDomain(ServerDomain value) async {
await _box.put(BNames.cloudFlareDomain, value); await _box.put(BNames.serverDomain, value);
_cloudFlareDomain = value; _serverDomain = value;
} }
Future<void> storeServerDetails(HetznerServerDetails value) async { Future<void> storeServerDetails(ServerHostingDetails value) async {
await _box.put(BNames.hetznerServer, value); await _box.put(BNames.serverDetails, value);
_hetznerServer = value; _serverDetails = value;
} }
Future<void> storeBackblazeBucket(BackblazeBucket value) async { Future<void> storeBackblazeBucket(BackblazeBucket value) async {
@ -64,8 +57,8 @@ class ApiConfigModel {
_hetznerKey = null; _hetznerKey = null;
_cloudFlareKey = null; _cloudFlareKey = null;
_backblazeCredential = null; _backblazeCredential = null;
_cloudFlareDomain = null; _serverDomain = null;
_hetznerServer = null; _serverDetails = null;
_backblazeBucket = null; _backblazeBucket = null;
} }
@ -74,8 +67,8 @@ class ApiConfigModel {
_cloudFlareKey = _box.get(BNames.cloudFlareKey); _cloudFlareKey = _box.get(BNames.cloudFlareKey);
_backblazeCredential = _box.get(BNames.backblazeKey); _backblazeCredential = _box.get(BNames.backblazeKey);
_cloudFlareDomain = _box.get(BNames.cloudFlareDomain); _serverDomain = _box.get(BNames.serverDomain);
_hetznerServer = _box.get(BNames.hetznerServer); _serverDetails = _box.get(BNames.serverDetails);
_backblazeBucket = _box.get(BNames.backblazeBucket); _backblazeBucket = _box.get(BNames.backblazeBucket);
} }
} }

View File

@ -3,8 +3,8 @@ import 'package:hive/hive.dart';
part 'server_details.g.dart'; part 'server_details.g.dart';
@HiveType(typeId: 2) @HiveType(typeId: 2)
class HetznerServerDetails { class ServerHostingDetails {
HetznerServerDetails({ ServerHostingDetails({
required this.ip4, required this.ip4,
required this.id, required this.id,
required this.createTime, required this.createTime,
@ -26,13 +26,13 @@ class HetznerServerDetails {
final DateTime? startTime; final DateTime? startTime;
@HiveField(4) @HiveField(4)
final HetznerDataBase dataBase; final ServerVolume dataBase;
@HiveField(5) @HiveField(5)
final String apiToken; final String apiToken;
HetznerServerDetails copyWith({DateTime? startTime}) { ServerHostingDetails copyWith({DateTime? startTime}) {
return HetznerServerDetails( return ServerHostingDetails(
startTime: startTime ?? this.startTime, startTime: startTime ?? this.startTime,
createTime: createTime, createTime: createTime,
id: id, id: id,
@ -46,8 +46,8 @@ class HetznerServerDetails {
} }
@HiveType(typeId: 5) @HiveType(typeId: 5)
class HetznerDataBase { class ServerVolume {
HetznerDataBase({ ServerVolume({
required this.id, required this.id,
required this.name, required this.name,
}); });

View File

@ -6,28 +6,28 @@ part of 'server_details.dart';
// TypeAdapterGenerator // TypeAdapterGenerator
// ************************************************************************** // **************************************************************************
class HetznerServerDetailsAdapter extends TypeAdapter<HetznerServerDetails> { class HetznerServerDetailsAdapter extends TypeAdapter<ServerHostingDetails> {
@override @override
final int typeId = 2; final int typeId = 2;
@override @override
HetznerServerDetails read(BinaryReader reader) { ServerHostingDetails read(BinaryReader reader) {
final numOfFields = reader.readByte(); final numOfFields = reader.readByte();
final fields = <int, dynamic>{ final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
}; };
return HetznerServerDetails( return ServerHostingDetails(
ip4: fields[0] as String, ip4: fields[0] as String,
id: fields[1] as int, id: fields[1] as int,
createTime: fields[3] as DateTime?, createTime: fields[3] as DateTime?,
dataBase: fields[4] as HetznerDataBase, dataBase: fields[4] as ServerVolume,
apiToken: fields[5] as String, apiToken: fields[5] as String,
startTime: fields[2] as DateTime?, startTime: fields[2] as DateTime?,
); );
} }
@override @override
void write(BinaryWriter writer, HetznerServerDetails obj) { void write(BinaryWriter writer, ServerHostingDetails obj) {
writer writer
..writeByte(6) ..writeByte(6)
..writeByte(0) ..writeByte(0)
@ -55,24 +55,24 @@ class HetznerServerDetailsAdapter extends TypeAdapter<HetznerServerDetails> {
typeId == other.typeId; typeId == other.typeId;
} }
class HetznerDataBaseAdapter extends TypeAdapter<HetznerDataBase> { class HetznerDataBaseAdapter extends TypeAdapter<ServerVolume> {
@override @override
final int typeId = 5; final int typeId = 5;
@override @override
HetznerDataBase read(BinaryReader reader) { ServerVolume read(BinaryReader reader) {
final numOfFields = reader.readByte(); final numOfFields = reader.readByte();
final fields = <int, dynamic>{ final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
}; };
return HetznerDataBase( return ServerVolume(
id: fields[1] as int, id: fields[1] as int,
name: fields[2] as String, name: fields[2] as String,
); );
} }
@override @override
void write(BinaryWriter writer, HetznerDataBase obj) { void write(BinaryWriter writer, ServerVolume obj) {
writer writer
..writeByte(2) ..writeByte(2)
..writeByte(1) ..writeByte(1)

View File

@ -1,12 +1,18 @@
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
part 'cloudflare_domain.g.dart'; part 'server_domain.g.dart';
enum DnsProvider {
Unknown,
Cloudflare,
}
@HiveType(typeId: 3) @HiveType(typeId: 3)
class CloudFlareDomain { class ServerDomain {
CloudFlareDomain({ ServerDomain({
required this.domainName, required this.domainName,
required this.zoneId, required this.zoneId,
required this.provider,
}); });
@HiveField(0) @HiveField(0)
@ -15,6 +21,9 @@ class CloudFlareDomain {
@HiveField(1) @HiveField(1)
final String zoneId; final String zoneId;
@HiveField(2, defaultValue: DnsProvider.Cloudflare)
final DnsProvider provider;
@override @override
String toString() { String toString() {
return '$domainName: $zoneId'; return '$domainName: $zoneId';

View File

@ -1,35 +1,39 @@
// GENERATED CODE - DO NOT MODIFY BY HAND // GENERATED CODE - DO NOT MODIFY BY HAND
part of 'cloudflare_domain.dart'; part of 'server_domain.dart';
// ************************************************************************** // **************************************************************************
// TypeAdapterGenerator // TypeAdapterGenerator
// ************************************************************************** // **************************************************************************
class CloudFlareDomainAdapter extends TypeAdapter<CloudFlareDomain> { class ServerDomainAdapter extends TypeAdapter<ServerDomain> {
@override @override
final int typeId = 3; final int typeId = 3;
@override @override
CloudFlareDomain read(BinaryReader reader) { ServerDomain read(BinaryReader reader) {
final numOfFields = reader.readByte(); final numOfFields = reader.readByte();
final fields = <int, dynamic>{ final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
}; };
return CloudFlareDomain( return ServerDomain(
domainName: fields[0] as String, domainName: fields[0] as String,
zoneId: fields[1] as String, zoneId: fields[1] as String,
provider:
fields[2] == null ? DnsProvider.Cloudflare : fields[2] as DnsProvider,
); );
} }
@override @override
void write(BinaryWriter writer, CloudFlareDomain obj) { void write(BinaryWriter writer, ServerDomain obj) {
writer writer
..writeByte(2) ..writeByte(3)
..writeByte(0) ..writeByte(0)
..write(obj.domainName) ..write(obj.domainName)
..writeByte(1) ..writeByte(1)
..write(obj.zoneId); ..write(obj.zoneId)
..writeByte(2)
..write(obj.provider);
} }
@override @override
@ -38,7 +42,7 @@ class CloudFlareDomainAdapter extends TypeAdapter<CloudFlareDomain> {
@override @override
bool operator ==(Object other) => bool operator ==(Object other) =>
identical(this, other) || identical(this, other) ||
other is CloudFlareDomainAdapter && other is ServerDomainAdapter &&
runtimeType == other.runtimeType && runtimeType == other.runtimeType &&
typeId == other.typeId; typeId == other.typeId;
} }

View File

@ -63,7 +63,7 @@ class _DnsDetailsPageState extends State<DnsDetailsPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var isReady = context.watch<AppConfigCubit>().state is AppConfigFinished; var isReady = context.watch<AppConfigCubit>().state is AppConfigFinished;
final domain = getIt<ApiConfigModel>().cloudFlareDomain?.domainName ?? ''; final domain = getIt<ApiConfigModel>().serverDomain?.domainName ?? '';
var dnsCubit = context.watch<DnsRecordsCubit>().state; var dnsCubit = context.watch<DnsRecordsCubit>().state;
print(dnsCubit.dnsState); print(dnsCubit.dnsState);

View File

@ -129,7 +129,7 @@ class _AppSettingsPageState extends State<AppSettingsPage> {
Widget deleteServer(BuildContext context) { Widget deleteServer(BuildContext context) {
var isDisabled = var isDisabled =
context.watch<AppConfigCubit>().state.hetznerServer == null; context.watch<AppConfigCubit>().state.serverDetails == null;
return Container( return Container(
padding: EdgeInsets.only(top: 20, bottom: 5), padding: EdgeInsets.only(top: 20, bottom: 5),
decoration: BoxDecoration( decoration: BoxDecoration(

View File

@ -100,7 +100,7 @@ class _Card extends StatelessWidget {
AppConfigState appConfig = context.watch<AppConfigCubit>().state; AppConfigState appConfig = context.watch<AppConfigCubit>().state;
var domainName = var domainName =
appConfig.isDomainFilled ? appConfig.cloudFlareDomain!.domainName : ''; appConfig.isDomainFilled ? appConfig.serverDomain!.domainName : '';
switch (provider.type) { switch (provider.type) {
case ProviderType.server: case ProviderType.server:

View File

@ -1,75 +1,48 @@
import 'package:cubit_form/cubit_form.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:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
import 'package:selfprivacy/logic/cubit/forms/setup/recovering/recovery_domain_form_cubit.dart';
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart'; import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
class RecoveryDomain extends StatefulWidget { class RecoveryDomain extends StatelessWidget {
@override
State<RecoveryDomain> createState() => _RecoveryDomainState();
}
class _RecoveryDomainState extends State<RecoveryDomain> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BrandHeroScreen( var appConfig = context.watch<AppConfigCubit>();
children: [
TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "recovering.domain_recover_placeholder".tr(),
),
),
SizedBox(height: 16),
BrandButton.rised(
onPressed: () {},
text: "more.continue".tr(),
),
],
heroTitle: "recovering.recovery_main_header".tr(),
heroSubtitle: "recovering.domain_recovery_description".tr(),
hasBackButton: true,
hasFlashButton: false,
heroIcon: Icons.link,
);
}
}
/*class RecoveryDomain extends StatelessWidget { return BlocProvider(
@override create: (context) =>
Widget build(BuildContext context) { RecoveryDomainFormCubit(appConfig, FieldCubitFactory(context)),
return SafeArea( child: Builder(builder: (context) {
child: Scaffold( var formCubitState = context.watch<RecoveryDomainFormCubit>().state;
appBar: PreferredSize(
preferredSize: Size.fromHeight(52), return BrandHeroScreen(
child: BrandHeader(hasBackButton: true),
),
body: ListView(
padding: EdgeInsets.all(16),
children: [ children: [
Text( CubitFormTextField(
"recovering.recovery_main_header".tr(), formFieldCubit:
style: Theme.of(context).textTheme.headlineMedium, context.read<RecoveryDomainFormCubit>().serverDomainField,
),
SizedBox(height: 18),
Text(
"recovering.domain_recovery_description".tr(),
style: Theme.of(context).textTheme.bodyLarge,
),
SizedBox(height: 18),
TextField(
decoration: InputDecoration( decoration: InputDecoration(
border: OutlineInputBorder(), border: OutlineInputBorder(),
labelText: "recovering.domain_recover_placeholder".tr(), labelText: "recovering.domain_recover_placeholder".tr(),
), ),
), ),
SizedBox(height: 18), SizedBox(height: 16),
BrandButton.rised( BrandButton.rised(
onPressed: () {}, onPressed: formCubitState.isSubmitting
? null
: () => context.read<RecoveryDomainFormCubit>().trySubmit(),
text: "more.continue".tr(), text: "more.continue".tr(),
), ),
], ],
), heroTitle: "recovering.recovery_main_header".tr(),
), heroSubtitle: "recovering.domain_recovery_description".tr(),
hasBackButton: true,
hasFlashButton: false,
heroIcon: Icons.link,
);
}),
); );
} }
}*/ }

View File

@ -3,7 +3,6 @@ import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
/// it's ui helpers use only for ui components, don't use for logic components. /// it's ui helpers use only for ui components, don't use for logic components.
class UiHelpers { class UiHelpers {
static String getDomainName(AppConfigState config) => config.isDomainFilled static String getDomainName(AppConfigState config) =>
? config.cloudFlareDomain!.domainName config.isDomainFilled ? config.serverDomain!.domainName : 'example.com';
: 'example.com';
} }