From a754a1191307821e6d82c8f4b5319daaf246ddaf Mon Sep 17 00:00:00 2001 From: Mitternacht822 Date: Tue, 7 Oct 2025 19:16:28 +0400 Subject: [PATCH] fix: added displaying vpn_key field added in older version of the app (#1873) * fix(api_key): added displaying vpn_key field added in older version of the app * revert changes * fix: implemented generation of api key text for PremiumV2 * fix: deleted unnecessary code * saving apikey text when generating * added method for vpn key export, fixed wrong saving file --- client/core/api/apiUtils.cpp | 48 +++++++++++++++++++ client/core/api/apiUtils.h | 1 + .../controllers/api/apiConfigsController.cpp | 24 ++++++++++ .../ui/controllers/api/apiConfigsController.h | 2 +- .../Pages2/PageSettingsApiSubscriptionKey.qml | 2 +- 5 files changed, 75 insertions(+), 2 deletions(-) diff --git a/client/core/api/apiUtils.cpp b/client/core/api/apiUtils.cpp index 3b999aa1..2c0c8635 100644 --- a/client/core/api/apiUtils.cpp +++ b/client/core/api/apiUtils.cpp @@ -162,3 +162,51 @@ QString apiUtils::getPremiumV1VpnKey(const QJsonObject &serverConfigObject) return QString("vpn://%1").arg(QString(signedData.toBase64(QByteArray::Base64UrlEncoding))); } + +QString apiUtils::getPremiumV2VpnKey(const QJsonObject &serverConfigObject) +{ + if (apiUtils::getConfigType(serverConfigObject) != apiDefs::ConfigType::AmneziaPremiumV2) { + return {}; + } + + QString vpnKeyText = ""; + + auto apiConfig = serverConfigObject.value(apiDefs::key::apiConfig).toObject(); + auto authData = serverConfigObject.value(QLatin1String("auth_data")).toObject(); + + const QString name = serverConfigObject.value(apiDefs::key::name).toString(); + const QString description = serverConfigObject.value(apiDefs::key::description).toString(); + const double configVersion = serverConfigObject.value(apiDefs::key::configVersion).toDouble(); + + const QString serviceType = apiConfig.value(apiDefs::key::serviceType).toString(); + const QString serviceProtocol = apiConfig.value(QLatin1String("service_protocol")).toString(); + const QString userCountryCode = apiConfig.value(QLatin1String("user_country_code")).toString(); + + const QString apiKey = authData.value(apiDefs::key::apiKey).toString(); + + QString vpnKeyStr = "{"; + vpnKeyStr += "\"" + QString(apiDefs::key::name) + "\": \"" + name + "\", "; + vpnKeyStr += "\"" + QString(apiDefs::key::description) + "\": \"" + description + "\", "; + vpnKeyStr += "\"" + QString(apiDefs::key::configVersion) + "\": " + QString::number(static_cast(configVersion)) + ", "; + + vpnKeyStr += "\"" + QString(apiDefs::key::apiConfig) + "\": {"; + vpnKeyStr += "\"" + QString(apiDefs::key::serviceType) + "\": \"" + serviceType + "\", "; + vpnKeyStr += "\"service_protocol\": \"" + serviceProtocol + "\", "; + vpnKeyStr += "\"user_country_code\": \"" + userCountryCode + "\""; + vpnKeyStr += "}, "; + + vpnKeyStr += "\"auth_data\": {"; + vpnKeyStr += "\"" + QString(apiDefs::key::apiKey) + "\": \"" + apiKey + "\""; + vpnKeyStr += "}"; + + vpnKeyStr += "}"; + + QByteArray vpnKeyCompressed = escapeUnicode(vpnKeyStr).toUtf8(); + vpnKeyCompressed = qCompress(vpnKeyCompressed, 6); + vpnKeyCompressed = vpnKeyCompressed.mid(4); + + QByteArray signedData = AMNEZIA_CONFIG_SIGNATURE + vpnKeyCompressed; + vpnKeyText = QString("vpn://%1").arg(QString(signedData.toBase64(QByteArray::Base64UrlEncoding))); + + return vpnKeyText; +} diff --git a/client/core/api/apiUtils.h b/client/core/api/apiUtils.h index b84d42e0..d4e1d9ce 100644 --- a/client/core/api/apiUtils.h +++ b/client/core/api/apiUtils.h @@ -23,6 +23,7 @@ namespace apiUtils const QByteArray &responseBody); QString getPremiumV1VpnKey(const QJsonObject &serverConfigObject); + QString getPremiumV2VpnKey(const QJsonObject &serverConfigObject); } #endif // APIUTILS_H diff --git a/client/ui/controllers/api/apiConfigsController.cpp b/client/ui/controllers/api/apiConfigsController.cpp index 30c18e38..026224c5 100644 --- a/client/ui/controllers/api/apiConfigsController.cpp +++ b/client/ui/controllers/api/apiConfigsController.cpp @@ -251,6 +251,23 @@ ApiConfigsController::ApiConfigsController(const QSharedPointer &s { } +bool ApiConfigsController::exportVpnKey(const QString &fileName) +{ + if (fileName.isEmpty()) { + emit errorOccurred(ErrorCode::PermissionsError); + return false; + } + + prepareVpnKeyExport(); + if (m_vpnKey.isEmpty()) { + emit errorOccurred(ErrorCode::ApiConfigEmptyError); + return false; + } + + SystemController::saveFile(fileName, m_vpnKey); + return true; +} + bool ApiConfigsController::exportNativeConfig(const QString &serverCountryCode, const QString &fileName) { if (fileName.isEmpty()) { @@ -332,6 +349,13 @@ void ApiConfigsController::prepareVpnKeyExport() auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject(); auto vpnKey = apiConfigObject.value(apiDefs::key::vpnKey).toString(); + if (vpnKey.isEmpty()) { + vpnKey = apiUtils::getPremiumV2VpnKey(serverConfigObject); + apiConfigObject.insert(apiDefs::key::vpnKey, vpnKey); + serverConfigObject.insert(configKey::apiConfig, apiConfigObject); + m_serversModel->editServer(serverConfigObject, m_serversModel->getProcessedServerIndex()); + } + m_vpnKey = vpnKey; vpnKey.replace("vpn://", ""); diff --git a/client/ui/controllers/api/apiConfigsController.h b/client/ui/controllers/api/apiConfigsController.h index c1a72a7d..2a4cd400 100644 --- a/client/ui/controllers/api/apiConfigsController.h +++ b/client/ui/controllers/api/apiConfigsController.h @@ -21,7 +21,7 @@ public: public slots: bool exportNativeConfig(const QString &serverCountryCode, const QString &fileName); bool revokeNativeConfig(const QString &serverCountryCode); - // bool exportVpnKey(const QString &fileName); + bool exportVpnKey(const QString &fileName); void prepareVpnKeyExport(); void copyVpnKeyToClipboard(); diff --git a/client/ui/qml/Pages2/PageSettingsApiSubscriptionKey.qml b/client/ui/qml/Pages2/PageSettingsApiSubscriptionKey.qml index f5464137..38504edd 100644 --- a/client/ui/qml/Pages2/PageSettingsApiSubscriptionKey.qml +++ b/client/ui/qml/Pages2/PageSettingsApiSubscriptionKey.qml @@ -119,7 +119,7 @@ PageType { if (fileName !== "") { PageController.showBusyIndicator(true) - ExportController.exportConfig(fileName) + ApiConfigsController.exportVpnKey(fileName) PageController.showBusyIndicator(false) } }