mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-29 12:16:55 +00:00
add volume
This commit is contained in:
parent
275ba21a47
commit
ae3ec309cb
|
@ -16,6 +16,7 @@ class HiveConfig {
|
|||
Hive.registerAdapter(HetznerServerDetailsAdapter());
|
||||
Hive.registerAdapter(CloudFlareDomainAdapter());
|
||||
Hive.registerAdapter(BackblazeCredentialAdapter());
|
||||
Hive.registerAdapter(HetznerDataBaseAdapter());
|
||||
|
||||
await Hive.openBox(BNames.appSettings);
|
||||
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({
|
||||
required String cloudFlareKey,
|
||||
required User rootUser,
|
||||
|
@ -62,31 +75,71 @@ class HetznerApi extends ApiMap {
|
|||
}) async {
|
||||
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(
|
||||
'''{"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 response = await client.post(
|
||||
Response serverCreateResponse = await client.post(
|
||||
'/servers',
|
||||
data: data,
|
||||
);
|
||||
client.close();
|
||||
return HetznerServerDetails(
|
||||
id: response.data['server']['id'],
|
||||
ip4: response.data['server']['public_net']['ipv4']['ip'],
|
||||
id: serverCreateResponse.data['server']['id'],
|
||||
ip4: serverCreateResponse.data['server']['public_net']['ipv4']['ip'],
|
||||
createTime: DateTime.now(),
|
||||
dataBase: HetznerDataBase(
|
||||
id: dbId,
|
||||
name: dbCreateResponse.data['volume']['name'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteSelfprivacyServer() async {
|
||||
Future<void> deleteSelfprivacyServerAndAllVolumes() async {
|
||||
var client = await getClient();
|
||||
Response response = await client.get('/servers');
|
||||
|
||||
List list = response.data['servers'];
|
||||
var server = list.firstWhere((el) => el['name'] == 'selfprivacy-server');
|
||||
Response serversReponse = await client.get('/servers');
|
||||
List servers = serversReponse.data['servers'];
|
||||
var server = servers.firstWhere((el) => el['name'] == 'selfprivacy-server');
|
||||
await client.delete('/servers/${server['id']}');
|
||||
close(client);
|
||||
|
||||
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);
|
||||
} else {
|
||||
Future.wait(laterFutures).then((value) => close(client));
|
||||
}
|
||||
}
|
||||
|
||||
Future<HetznerServerDetails> startServer({
|
||||
|
|
|
@ -202,7 +202,7 @@ class AppConfigCubit extends Cubit<AppConfigState> {
|
|||
}
|
||||
|
||||
void clearAppConfig() {
|
||||
_closeTimer();
|
||||
closeTimer();
|
||||
repository.clearAppConfig();
|
||||
emit(InitialAppConfigState());
|
||||
}
|
||||
|
@ -263,17 +263,16 @@ class AppConfigCubit extends Cubit<AppConfigState> {
|
|||
onSuccess: onSuccess,
|
||||
);
|
||||
} catch (e) {
|
||||
addError(e);
|
||||
emit(_stateCopy);
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
_closeTimer();
|
||||
closeTimer();
|
||||
return super.close();
|
||||
}
|
||||
|
||||
void _closeTimer() {
|
||||
void closeTimer() {
|
||||
if (timer != null && timer!.isActive) {
|
||||
timer!.cancel();
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ class AppConfigRepository {
|
|||
text: 'basis.delete'.tr(),
|
||||
isRed: true,
|
||||
onPressed: () async {
|
||||
await hetznerApi.deleteSelfprivacyServer();
|
||||
await hetznerApi.deleteSelfprivacyServerAndAllVolumes();
|
||||
|
||||
var serverDetails = await hetznerApi.createServer(
|
||||
cloudFlareKey: cloudFlareKey,
|
||||
|
|
|
@ -92,6 +92,8 @@ class AppConfigState extends Equatable {
|
|||
isServerReseted,
|
||||
hasFinalChecked,
|
||||
];
|
||||
|
||||
print(res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
|||
class TimerModel extends ChangeNotifier {
|
||||
DateTime _time = DateTime.now();
|
||||
|
||||
DateTime get messages => _time;
|
||||
DateTime get time => _time;
|
||||
|
||||
void restart() {
|
||||
_time = DateTime.now();
|
||||
|
|
|
@ -8,14 +8,15 @@ class HetznerServerDetails {
|
|||
required this.ip4,
|
||||
required this.id,
|
||||
required this.createTime,
|
||||
required this.dataBase,
|
||||
this.startTime,
|
||||
});
|
||||
|
||||
@HiveField(0)
|
||||
final String? ip4;
|
||||
final String ip4;
|
||||
|
||||
@HiveField(1)
|
||||
final int? id;
|
||||
final int id;
|
||||
|
||||
@HiveField(3)
|
||||
final DateTime? createTime;
|
||||
|
@ -23,14 +24,31 @@ class HetznerServerDetails {
|
|||
@HiveField(2)
|
||||
final DateTime? startTime;
|
||||
|
||||
@HiveField(4)
|
||||
final HetznerDataBase dataBase;
|
||||
|
||||
HetznerServerDetails copyWith({DateTime? startTime}) {
|
||||
return HetznerServerDetails(
|
||||
startTime: startTime ?? this.startTime,
|
||||
createTime: createTime,
|
||||
id: id,
|
||||
ip4: ip4,
|
||||
dataBase: dataBase,
|
||||
);
|
||||
}
|
||||
|
||||
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(),
|
||||
};
|
||||
return HetznerServerDetails(
|
||||
ip4: fields[0] as String?,
|
||||
id: fields[1] as int?,
|
||||
ip4: fields[0] as String,
|
||||
id: fields[1] as int,
|
||||
createTime: fields[3] as DateTime?,
|
||||
dataBase: fields[4] as HetznerDataBase,
|
||||
startTime: fields[2] as DateTime?,
|
||||
);
|
||||
}
|
||||
|
@ -27,7 +28,7 @@ class HetznerServerDetailsAdapter extends TypeAdapter<HetznerServerDetails> {
|
|||
@override
|
||||
void write(BinaryWriter writer, HetznerServerDetails obj) {
|
||||
writer
|
||||
..writeByte(4)
|
||||
..writeByte(5)
|
||||
..writeByte(0)
|
||||
..write(obj.ip4)
|
||||
..writeByte(1)
|
||||
|
@ -35,7 +36,9 @@ class HetznerServerDetailsAdapter extends TypeAdapter<HetznerServerDetails> {
|
|||
..writeByte(3)
|
||||
..write(obj.createTime)
|
||||
..writeByte(2)
|
||||
..write(obj.startTime);
|
||||
..write(obj.startTime)
|
||||
..writeByte(4)
|
||||
..write(obj.dataBase);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -48,3 +51,40 @@ class HetznerServerDetailsAdapter extends TypeAdapter<HetznerServerDetails> {
|
|||
runtimeType == other.runtimeType &&
|
||||
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()),
|
||||
Spacer(),
|
||||
BrandButton.rised(
|
||||
onPressed:
|
||||
isLoading! ? null : () => appConfigCubit.createServerAndSetDnsRecords(),
|
||||
onPressed: isLoading!
|
||||
? null
|
||||
: () => appConfigCubit.createServerAndSetDnsRecords(),
|
||||
title: isLoading ? 'basis.loading'.tr() : 'initializing.11'.tr(),
|
||||
),
|
||||
Spacer(flex: 2),
|
||||
|
|
|
@ -4,11 +4,11 @@ const _chars =
|
|||
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890_';
|
||||
Random _rnd = Random();
|
||||
|
||||
String getRandomString(int length) => String.fromCharCodes(
|
||||
String getRandomString(int length, [chars = _chars]) => String.fromCharCodes(
|
||||
Iterable.generate(
|
||||
length,
|
||||
(_) => _chars.codeUnitAt(
|
||||
_rnd.nextInt(_chars.length),
|
||||
(_) => chars.codeUnitAt(
|
||||
_rnd.nextInt(chars.length),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue