mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-27 11:16:45 +00:00
Hotfix SPCVE-0001
This commit is contained in:
parent
08ff445935
commit
6011d6fdce
|
@ -4,6 +4,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/backblaze_credential.dart';
|
||||||
import 'package:selfprivacy/logic/models/hetzner_server_info.dart';
|
import 'package:selfprivacy/logic/models/hetzner_server_info.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';
|
||||||
|
@ -93,6 +94,7 @@ class HetznerApi extends ApiMap {
|
||||||
required User rootUser,
|
required User rootUser,
|
||||||
required String domainName,
|
required String domainName,
|
||||||
required HetznerDataBase dataBase,
|
required HetznerDataBase dataBase,
|
||||||
|
required BackblazeCredential backblazeCredential,
|
||||||
}) async {
|
}) async {
|
||||||
var client = await getClient();
|
var client = await getClient();
|
||||||
|
|
||||||
|
@ -112,11 +114,15 @@ class HetznerApi extends ApiMap {
|
||||||
// var dbId = dbCreateResponse.data['volume']['id'];
|
// var dbId = dbCreateResponse.data['volume']['id'];
|
||||||
var dbId = dataBase.id;
|
var dbId = dataBase.id;
|
||||||
|
|
||||||
|
final apiToken = StringGenerators.apiToken();
|
||||||
|
|
||||||
|
final hostname = domainName.split('.')[0];
|
||||||
|
|
||||||
/// add ssh key when you need it: e.g. "ssh_keys":["kherel"]
|
/// add ssh key when you need it: e.g. "ssh_keys":["kherel"]
|
||||||
/// check the branch name, it could be "development" or "master".
|
/// check the branch name, it could be "development" or "master".
|
||||||
|
|
||||||
var data = jsonDecode(
|
var data = jsonDecode(
|
||||||
'''{"name":"$domainName","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/development/nixos-infect | PROVIDER=hetzner NIX_CHANNEL=nixos-21.05 DOMAIN=$domainName LUSER=${rootUser.login} PASSWORD=${rootUser.password} CF_TOKEN=$cloudFlareKey DB_PASSWORD=$dbPassword bash 2>&1 | tee /tmp/infect.log","labels":{},"automount":true, "location": "fsn1"}''');
|
'''{"name":"$domainName","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/SelfPrivacy/selfprivacy-nixos-infect/raw/branch/master/nixos-infect | PROVIDER=hetzner NIX_CHANNEL=nixos-21.05 DOMAIN=$domainName LUSER=${rootUser.login} PASSWORD=${rootUser.password} CF_TOKEN=$cloudFlareKey DB_PASSWORD=$dbPassword BACKBLAZE_KEY_ID=${backblazeCredential.keyId} BACKBLAZE_ACCOUNT_KEY=${backblazeCredential.applicationKey} API_TOKEN=$apiToken HOSTNAME=$hostname bash 2>&1 | tee /tmp/infect.log","labels":{},"automount":true, "location": "fsn1"}''');
|
||||||
|
|
||||||
Response serverCreateResponse = await client.post(
|
Response serverCreateResponse = await client.post(
|
||||||
'/servers',
|
'/servers',
|
||||||
|
@ -129,6 +135,7 @@ class HetznerApi extends ApiMap {
|
||||||
ip4: serverCreateResponse.data['server']['public_net']['ipv4']['ip'],
|
ip4: serverCreateResponse.data['server']['public_net']['ipv4']['ip'],
|
||||||
createTime: DateTime.now(),
|
createTime: DateTime.now(),
|
||||||
dataBase: dataBase,
|
dataBase: dataBase,
|
||||||
|
apiToken: apiToken,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,11 @@ class ServerApi extends ApiMap {
|
||||||
if (isWithToken) {
|
if (isWithToken) {
|
||||||
var cloudFlareDomain = getIt<ApiConfigModel>().cloudFlareDomain;
|
var cloudFlareDomain = getIt<ApiConfigModel>().cloudFlareDomain;
|
||||||
var domainName = cloudFlareDomain!.domainName;
|
var domainName = cloudFlareDomain!.domainName;
|
||||||
|
var apiToken = getIt<ApiConfigModel>().hetznerServer?.apiToken;
|
||||||
|
|
||||||
options = BaseOptions(baseUrl: 'https://api.$domainName');
|
options = BaseOptions(baseUrl: 'https://api.$domainName', headers: {
|
||||||
|
'Authorization': 'Bearer ${apiToken}',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
|
@ -47,18 +50,19 @@ class ServerApi extends ApiMap {
|
||||||
Response response;
|
Response response;
|
||||||
|
|
||||||
var client = await getClient();
|
var client = await getClient();
|
||||||
|
// POST request with JSON body containing username and password
|
||||||
try {
|
try {
|
||||||
response = await client.post(
|
response = await client.post(
|
||||||
'/users/create',
|
'/users',
|
||||||
|
data: {
|
||||||
|
'username': user.login,
|
||||||
|
'password': user.password,
|
||||||
|
},
|
||||||
options: Options(
|
options: Options(
|
||||||
headers: {
|
contentType: 'application/json',
|
||||||
"X-User": user.login,
|
|
||||||
"X-Password": user.password,
|
|
||||||
"X-Domain": getIt<ApiConfigModel>().cloudFlareDomain!.domainName
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
res = response.statusCode == HttpStatus.ok;
|
res = response.statusCode == HttpStatus.created;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e);
|
print(e);
|
||||||
res = false;
|
res = false;
|
||||||
|
@ -99,8 +103,8 @@ class ServerApi extends ApiMap {
|
||||||
|
|
||||||
Future<void> sendSsh(String ssh) async {
|
Future<void> sendSsh(String ssh) async {
|
||||||
var client = await getClient();
|
var client = await getClient();
|
||||||
client.post(
|
client.put(
|
||||||
'/services/ssh/enable',
|
'/services/ssh/key/send',
|
||||||
data: {"public_key": ssh},
|
data: {"public_key": ssh},
|
||||||
);
|
);
|
||||||
client.close();
|
client.close();
|
||||||
|
|
|
@ -347,6 +347,7 @@ class AppConfigCubit extends Cubit<AppConfigState> {
|
||||||
state.rootUser!,
|
state.rootUser!,
|
||||||
state.cloudFlareDomain!.domainName,
|
state.cloudFlareDomain!.domainName,
|
||||||
state.cloudFlareKey!,
|
state.cloudFlareKey!,
|
||||||
|
state.backblazeCredential!,
|
||||||
onCancel: onCancel,
|
onCancel: onCancel,
|
||||||
onSuccess: onSuccess,
|
onSuccess: onSuccess,
|
||||||
);
|
);
|
||||||
|
|
|
@ -110,7 +110,8 @@ class AppConfigRepository {
|
||||||
Future<void> createServer(
|
Future<void> createServer(
|
||||||
User rootUser,
|
User rootUser,
|
||||||
String domainName,
|
String domainName,
|
||||||
String cloudFlareKey, {
|
String cloudFlareKey,
|
||||||
|
BackblazeCredential backblazeCredential, {
|
||||||
required void Function() onCancel,
|
required void Function() onCancel,
|
||||||
required Future<void> Function(HetznerServerDetails serverDetails)
|
required Future<void> Function(HetznerServerDetails serverDetails)
|
||||||
onSuccess,
|
onSuccess,
|
||||||
|
@ -126,6 +127,7 @@ class AppConfigRepository {
|
||||||
rootUser: rootUser,
|
rootUser: rootUser,
|
||||||
domainName: domainName,
|
domainName: domainName,
|
||||||
dataBase: dataBase,
|
dataBase: dataBase,
|
||||||
|
backblazeCredential: backblazeCredential,
|
||||||
);
|
);
|
||||||
saveServerDetails(serverDetails);
|
saveServerDetails(serverDetails);
|
||||||
onSuccess(serverDetails);
|
onSuccess(serverDetails);
|
||||||
|
@ -149,6 +151,7 @@ class AppConfigRepository {
|
||||||
rootUser: rootUser,
|
rootUser: rootUser,
|
||||||
domainName: domainName,
|
domainName: domainName,
|
||||||
dataBase: dataBase,
|
dataBase: dataBase,
|
||||||
|
backblazeCredential: backblazeCredential,
|
||||||
);
|
);
|
||||||
|
|
||||||
await saveServerDetails(serverDetails);
|
await saveServerDetails(serverDetails);
|
||||||
|
|
|
@ -9,6 +9,7 @@ class HetznerServerDetails {
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.createTime,
|
required this.createTime,
|
||||||
required this.dataBase,
|
required this.dataBase,
|
||||||
|
required this.apiToken,
|
||||||
this.startTime,
|
this.startTime,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -27,6 +28,9 @@ class HetznerServerDetails {
|
||||||
@HiveField(4)
|
@HiveField(4)
|
||||||
final HetznerDataBase dataBase;
|
final HetznerDataBase dataBase;
|
||||||
|
|
||||||
|
@HiveField(5)
|
||||||
|
final String apiToken;
|
||||||
|
|
||||||
HetznerServerDetails copyWith({DateTime? startTime}) {
|
HetznerServerDetails copyWith({DateTime? startTime}) {
|
||||||
return HetznerServerDetails(
|
return HetznerServerDetails(
|
||||||
startTime: startTime ?? this.startTime,
|
startTime: startTime ?? this.startTime,
|
||||||
|
@ -34,6 +38,7 @@ class HetznerServerDetails {
|
||||||
id: id,
|
id: id,
|
||||||
ip4: ip4,
|
ip4: ip4,
|
||||||
dataBase: dataBase,
|
dataBase: dataBase,
|
||||||
|
apiToken: apiToken,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ class HetznerServerDetailsAdapter extends TypeAdapter<HetznerServerDetails> {
|
||||||
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 HetznerDataBase,
|
||||||
|
apiToken: fields[5] as String,
|
||||||
startTime: fields[2] as DateTime?,
|
startTime: fields[2] as DateTime?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -28,7 +29,7 @@ class HetznerServerDetailsAdapter extends TypeAdapter<HetznerServerDetails> {
|
||||||
@override
|
@override
|
||||||
void write(BinaryWriter writer, HetznerServerDetails obj) {
|
void write(BinaryWriter writer, HetznerServerDetails obj) {
|
||||||
writer
|
writer
|
||||||
..writeByte(5)
|
..writeByte(6)
|
||||||
..writeByte(0)
|
..writeByte(0)
|
||||||
..write(obj.ip4)
|
..write(obj.ip4)
|
||||||
..writeByte(1)
|
..writeByte(1)
|
||||||
|
@ -38,7 +39,9 @@ class HetznerServerDetailsAdapter extends TypeAdapter<HetznerServerDetails> {
|
||||||
..writeByte(2)
|
..writeByte(2)
|
||||||
..write(obj.startTime)
|
..write(obj.startTime)
|
||||||
..writeByte(4)
|
..writeByte(4)
|
||||||
..write(obj.dataBase);
|
..write(obj.dataBase)
|
||||||
|
..writeByte(5)
|
||||||
|
..write(obj.apiToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -96,4 +96,11 @@ class StringGenerators {
|
||||||
hasUppercaseLetters: true,
|
hasUppercaseLetters: true,
|
||||||
hasNumbers: true,
|
hasNumbers: true,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static StringGeneratorFunction apiToken = () => getRandomString(
|
||||||
|
64,
|
||||||
|
hasLowercaseLetters: true,
|
||||||
|
hasUppercaseLetters: true,
|
||||||
|
hasNumbers: true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue