mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-30 20:56:53 +00:00
add volume
This commit is contained in:
parent
275ba21a47
commit
ae3ec309cb
|
@ -16,6 +16,7 @@ class HiveConfig {
|
||||||
Hive.registerAdapter(HetznerServerDetailsAdapter());
|
Hive.registerAdapter(HetznerServerDetailsAdapter());
|
||||||
Hive.registerAdapter(CloudFlareDomainAdapter());
|
Hive.registerAdapter(CloudFlareDomainAdapter());
|
||||||
Hive.registerAdapter(BackblazeCredentialAdapter());
|
Hive.registerAdapter(BackblazeCredentialAdapter());
|
||||||
|
Hive.registerAdapter(HetznerDataBaseAdapter());
|
||||||
|
|
||||||
await Hive.openBox(BNames.appSettings);
|
await Hive.openBox(BNames.appSettings);
|
||||||
var cipher = HiveAesCipher(await getEncriptedKey());
|
var cipher = HiveAesCipher(await getEncriptedKey());
|
||||||
|
|
|
@ -55,6 +55,19 @@ class HetznerApi extends ApiMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> isFreeToCreate() async {
|
||||||
|
var client = await getClient();
|
||||||
|
|
||||||
|
Response serversReponse = await client.get('/servers');
|
||||||
|
List servers = serversReponse.data['servers'];
|
||||||
|
var server = servers.firstWhere(
|
||||||
|
(el) => el['name'] == 'selfprivacy-server',
|
||||||
|
orElse: null,
|
||||||
|
);
|
||||||
|
client.close();
|
||||||
|
return server == null;
|
||||||
|
}
|
||||||
|
|
||||||
Future<HetznerServerDetails> createServer({
|
Future<HetznerServerDetails> createServer({
|
||||||
required String cloudFlareKey,
|
required String cloudFlareKey,
|
||||||
required User rootUser,
|
required User rootUser,
|
||||||
|
@ -62,31 +75,71 @@ class HetznerApi extends ApiMap {
|
||||||
}) async {
|
}) async {
|
||||||
var dbPassword = getRandomString(40);
|
var dbPassword = getRandomString(40);
|
||||||
|
|
||||||
|
const chars =
|
||||||
|
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
|
||||||
|
|
||||||
|
var dbStorageName = getRandomString(6, chars);
|
||||||
|
var client = await getClient();
|
||||||
|
|
||||||
|
Response dbCreateResponse = await client.post(
|
||||||
|
'/volumes',
|
||||||
|
data: {
|
||||||
|
"size": 10,
|
||||||
|
"name": dbStorageName,
|
||||||
|
"labels": {"labelkey": "value"},
|
||||||
|
"location": "fsn1",
|
||||||
|
"automount": false,
|
||||||
|
"format": "ext4"
|
||||||
|
},
|
||||||
|
);
|
||||||
|
var dbId = dbCreateResponse.data['volume']['id'];
|
||||||
var data = jsonDecode(
|
var data = jsonDecode(
|
||||||
'''{"name":"selfprivacy-server","server_type":"cx11","start_after_create":false,"image":"ubuntu-20.04", "volumes":[],"networks":[],"user_data":"#cloud-config\\nruncmd:\\n- curl https://git.selfprivacy.org/ilchub/selfprivacy-nixos-infect/raw/branch/master/nixos-infect | PROVIDER=hetzner NIX_CHANNEL=nixos-20.09 DOMAIN=$domainName LUSER=${rootUser.login} PASSWORD=${rootUser.password} HASHED_PASSWORD=${rootUser.hashPassword} CF_TOKEN=$cloudFlareKey DB_PASSWORD=$dbPassword bash 2>&1 | tee /tmp/infect.log","labels":{},"automount":false}''',
|
'''{"name":"selfprivacy-server","server_type":"cx11","start_after_create":false,"image":"ubuntu-20.04", "volumes":[$dbId],"networks":[],"user_data":"#cloud-config\\nruncmd:\\n- curl https://git.selfprivacy.org/ilchub/selfprivacy-nixos-infect/raw/branch/master/nixos-infect | PROVIDER=hetzner NIX_CHANNEL=nixos-20.09 DOMAIN=$domainName LUSER=${rootUser.login} PASSWORD=${rootUser.password} HASHED_PASSWORD=${rootUser.hashPassword} CF_TOKEN=$cloudFlareKey DB_PASSWORD=$dbPassword bash 2>&1 | tee /tmp/infect.log","labels":{},"automount":true, "location": "fsn1"}''',
|
||||||
);
|
);
|
||||||
|
|
||||||
var client = await getClient();
|
Response serverCreateResponse = await client.post(
|
||||||
Response response = await client.post(
|
|
||||||
'/servers',
|
'/servers',
|
||||||
data: data,
|
data: data,
|
||||||
);
|
);
|
||||||
client.close();
|
client.close();
|
||||||
return HetznerServerDetails(
|
return HetznerServerDetails(
|
||||||
id: response.data['server']['id'],
|
id: serverCreateResponse.data['server']['id'],
|
||||||
ip4: response.data['server']['public_net']['ipv4']['ip'],
|
ip4: serverCreateResponse.data['server']['public_net']['ipv4']['ip'],
|
||||||
createTime: DateTime.now(),
|
createTime: DateTime.now(),
|
||||||
|
dataBase: HetznerDataBase(
|
||||||
|
id: dbId,
|
||||||
|
name: dbCreateResponse.data['volume']['name'],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteSelfprivacyServer() async {
|
Future<void> deleteSelfprivacyServerAndAllVolumes() async {
|
||||||
var client = await getClient();
|
var client = await getClient();
|
||||||
Response response = await client.get('/servers');
|
|
||||||
|
|
||||||
List list = response.data['servers'];
|
Response serversReponse = await client.get('/servers');
|
||||||
var server = list.firstWhere((el) => el['name'] == 'selfprivacy-server');
|
List servers = serversReponse.data['servers'];
|
||||||
|
var server = servers.firstWhere((el) => el['name'] == 'selfprivacy-server');
|
||||||
await client.delete('/servers/${server['id']}');
|
await client.delete('/servers/${server['id']}');
|
||||||
|
|
||||||
|
Response volumesReponse = await client.get('/volumes');
|
||||||
|
List volumes = volumesReponse.data['volumes'];
|
||||||
|
|
||||||
|
var laterFutures = <Future>[];
|
||||||
|
for (var volume in volumes) {
|
||||||
|
if (volume['server'] == null) {
|
||||||
|
await client.delete('/volumes/${volume['id']}');
|
||||||
|
} else {
|
||||||
|
laterFutures.add(Future.delayed(Duration(seconds: 60)).then(
|
||||||
|
(_) => client.delete('/volumes/${volume['id']}'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (laterFutures.isEmpty) {
|
||||||
close(client);
|
close(client);
|
||||||
|
} else {
|
||||||
|
Future.wait(laterFutures).then((value) => close(client));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<HetznerServerDetails> startServer({
|
Future<HetznerServerDetails> startServer({
|
||||||
|
|
|
@ -202,7 +202,7 @@ class AppConfigCubit extends Cubit<AppConfigState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearAppConfig() {
|
void clearAppConfig() {
|
||||||
_closeTimer();
|
closeTimer();
|
||||||
repository.clearAppConfig();
|
repository.clearAppConfig();
|
||||||
emit(InitialAppConfigState());
|
emit(InitialAppConfigState());
|
||||||
}
|
}
|
||||||
|
@ -263,17 +263,16 @@ class AppConfigCubit extends Cubit<AppConfigState> {
|
||||||
onSuccess: onSuccess,
|
onSuccess: onSuccess,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
addError(e);
|
|
||||||
emit(_stateCopy);
|
emit(_stateCopy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
_closeTimer();
|
closeTimer();
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _closeTimer() {
|
void closeTimer() {
|
||||||
if (timer != null && timer!.isActive) {
|
if (timer != null && timer!.isActive) {
|
||||||
timer!.cancel();
|
timer!.cancel();
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ class AppConfigRepository {
|
||||||
text: 'basis.delete'.tr(),
|
text: 'basis.delete'.tr(),
|
||||||
isRed: true,
|
isRed: true,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await hetznerApi.deleteSelfprivacyServer();
|
await hetznerApi.deleteSelfprivacyServerAndAllVolumes();
|
||||||
|
|
||||||
var serverDetails = await hetznerApi.createServer(
|
var serverDetails = await hetznerApi.createServer(
|
||||||
cloudFlareKey: cloudFlareKey,
|
cloudFlareKey: cloudFlareKey,
|
||||||
|
|
|
@ -92,6 +92,8 @@ class AppConfigState extends Equatable {
|
||||||
isServerReseted,
|
isServerReseted,
|
||||||
hasFinalChecked,
|
hasFinalChecked,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
print(res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||||
class TimerModel extends ChangeNotifier {
|
class TimerModel extends ChangeNotifier {
|
||||||
DateTime _time = DateTime.now();
|
DateTime _time = DateTime.now();
|
||||||
|
|
||||||
DateTime get messages => _time;
|
DateTime get time => _time;
|
||||||
|
|
||||||
void restart() {
|
void restart() {
|
||||||
_time = DateTime.now();
|
_time = DateTime.now();
|
||||||
|
|
|
@ -8,14 +8,15 @@ class HetznerServerDetails {
|
||||||
required this.ip4,
|
required this.ip4,
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.createTime,
|
required this.createTime,
|
||||||
|
required this.dataBase,
|
||||||
this.startTime,
|
this.startTime,
|
||||||
});
|
});
|
||||||
|
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
final String? ip4;
|
final String ip4;
|
||||||
|
|
||||||
@HiveField(1)
|
@HiveField(1)
|
||||||
final int? id;
|
final int id;
|
||||||
|
|
||||||
@HiveField(3)
|
@HiveField(3)
|
||||||
final DateTime? createTime;
|
final DateTime? createTime;
|
||||||
|
@ -23,14 +24,31 @@ class HetznerServerDetails {
|
||||||
@HiveField(2)
|
@HiveField(2)
|
||||||
final DateTime? startTime;
|
final DateTime? startTime;
|
||||||
|
|
||||||
|
@HiveField(4)
|
||||||
|
final HetznerDataBase dataBase;
|
||||||
|
|
||||||
HetznerServerDetails copyWith({DateTime? startTime}) {
|
HetznerServerDetails copyWith({DateTime? startTime}) {
|
||||||
return HetznerServerDetails(
|
return HetznerServerDetails(
|
||||||
startTime: startTime ?? this.startTime,
|
startTime: startTime ?? this.startTime,
|
||||||
createTime: createTime,
|
createTime: createTime,
|
||||||
id: id,
|
id: id,
|
||||||
ip4: ip4,
|
ip4: ip4,
|
||||||
|
dataBase: dataBase,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String toString() => id.toString();
|
String toString() => id.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@HiveType(typeId: 5)
|
||||||
|
class HetznerDataBase {
|
||||||
|
HetznerDataBase({
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
});
|
||||||
|
|
||||||
|
@HiveField(1)
|
||||||
|
int id;
|
||||||
|
@HiveField(2)
|
||||||
|
String name;
|
||||||
|
}
|
||||||
|
|
|
@ -17,9 +17,10 @@ class HetznerServerDetailsAdapter extends TypeAdapter<HetznerServerDetails> {
|
||||||
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 HetznerServerDetails(
|
||||||
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,
|
||||||
startTime: fields[2] as DateTime?,
|
startTime: fields[2] as DateTime?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -27,7 +28,7 @@ class HetznerServerDetailsAdapter extends TypeAdapter<HetznerServerDetails> {
|
||||||
@override
|
@override
|
||||||
void write(BinaryWriter writer, HetznerServerDetails obj) {
|
void write(BinaryWriter writer, HetznerServerDetails obj) {
|
||||||
writer
|
writer
|
||||||
..writeByte(4)
|
..writeByte(5)
|
||||||
..writeByte(0)
|
..writeByte(0)
|
||||||
..write(obj.ip4)
|
..write(obj.ip4)
|
||||||
..writeByte(1)
|
..writeByte(1)
|
||||||
|
@ -35,7 +36,9 @@ class HetznerServerDetailsAdapter extends TypeAdapter<HetznerServerDetails> {
|
||||||
..writeByte(3)
|
..writeByte(3)
|
||||||
..write(obj.createTime)
|
..write(obj.createTime)
|
||||||
..writeByte(2)
|
..writeByte(2)
|
||||||
..write(obj.startTime);
|
..write(obj.startTime)
|
||||||
|
..writeByte(4)
|
||||||
|
..write(obj.dataBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -48,3 +51,40 @@ class HetznerServerDetailsAdapter extends TypeAdapter<HetznerServerDetails> {
|
||||||
runtimeType == other.runtimeType &&
|
runtimeType == other.runtimeType &&
|
||||||
typeId == other.typeId;
|
typeId == other.typeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class HetznerDataBaseAdapter extends TypeAdapter<HetznerDataBase> {
|
||||||
|
@override
|
||||||
|
final int typeId = 5;
|
||||||
|
|
||||||
|
@override
|
||||||
|
HetznerDataBase read(BinaryReader reader) {
|
||||||
|
final numOfFields = reader.readByte();
|
||||||
|
final fields = <int, dynamic>{
|
||||||
|
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||||
|
};
|
||||||
|
return HetznerDataBase(
|
||||||
|
id: fields[1] as int,
|
||||||
|
name: fields[2] as String,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void write(BinaryWriter writer, HetznerDataBase obj) {
|
||||||
|
writer
|
||||||
|
..writeByte(2)
|
||||||
|
..writeByte(1)
|
||||||
|
..write(obj.id)
|
||||||
|
..writeByte(2)
|
||||||
|
..write(obj.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => typeId.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is HetznerDataBaseAdapter &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
typeId == other.typeId;
|
||||||
|
}
|
||||||
|
|
|
@ -407,8 +407,9 @@ class InitializingPage extends StatelessWidget {
|
||||||
BrandText.body2('initializing.11'.tr()),
|
BrandText.body2('initializing.11'.tr()),
|
||||||
Spacer(),
|
Spacer(),
|
||||||
BrandButton.rised(
|
BrandButton.rised(
|
||||||
onPressed:
|
onPressed: isLoading!
|
||||||
isLoading! ? null : () => appConfigCubit.createServerAndSetDnsRecords(),
|
? null
|
||||||
|
: () => appConfigCubit.createServerAndSetDnsRecords(),
|
||||||
title: isLoading ? 'basis.loading'.tr() : 'initializing.11'.tr(),
|
title: isLoading ? 'basis.loading'.tr() : 'initializing.11'.tr(),
|
||||||
),
|
),
|
||||||
Spacer(flex: 2),
|
Spacer(flex: 2),
|
||||||
|
|
|
@ -4,11 +4,11 @@ const _chars =
|
||||||
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890_';
|
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890_';
|
||||||
Random _rnd = Random();
|
Random _rnd = Random();
|
||||||
|
|
||||||
String getRandomString(int length) => String.fromCharCodes(
|
String getRandomString(int length, [chars = _chars]) => String.fromCharCodes(
|
||||||
Iterable.generate(
|
Iterable.generate(
|
||||||
length,
|
length,
|
||||||
(_) => _chars.codeUnitAt(
|
(_) => chars.codeUnitAt(
|
||||||
_rnd.nextInt(_chars.length),
|
_rnd.nextInt(chars.length),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue