#include "apiController.h" #include #include #include #include #include "configurators/openvpn_configurator.h" #include "configurators/wireguard_configurator.h" #include "core/errorstrings.h" namespace { namespace configKey { constexpr char cloak[] = "cloak"; constexpr char awg[] = "awg"; constexpr char apiEdnpoint[] = "api_endpoint"; constexpr char accessToken[] = "api_key"; constexpr char certificate[] = "certificate"; constexpr char publicKey[] = "public_key"; constexpr char protocol[] = "protocol"; } } ApiController::ApiController(const QSharedPointer &serversModel, const QSharedPointer &containersModel, QObject *parent) : QObject(parent), m_serversModel(serversModel), m_containersModel(containersModel) { } void ApiController::processApiConfig(const QString &protocol, const ApiController::ApiPayloadData &apiPayloadData, QString &config) { if (protocol == configKey::cloak) { config.replace("", "\n"); config.replace("$OPENVPN_PRIV_KEY", apiPayloadData.certRequest.privKey); return; } else if (protocol == configKey::awg) { config.replace("$WIREGUARD_CLIENT_PRIVATE_KEY", apiPayloadData.wireGuardClientPrivKey); } return; } ApiController::ApiPayloadData ApiController::generateApiPayloadData(const QString &protocol) { ApiController::ApiPayloadData apiPayload; if (protocol == configKey::cloak) { apiPayload.certRequest = OpenVpnConfigurator::createCertRequest(); } else if (protocol == configKey::awg) { auto connData = WireguardConfigurator::genClientKeys(); apiPayload.wireGuardClientPubKey = connData.clientPubKey; apiPayload.wireGuardClientPrivKey = connData.clientPrivKey; } return apiPayload; } QJsonObject ApiController::fillApiPayload(const QString &protocol, const ApiController::ApiPayloadData &apiPayloadData) { QJsonObject obj; if (protocol == configKey::cloak) { obj[configKey::certificate] = apiPayloadData.certRequest.request; } else if (protocol == configKey::awg) { obj[configKey::publicKey] = apiPayloadData.wireGuardClientPubKey; } return obj; } void ApiController::updateServerConfigFromApi() { QtConcurrent::run([this]() { if (m_isConfigUpdateStarted) { emit updateFinished(false); return; } auto serverConfig = m_serversModel->getDefaultServerConfig(); auto containerConfig = serverConfig.value(config_key::containers).toArray(); if (serverConfig.value(config_key::configVersion).toInt() && containerConfig.isEmpty()) { emit updateStarted(); m_isConfigUpdateStarted = true; QNetworkAccessManager manager; QNetworkRequest request; request.setTransferTimeout(7000); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setRawHeader("Authorization", "Api-Key " + serverConfig.value(configKey::accessToken).toString().toUtf8()); QString endpoint = serverConfig.value(configKey::apiEdnpoint).toString(); request.setUrl(endpoint); QString protocol = serverConfig.value(configKey::protocol).toString(); auto apiPayloadData = generateApiPayloadData(protocol); QByteArray requestBody = QJsonDocument(fillApiPayload(protocol, apiPayloadData)).toJson(); QScopedPointer reply; reply.reset(manager.post(request, requestBody)); QEventLoop wait; QObject::connect(reply.get(), &QNetworkReply::finished, &wait, &QEventLoop::quit); wait.exec(); if (reply->error() == QNetworkReply::NoError) { QString contents = QString::fromUtf8(reply->readAll()); auto data = QJsonDocument::fromJson(contents.toUtf8()).object().value(config_key::config).toString(); data.replace("vpn://", ""); QByteArray ba = QByteArray::fromBase64(data.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); if (ba.isEmpty()) { emit errorOccurred(errorString(ApiConfigDownloadError)); m_isConfigUpdateStarted = false; return; } QByteArray ba_uncompressed = qUncompress(ba); if (!ba_uncompressed.isEmpty()) { ba = ba_uncompressed; } QString configStr = ba; processApiConfig(protocol, apiPayloadData, configStr); QJsonObject apiConfig = QJsonDocument::fromJson(configStr.toUtf8()).object(); serverConfig.insert(config_key::dns1, apiConfig.value(config_key::dns1)); serverConfig.insert(config_key::dns2, apiConfig.value(config_key::dns2)); serverConfig.insert(config_key::containers, apiConfig.value(config_key::containers)); serverConfig.insert(config_key::hostName, apiConfig.value(config_key::hostName)); auto defaultContainer = apiConfig.value(config_key::defaultContainer).toString(); serverConfig.insert(config_key::defaultContainer, defaultContainer); m_serversModel->editServer(serverConfig, m_serversModel->getDefaultServerIndex()); } else { QString err = reply->errorString(); qDebug() << QString::fromUtf8(reply->readAll()); qDebug() << reply->error(); qDebug() << err; qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); emit errorOccurred(errorString(ApiConfigDownloadError)); m_isConfigUpdateStarted = false; return; } } emit updateFinished(m_isConfigUpdateStarted); m_isConfigUpdateStarted = false; return; }); } void ApiController::clearApiConfig() { auto serverConfig = m_serversModel->getDefaultServerConfig(); serverConfig.remove(config_key::dns1); serverConfig.remove(config_key::dns2); serverConfig.remove(config_key::containers); serverConfig.remove(config_key::hostName); serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None)); m_serversModel->editServer(serverConfig, m_serversModel->getDefaultServerIndex()); }