diff --git a/lib/logic/api_maps/hetzner.dart b/lib/logic/api_maps/hetzner.dart index 0447dfd3..48d4d69e 100644 --- a/lib/logic/api_maps/hetzner.dart +++ b/lib/logic/api_maps/hetzner.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:dio/dio.dart'; import 'package:selfprivacy/config/get_it_config.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/server_details.dart'; import 'package:selfprivacy/logic/models/user.dart'; @@ -93,6 +94,7 @@ class HetznerApi extends ApiMap { required User rootUser, required String domainName, required HetznerDataBase dataBase, + required BackblazeCredential backblazeCredential, }) async { var client = await getClient(); @@ -112,11 +114,15 @@ class HetznerApi extends ApiMap { // var dbId = dbCreateResponse.data['volume']['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"] /// check the branch name, it could be "development" or "master". 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( '/servers', @@ -129,6 +135,7 @@ class HetznerApi extends ApiMap { ip4: serverCreateResponse.data['server']['public_net']['ipv4']['ip'], createTime: DateTime.now(), dataBase: dataBase, + apiToken: apiToken, ); } diff --git a/lib/logic/api_maps/server.dart b/lib/logic/api_maps/server.dart index 04c0f206..ea0d9d40 100644 --- a/lib/logic/api_maps/server.dart +++ b/lib/logic/api_maps/server.dart @@ -20,8 +20,11 @@ class ServerApi extends ApiMap { if (isWithToken) { var cloudFlareDomain = getIt().cloudFlareDomain; var domainName = cloudFlareDomain!.domainName; + var apiToken = getIt().hetznerServer?.apiToken; - options = BaseOptions(baseUrl: 'https://api.$domainName'); + options = BaseOptions(baseUrl: 'https://api.$domainName', headers: { + 'Authorization': 'Bearer ${apiToken}', + }); } return options; @@ -47,18 +50,19 @@ class ServerApi extends ApiMap { Response response; var client = await getClient(); + // POST request with JSON body containing username and password try { response = await client.post( - '/users/create', + '/users', + data: { + 'username': user.login, + 'password': user.password, + }, options: Options( - headers: { - "X-User": user.login, - "X-Password": user.password, - "X-Domain": getIt().cloudFlareDomain!.domainName - }, + contentType: 'application/json', ), ); - res = response.statusCode == HttpStatus.ok; + res = response.statusCode == HttpStatus.created; } catch (e) { print(e); res = false; @@ -99,8 +103,8 @@ class ServerApi extends ApiMap { Future sendSsh(String ssh) async { var client = await getClient(); - client.post( - '/services/ssh/enable', + client.put( + '/services/ssh/key/send', data: {"public_key": ssh}, ); client.close(); diff --git a/lib/logic/cubit/app_config/app_config_cubit.dart b/lib/logic/cubit/app_config/app_config_cubit.dart index 2d65ca45..8c881dc6 100644 --- a/lib/logic/cubit/app_config/app_config_cubit.dart +++ b/lib/logic/cubit/app_config/app_config_cubit.dart @@ -347,6 +347,7 @@ class AppConfigCubit extends Cubit { state.rootUser!, state.cloudFlareDomain!.domainName, state.cloudFlareKey!, + state.backblazeCredential!, onCancel: onCancel, onSuccess: onSuccess, ); diff --git a/lib/logic/cubit/app_config/app_config_repository.dart b/lib/logic/cubit/app_config/app_config_repository.dart index 4a58d766..eb811c45 100644 --- a/lib/logic/cubit/app_config/app_config_repository.dart +++ b/lib/logic/cubit/app_config/app_config_repository.dart @@ -110,7 +110,8 @@ class AppConfigRepository { Future createServer( User rootUser, String domainName, - String cloudFlareKey, { + String cloudFlareKey, + BackblazeCredential backblazeCredential, { required void Function() onCancel, required Future Function(HetznerServerDetails serverDetails) onSuccess, @@ -126,6 +127,7 @@ class AppConfigRepository { rootUser: rootUser, domainName: domainName, dataBase: dataBase, + backblazeCredential: backblazeCredential, ); saveServerDetails(serverDetails); onSuccess(serverDetails); @@ -149,6 +151,7 @@ class AppConfigRepository { rootUser: rootUser, domainName: domainName, dataBase: dataBase, + backblazeCredential: backblazeCredential, ); await saveServerDetails(serverDetails); diff --git a/lib/logic/models/server_details.dart b/lib/logic/models/server_details.dart index 4afbc5cd..f928ebc8 100644 --- a/lib/logic/models/server_details.dart +++ b/lib/logic/models/server_details.dart @@ -9,6 +9,7 @@ class HetznerServerDetails { required this.id, required this.createTime, required this.dataBase, + required this.apiToken, this.startTime, }); @@ -27,6 +28,9 @@ class HetznerServerDetails { @HiveField(4) final HetznerDataBase dataBase; + @HiveField(5) + final String apiToken; + HetznerServerDetails copyWith({DateTime? startTime}) { return HetznerServerDetails( startTime: startTime ?? this.startTime, @@ -34,6 +38,7 @@ class HetznerServerDetails { id: id, ip4: ip4, dataBase: dataBase, + apiToken: apiToken, ); } diff --git a/lib/logic/models/server_details.g.dart b/lib/logic/models/server_details.g.dart index d59c9020..cba8848c 100644 --- a/lib/logic/models/server_details.g.dart +++ b/lib/logic/models/server_details.g.dart @@ -21,6 +21,7 @@ class HetznerServerDetailsAdapter extends TypeAdapter { id: fields[1] as int, createTime: fields[3] as DateTime?, dataBase: fields[4] as HetznerDataBase, + apiToken: fields[5] as String, startTime: fields[2] as DateTime?, ); } @@ -28,7 +29,7 @@ class HetznerServerDetailsAdapter extends TypeAdapter { @override void write(BinaryWriter writer, HetznerServerDetails obj) { writer - ..writeByte(5) + ..writeByte(6) ..writeByte(0) ..write(obj.ip4) ..writeByte(1) @@ -38,7 +39,9 @@ class HetznerServerDetailsAdapter extends TypeAdapter { ..writeByte(2) ..write(obj.startTime) ..writeByte(4) - ..write(obj.dataBase); + ..write(obj.dataBase) + ..writeByte(5) + ..write(obj.apiToken); } @override diff --git a/lib/utils/password_generator.dart b/lib/utils/password_generator.dart index f7bdd2d6..d184a8e3 100644 --- a/lib/utils/password_generator.dart +++ b/lib/utils/password_generator.dart @@ -96,4 +96,11 @@ class StringGenerators { hasUppercaseLetters: true, hasNumbers: true, ); + + static StringGeneratorFunction apiToken = () => getRandomString( + 64, + hasLowercaseLetters: true, + hasUppercaseLetters: true, + hasNumbers: true, + ); }