feature: added page for export api native configs
This commit is contained in:
parent
389c1f5327
commit
42d3d9b98a
30 changed files with 461 additions and 129 deletions
|
@ -57,7 +57,9 @@ if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
|
|||
endif()
|
||||
|
||||
qt_standard_project_setup()
|
||||
qt_add_executable(${PROJECT} MANUAL_FINALIZATION)
|
||||
qt_add_executable(${PROJECT} MANUAL_FINALIZATION
|
||||
core/api/apiDefs.h
|
||||
)
|
||||
|
||||
if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
|
||||
qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_interface.rep)
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <QClipboard>
|
||||
#include <QFontDatabase>
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QMimeData>
|
||||
#include <QQuickItem>
|
||||
#include <QQuickStyle>
|
||||
|
@ -10,8 +12,6 @@
|
|||
#include <QTextDocument>
|
||||
#include <QTimer>
|
||||
#include <QTranslator>
|
||||
#include <QLocalSocket>
|
||||
#include <QLocalServer>
|
||||
|
||||
#include "logger.h"
|
||||
#include "ui/models/installedAppsModel.h"
|
||||
|
@ -282,16 +282,17 @@ bool AmneziaApplication::parseCommands()
|
|||
}
|
||||
|
||||
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
||||
void AmneziaApplication::startLocalServer() {
|
||||
void AmneziaApplication::startLocalServer()
|
||||
{
|
||||
const QString serverName("AmneziaVPNInstance");
|
||||
QLocalServer::removeServer(serverName);
|
||||
|
||||
QLocalServer* server = new QLocalServer(this);
|
||||
QLocalServer *server = new QLocalServer(this);
|
||||
server->listen(serverName);
|
||||
|
||||
QObject::connect(server, &QLocalServer::newConnection, this, [server, this]() {
|
||||
if (server) {
|
||||
QLocalSocket* clientConnection = server->nextPendingConnection();
|
||||
QLocalSocket *clientConnection = server->nextPendingConnection();
|
||||
clientConnection->deleteLater();
|
||||
}
|
||||
emit m_pageController->raiseMainWindow();
|
||||
|
@ -467,6 +468,9 @@ void AmneziaApplication::initControllers()
|
|||
m_systemController.reset(new SystemController(m_settings));
|
||||
m_engine->rootContext()->setContextProperty("SystemController", m_systemController.get());
|
||||
|
||||
m_apiSettingsController.reset(new ApiSettingsController(m_serversModel, m_apiAccountInfoModel, m_settings));
|
||||
m_apiSettingsController.reset(new ApiSettingsController(m_serversModel, m_apiAccountInfoModel, m_apiCountryModel, m_settings));
|
||||
m_engine->rootContext()->setContextProperty("ApiSettingsController", m_apiSettingsController.get());
|
||||
|
||||
m_apiConfigsController.reset(new ApiConfigsController(m_serversModel, m_settings));
|
||||
m_engine->rootContext()->setContextProperty("ApiConfigsController", m_apiConfigsController.get());
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "ui/controllers/sitesController.h"
|
||||
#include "ui/controllers/systemController.h"
|
||||
#include "ui/controllers/appSplitTunnelingController.h"
|
||||
// #include "ui/controllers/api/importController.h"
|
||||
#include "ui/controllers/api/apiConfigsController.h"
|
||||
#include "ui/controllers/api/apiSettingsController.h"
|
||||
#include "ui/models/containers_model.h"
|
||||
#include "ui/models/languageModel.h"
|
||||
|
@ -139,6 +139,7 @@ private:
|
|||
QScopedPointer<AppSplitTunnelingController> m_appSplitTunnelingController;
|
||||
|
||||
QScopedPointer<ApiSettingsController> m_apiSettingsController;
|
||||
QScopedPointer<ApiConfigsController> m_apiConfigsController;
|
||||
|
||||
QNetworkAccessManager *m_nam;
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ set(HEADERS ${HEADERS}
|
|||
${CLIENT_ROOT_DIR}/core/networkUtilities.h
|
||||
${CLIENT_ROOT_DIR}/core/serialization/serialization.h
|
||||
${CLIENT_ROOT_DIR}/core/serialization/transfer.h
|
||||
${CLIENT_ROOT_DIR}/core/enums/apiEnums.h
|
||||
${CLIENT_ROOT_DIR}/../common/logger/logger.h
|
||||
${CLIENT_ROOT_DIR}/utils/qmlUtils.h
|
||||
${CLIENT_ROOT_DIR}/core/api/apiUtils.h
|
||||
|
|
32
client/core/api/apiDefs.h
Normal file
32
client/core/api/apiDefs.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef APIDEFS_H
|
||||
#define APIDEFS_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace apiDefs
|
||||
{
|
||||
enum ConfigType {
|
||||
AmneziaFreeV2 = 1,
|
||||
AmneziaFreeV3,
|
||||
AmneziaPremiumV1,
|
||||
AmneziaPremiumV2,
|
||||
SelfHosted
|
||||
};
|
||||
|
||||
enum ConfigSource {
|
||||
Telegram = 1,
|
||||
AmneziaGateway
|
||||
};
|
||||
|
||||
namespace key
|
||||
{
|
||||
constexpr QLatin1String configVersion("config_version");
|
||||
|
||||
constexpr QLatin1String apiConfig("api_config");
|
||||
constexpr QLatin1String stackType("stack_type");
|
||||
}
|
||||
|
||||
const int requestTimeoutMsecs = 12 * 1000; // 12 secs
|
||||
}
|
||||
|
||||
#endif // APIDEFS_H
|
|
@ -1,10 +1,46 @@
|
|||
#include "apiUtils.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QJsonObject>
|
||||
|
||||
bool ApiUtils::isSubscriptionExpired(const QString &subscriptionEndDate)
|
||||
bool apiUtils::isSubscriptionExpired(const QString &subscriptionEndDate)
|
||||
{
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
QDateTime endDate = QDateTime::fromString(subscriptionEndDate, Qt::ISODateWithMs);
|
||||
return endDate < now;
|
||||
}
|
||||
|
||||
bool apiUtils::isServerFromApi(const QJsonObject &serverConfigObject)
|
||||
{
|
||||
auto configVersion = serverConfigObject.value(apiDefs::key::configVersion).toInt();
|
||||
switch (configVersion) {
|
||||
case apiDefs::ConfigSource::Telegram: return true;
|
||||
case apiDefs::ConfigSource::AmneziaGateway: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
apiDefs::ConfigType apiUtils::getConfigType(const QJsonObject &serverConfigObject)
|
||||
{
|
||||
auto configVersion = serverConfigObject.value(apiDefs::key::configVersion).toInt();
|
||||
switch (configVersion) {
|
||||
case apiDefs::ConfigSource::Telegram: {
|
||||
};
|
||||
case apiDefs::ConfigSource::AmneziaGateway: {
|
||||
constexpr QLatin1String premium("prem");
|
||||
constexpr QLatin1String free("free");
|
||||
|
||||
auto apiConfigObject = serverConfigObject.value(apiDefs::key::apiConfig).toObject();
|
||||
auto stackType = apiConfigObject.value(apiDefs::key::stackType).toString();
|
||||
|
||||
if (stackType == premium) {
|
||||
return apiDefs::ConfigType::AmneziaPremiumV2;
|
||||
} else if (stackType == free) {
|
||||
return apiDefs::ConfigType::AmneziaFreeV3;
|
||||
}
|
||||
}
|
||||
default: {
|
||||
return apiDefs::ConfigType::SelfHosted;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,9 +3,15 @@
|
|||
|
||||
#include <QObject>
|
||||
|
||||
namespace ApiUtils
|
||||
#include "apiDefs.h"
|
||||
|
||||
namespace apiUtils
|
||||
{
|
||||
bool isServerFromApi(const QJsonObject &serverConfigObject);
|
||||
|
||||
bool isSubscriptionExpired(const QString &subscriptionEndDate);
|
||||
|
||||
apiDefs::ConfigType getConfigType(const QJsonObject &serverConfigObject);
|
||||
}
|
||||
|
||||
#endif // APIUTILS_H
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include "amnezia_application.h"
|
||||
#include "configurators/wireguard_configurator.h"
|
||||
#include "core/enums/apiEnums.h"
|
||||
#include "core/api/apiDefs.h"
|
||||
#include "gatewayController.h"
|
||||
#include "version.h"
|
||||
|
||||
|
@ -106,7 +106,7 @@ void ApiController::fillServerConfig(const QString &protocol, const ApiControlle
|
|||
serverConfig[config_key::containers] = newServerConfig.value(config_key::containers);
|
||||
serverConfig[config_key::hostName] = newServerConfig.value(config_key::hostName);
|
||||
|
||||
if (newServerConfig.value(config_key::configVersion).toInt() == ApiConfigSources::AmneziaGateway) {
|
||||
if (newServerConfig.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway) {
|
||||
serverConfig[config_key::configVersion] = newServerConfig.value(config_key::configVersion);
|
||||
serverConfig[config_key::description] = newServerConfig.value(config_key::description);
|
||||
serverConfig[config_key::name] = newServerConfig.value(config_key::name);
|
||||
|
@ -119,7 +119,7 @@ void ApiController::fillServerConfig(const QString &protocol, const ApiControlle
|
|||
map.insert(newServerConfig.value(configKey::apiConfig).toObject().toVariantMap());
|
||||
auto apiConfig = QJsonObject::fromVariantMap(map);
|
||||
|
||||
if (newServerConfig.value(config_key::configVersion).toInt() == ApiConfigSources::AmneziaGateway) {
|
||||
if (newServerConfig.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway) {
|
||||
apiConfig.insert(configKey::serviceInfo, QJsonDocument::fromJson(apiResponseBody).object().value(configKey::serviceInfo).toObject());
|
||||
}
|
||||
|
||||
|
@ -274,23 +274,4 @@ ErrorCode ApiController::getConfigForService(const QString &installationUuid, co
|
|||
return errorCode;
|
||||
}
|
||||
|
||||
ErrorCode ApiController::getNativeConfig(const QString &userCountryCode, const QString &serviceType, const QString &protocol,
|
||||
const QString &serverCountryCode, const QJsonObject &authData, QString &nativeConfig)
|
||||
{
|
||||
GatewayController gatewayController(m_gatewayEndpoint, m_isDevEnvironment, requestTimeoutMsecs);
|
||||
|
||||
ApiPayloadData apiPayloadData = generateApiPayloadData(protocol);
|
||||
|
||||
QJsonObject apiPayload = fillApiPayload(protocol, apiPayloadData);
|
||||
apiPayload[configKey::userCountryCode] = userCountryCode;
|
||||
apiPayload[configKey::serverCountryCode] = serverCountryCode;
|
||||
apiPayload[configKey::serviceType] = serviceType;
|
||||
apiPayload[configKey::authData] = authData;
|
||||
|
||||
QByteArray responseBody;
|
||||
ErrorCode errorCode = gatewayController.post(QString("%1v1/country_config"), apiPayload, responseBody);
|
||||
|
||||
nativeConfig = responseBody;
|
||||
|
||||
return errorCode;
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@ public slots:
|
|||
ErrorCode getConfigForService(const QString &installationUuid, const QString &userCountryCode, const QString &serviceType,
|
||||
const QString &protocol, const QString &serverCountryCode, const QJsonObject &authData,
|
||||
QJsonObject &serverConfig);
|
||||
ErrorCode getNativeConfig(const QString &userCountryCode, const QString &serviceType, const QString &protocol,
|
||||
const QString &serverCountryCode, const QJsonObject &authData, QString &nativeConfig);
|
||||
|
||||
signals:
|
||||
void errorOccurred(ErrorCode errorCode);
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
#ifndef APIENUMS_H
|
||||
#define APIENUMS_H
|
||||
|
||||
enum ApiConfigSources {
|
||||
Telegram = 1,
|
||||
AmneziaGateway
|
||||
};
|
||||
|
||||
#endif // APIENUMS_H
|
|
@ -228,6 +228,7 @@
|
|||
<file>ui/qml/Controls2/ListViewType.qml</file>
|
||||
<file>ui/qml/Pages2/PageSettingsApiSupport.qml</file>
|
||||
<file>ui/qml/Pages2/PageSettingsApiInstructions.qml</file>
|
||||
<file>ui/qml/Pages2/PageSettingsApiNativeConfigs.qml</file>
|
||||
</qresource>
|
||||
<qresource prefix="/countriesFlags">
|
||||
<file>images/flagKit/ZW.svg</file>
|
||||
|
|
106
client/ui/controllers/api/apiConfigsController.cpp
Normal file
106
client/ui/controllers/api/apiConfigsController.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
#include "ApiConfigsController.h"
|
||||
|
||||
#include "configurators/wireguard_configurator.h"
|
||||
#include "core/api/apiDefs.h"
|
||||
#include "core/controllers/gatewayController.h"
|
||||
#include "version.h"
|
||||
#include "ui/controllers/systemController.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 uuid[] = "installation_uuid";
|
||||
constexpr char osVersion[] = "os_version";
|
||||
constexpr char appVersion[] = "app_version";
|
||||
|
||||
constexpr char userCountryCode[] = "user_country_code";
|
||||
constexpr char serverCountryCode[] = "server_country_code";
|
||||
constexpr char serviceType[] = "service_type";
|
||||
constexpr char serviceInfo[] = "service_info";
|
||||
constexpr char serviceProtocol[] = "service_protocol";
|
||||
|
||||
constexpr char aesKey[] = "aes_key";
|
||||
constexpr char aesIv[] = "aes_iv";
|
||||
constexpr char aesSalt[] = "aes_salt";
|
||||
|
||||
constexpr char apiPayload[] = "api_payload";
|
||||
constexpr char keyPayload[] = "key_payload";
|
||||
|
||||
constexpr char apiConfig[] = "api_config";
|
||||
constexpr char authData[] = "auth_data";
|
||||
|
||||
constexpr char config[] = "config";
|
||||
}
|
||||
}
|
||||
|
||||
ApiConfigsController::ApiConfigsController(const QSharedPointer<ServersModel> &serversModel, const std::shared_ptr<Settings> &settings,
|
||||
QObject *parent)
|
||||
: QObject(parent), m_serversModel(serversModel), m_settings(settings)
|
||||
{
|
||||
}
|
||||
|
||||
void ApiConfigsController::exportNativeConfig(const QString &serverCountryCode, const QString &fileName)
|
||||
{
|
||||
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs);
|
||||
|
||||
auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex());
|
||||
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
|
||||
|
||||
QString protocol = apiConfigObject.value(configKey::serviceProtocol).toString();
|
||||
ApiPayloadData apiPayloadData = generateApiPayloadData(protocol);
|
||||
|
||||
QJsonObject apiPayload = fillApiPayload(protocol, apiPayloadData);
|
||||
apiPayload[configKey::userCountryCode] = apiConfigObject.value(configKey::userCountryCode);
|
||||
apiPayload[configKey::serverCountryCode] = apiConfigObject.value(configKey::serverCountryCode);
|
||||
apiPayload[configKey::serviceType] = apiConfigObject.value(configKey::serviceType);
|
||||
apiPayload[configKey::authData] = serverConfigObject.value(configKey::authData);
|
||||
apiPayload[configKey::uuid] = m_settings->getInstallationUuid(true);
|
||||
|
||||
QByteArray responseBody;
|
||||
ErrorCode errorCode = gatewayController.post(QString("%1v1/native_config"), apiPayload, responseBody);
|
||||
// // if (errorCode != ErrorCode::NoError) {
|
||||
|
||||
// // }
|
||||
|
||||
QJsonObject jsonConfig = QJsonDocument::fromJson(responseBody).object();
|
||||
QString nativeConfig = jsonConfig.value(configKey::config).toString();
|
||||
|
||||
SystemController::saveFile(fileName, nativeConfig);
|
||||
}
|
||||
|
||||
ApiConfigsController::ApiPayloadData ApiConfigsController::generateApiPayloadData(const QString &protocol)
|
||||
{
|
||||
ApiConfigsController::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 ApiConfigsController::fillApiPayload(const QString &protocol, const ApiPayloadData &apiPayloadData)
|
||||
{
|
||||
QJsonObject obj;
|
||||
if (protocol == configKey::cloak) {
|
||||
obj[configKey::certificate] = apiPayloadData.certRequest.request;
|
||||
} else if (protocol == configKey::awg) {
|
||||
obj[configKey::publicKey] = apiPayloadData.wireGuardClientPubKey;
|
||||
}
|
||||
|
||||
obj[configKey::osVersion] = QSysInfo::productType();
|
||||
obj[configKey::appVersion] = QString(APP_VERSION);
|
||||
|
||||
return obj;
|
||||
}
|
35
client/ui/controllers/api/apiConfigsController.h
Normal file
35
client/ui/controllers/api/apiConfigsController.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef APICONFIGSCONTROLLER_H
|
||||
#define APICONFIGSCONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "configurators/openvpn_configurator.h"
|
||||
#include "ui/models/servers_model.h"
|
||||
|
||||
class ApiConfigsController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ApiConfigsController(const QSharedPointer<ServersModel> &serversModel, const std::shared_ptr<Settings> &settings,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void exportNativeConfig(const QString &serverCountryCode, const QString &fileName);
|
||||
|
||||
private:
|
||||
struct ApiPayloadData
|
||||
{
|
||||
OpenVpnConfigurator::ConnectionData certRequest;
|
||||
|
||||
QString wireGuardClientPrivKey;
|
||||
QString wireGuardClientPubKey;
|
||||
};
|
||||
|
||||
ApiPayloadData generateApiPayloadData(const QString &protocol);
|
||||
QJsonObject fillApiPayload(const QString &protocol, const ApiPayloadData &apiPayloadData);
|
||||
|
||||
QSharedPointer<ServersModel> m_serversModel;
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
};
|
||||
|
||||
#endif // APICONFIGSCONTROLLER_H
|
|
@ -19,9 +19,14 @@ namespace
|
|||
}
|
||||
|
||||
ApiSettingsController::ApiSettingsController(const QSharedPointer<ServersModel> &serversModel,
|
||||
const QSharedPointer<ApiAccountInfoModel> &apiAccountInfoModel, const std::shared_ptr<Settings> &settings,
|
||||
QObject *parent)
|
||||
: QObject(parent), m_serversModel(serversModel), m_apiAccountInfoModel(apiAccountInfoModel), m_settings(settings)
|
||||
const QSharedPointer<ApiAccountInfoModel> &apiAccountInfoModel,
|
||||
const QSharedPointer<ApiCountryModel> &apiCountryModel,
|
||||
const std::shared_ptr<Settings> &settings, QObject *parent)
|
||||
: QObject(parent),
|
||||
m_serversModel(serversModel),
|
||||
m_apiAccountInfoModel(apiAccountInfoModel),
|
||||
m_apiCountryModel(apiCountryModel),
|
||||
m_settings(settings)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -55,3 +60,8 @@ bool ApiSettingsController::getAccountInfo()
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ApiSettingsController::updateApiCountryModel()
|
||||
{
|
||||
m_apiCountryModel->updateModel(m_apiAccountInfoModel->getAvailableCountries(), "");
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <QObject>
|
||||
|
||||
#include "ui/models/api/apiAccountInfoModel.h"
|
||||
#include "ui/models/apiCountryModel.h"
|
||||
#include "ui/models/servers_model.h"
|
||||
|
||||
class ApiSettingsController : public QObject
|
||||
|
@ -11,15 +12,18 @@ class ApiSettingsController : public QObject
|
|||
Q_OBJECT
|
||||
public:
|
||||
ApiSettingsController(const QSharedPointer<ServersModel> &serversModel, const QSharedPointer<ApiAccountInfoModel> &apiAccountInfoModel,
|
||||
const std::shared_ptr<Settings> &settings, QObject *parent = nullptr);
|
||||
const QSharedPointer<ApiCountryModel> &apiCountryModel, const std::shared_ptr<Settings> &settings,
|
||||
QObject *parent = nullptr);
|
||||
~ApiSettingsController();
|
||||
|
||||
public slots:
|
||||
bool getAccountInfo();
|
||||
void updateApiCountryModel();
|
||||
|
||||
private:
|
||||
QSharedPointer<ServersModel> m_serversModel;
|
||||
QSharedPointer<ApiAccountInfoModel> m_apiAccountInfoModel;
|
||||
QSharedPointer<ApiCountryModel> m_apiCountryModel;
|
||||
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
};
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
#include "importController.h"
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
#ifndef IMPORTCONTROLLER_H
|
||||
#define IMPORTCONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "ui/models/api/apiAccountInfoModel.h"
|
||||
#include "ui/models/servers_model.h"
|
||||
|
||||
// namespace api
|
||||
// {
|
||||
// class ImportController : public QObject
|
||||
// {
|
||||
// Q_OBJECT
|
||||
// public:
|
||||
// ImportController(const QSharedPointer<ServersModel> &serversModel, QSharedPointer<AccountInfoModel> &accountInfoModel);
|
||||
// ~ImportController();
|
||||
|
||||
// private:
|
||||
// QSharedPointer<ServersModel> m_serversModel;
|
||||
// QSharedPointer<AccountInfoModel> m_accountInfoModel;
|
||||
// };
|
||||
// }
|
||||
|
||||
#endif // IMPORTCONTROLLER_H
|
|
@ -8,7 +8,7 @@
|
|||
#include <QtConcurrent>
|
||||
|
||||
#include "core/controllers/vpnConfigurationController.h"
|
||||
#include "core/enums/apiEnums.h"
|
||||
#include "core/api/apiDefs.h"
|
||||
#include "version.h"
|
||||
|
||||
ConnectionController::ConnectionController(const QSharedPointer<ServersModel> &serversModel,
|
||||
|
@ -48,15 +48,15 @@ void ConnectionController::openConnection()
|
|||
|
||||
emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Preparing);
|
||||
|
||||
if (configVersion == ApiConfigSources::Telegram
|
||||
if (configVersion == apiDefs::ConfigSource::Telegram
|
||||
&& !m_serversModel->data(serverIndex, ServersModel::Roles::HasInstalledContainers).toBool()) {
|
||||
emit updateApiConfigFromTelegram();
|
||||
} else if (configVersion == ApiConfigSources::AmneziaGateway
|
||||
} else if (configVersion == apiDefs::ConfigSource::AmneziaGateway
|
||||
&& !m_serversModel->data(serverIndex, ServersModel::Roles::HasInstalledContainers).toBool()) {
|
||||
emit updateApiConfigFromGateway();
|
||||
} else if (configVersion && m_serversModel->isApiKeyExpired(serverIndex)) {
|
||||
qDebug() << "attempt to update api config by expires_at event";
|
||||
if (configVersion == ApiConfigSources::Telegram) {
|
||||
if (configVersion == apiDefs::ConfigSource::Telegram) {
|
||||
emit updateApiConfigFromTelegram();
|
||||
} else {
|
||||
emit updateApiConfigFromGateway();
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace PageLoader
|
|||
PageSettingsApiAvailableCountries,
|
||||
PageSettingsApiSupport,
|
||||
PageSettingsApiInstructions,
|
||||
PageSettingsApiNativeConfigs,
|
||||
|
||||
PageServiceSftpSettings,
|
||||
PageServiceTorWebsiteSettings,
|
||||
|
|
|
@ -12,9 +12,9 @@ namespace
|
|||
namespace configKey
|
||||
{
|
||||
constexpr char availableCountries[] = "available_countries";
|
||||
constexpr char serverCountryCode[] = "server_country_code";
|
||||
constexpr char serverCountryName[] = "server_country_name";
|
||||
constexpr char lastUpdated[] = "last_updated";
|
||||
// constexpr char serverCountryCode[] = "server_country_code";
|
||||
// constexpr char serverCountryName[] = "server_country_name";
|
||||
// constexpr char lastUpdated[] = "last_updated";
|
||||
constexpr char activeDeviceCount[] = "active_device_count";
|
||||
constexpr char maxDeviceCount[] = "max_device_count";
|
||||
constexpr char subscriptionEndDate[] = "subscription_end_date";
|
||||
|
@ -38,7 +38,7 @@ QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const
|
|||
|
||||
switch (role) {
|
||||
case SubscriptionStatusRole: {
|
||||
return ApiUtils::isSubscriptionExpired(m_accountInfoData.subscriptionEndDate) ? tr("Inactive") : tr("Active");
|
||||
return apiUtils::isSubscriptionExpired(m_accountInfoData.subscriptionEndDate) ? tr("Inactive") : tr("Active");
|
||||
}
|
||||
case EndDateRole: {
|
||||
return QDateTime::fromString(m_accountInfoData.subscriptionEndDate, Qt::ISODate).toLocalTime().toString("d MMM yyyy");
|
||||
|
@ -46,9 +46,15 @@ QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const
|
|||
case ConnectedDevicesRole: {
|
||||
return tr("%1 out of %2").arg(m_accountInfoData.activeDeviceCount).arg(m_accountInfoData.maxDeviceCount);
|
||||
}
|
||||
// case ServiceDescriptionRole: {
|
||||
// return apiServiceData.serviceInfo.name;
|
||||
// }
|
||||
case ServiceDescriptionRole: {
|
||||
if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaPremiumV2) {
|
||||
return tr("Classic VPN for comfortable work, downloading large files and watching videos. Works for any sites. Speed up to 200 "
|
||||
"Mb/s");
|
||||
} else if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) {
|
||||
return tr("Free unlimited access to a basic set of websites such as Facebook, Instagram, Twitter (X), Discord, Telegram and "
|
||||
"more. YouTube is not included in the free plan.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
|
@ -60,21 +66,23 @@ void ApiAccountInfoModel::updateModel(const QJsonObject &accountInfoObject, cons
|
|||
|
||||
AccountInfoData accountInfoData;
|
||||
|
||||
auto availableCountries = accountInfoObject.value(configKey::availableCountries).toArray();
|
||||
for (const auto &country : availableCountries) {
|
||||
auto countryObject = country.toObject();
|
||||
CountryInfo countryInfo;
|
||||
countryInfo.serverCountryCode = countryObject.value(configKey::serverCountryCode).toString();
|
||||
countryInfo.serverCountryName = countryObject.value(configKey::serverCountryName).toString();
|
||||
countryInfo.lastUpdated = countryObject.value(configKey::lastUpdated).toString();
|
||||
m_availableCountries = accountInfoObject.value(configKey::availableCountries).toArray();
|
||||
// for (const auto &country : availableCountries) {
|
||||
// auto countryObject = country.toObject();
|
||||
// CountryInfo countryInfo;
|
||||
// countryInfo.serverCountryCode = countryObject.value(configKey::serverCountryCode).toString();
|
||||
// countryInfo.serverCountryName = countryObject.value(configKey::serverCountryName).toString();
|
||||
// countryInfo.lastUpdated = countryObject.value(configKey::lastUpdated).toString();
|
||||
|
||||
accountInfoData.AvailableCountries.push_back(countryInfo);
|
||||
}
|
||||
// accountInfoData.AvailableCountries.push_back(countryInfo);
|
||||
// }
|
||||
|
||||
accountInfoData.activeDeviceCount = accountInfoObject.value(configKey::activeDeviceCount).toInt();
|
||||
accountInfoData.maxDeviceCount = accountInfoObject.value(configKey::maxDeviceCount).toInt();
|
||||
accountInfoData.subscriptionEndDate = accountInfoObject.value(configKey::subscriptionEndDate).toString();
|
||||
|
||||
accountInfoData.configType = apiUtils::getConfigType(serverConfig);
|
||||
|
||||
m_accountInfoData = accountInfoData;
|
||||
|
||||
endResetModel();
|
||||
|
@ -93,6 +101,11 @@ QVariant ApiAccountInfoModel::data(const QString &roleString)
|
|||
return {};
|
||||
}
|
||||
|
||||
QJsonArray ApiAccountInfoModel::getAvailableCountries()
|
||||
{
|
||||
return m_availableCountries;
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ApiAccountInfoModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "core/api/apiDefs.h"
|
||||
|
||||
class ApiAccountInfoModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -27,29 +29,23 @@ public slots:
|
|||
void updateModel(const QJsonObject &accountInfoObject, const QJsonObject &serverConfig);
|
||||
QVariant data(const QString &roleString);
|
||||
|
||||
QJsonArray getAvailableCountries();
|
||||
|
||||
protected:
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
private:
|
||||
struct CountryInfo
|
||||
{
|
||||
QString serverCountryCode;
|
||||
QString serverCountryName;
|
||||
QString lastUpdated;
|
||||
};
|
||||
|
||||
struct AccountInfoData
|
||||
{
|
||||
QString subscriptionEndDate;
|
||||
int activeDeviceCount;
|
||||
int maxDeviceCount;
|
||||
|
||||
QString vpnKey;
|
||||
|
||||
QVector<CountryInfo> AvailableCountries;
|
||||
apiDefs::ConfigType configType;
|
||||
};
|
||||
|
||||
AccountInfoData m_accountInfoData;
|
||||
QJsonArray m_availableCountries;
|
||||
};
|
||||
|
||||
#endif // APIACCOUNTINFOMODEL_H
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "servers_model.h"
|
||||
|
||||
#include "core/api/apiDefs.h"
|
||||
#include "core/controllers/serverController.h"
|
||||
#include "core/enums/apiEnums.h"
|
||||
#include "core/networkUtilities.h"
|
||||
|
||||
#ifdef Q_OS_IOS
|
||||
|
@ -132,10 +132,10 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const
|
|||
return serverHasInstalledContainers(index.row());
|
||||
}
|
||||
case IsServerFromTelegramApiRole: {
|
||||
return server.value(config_key::configVersion).toInt() == ApiConfigSources::Telegram;
|
||||
return server.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::Telegram;
|
||||
}
|
||||
case IsServerFromGatewayApiRole: {
|
||||
return server.value(config_key::configVersion).toInt() == ApiConfigSources::AmneziaGateway;
|
||||
return server.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway;
|
||||
}
|
||||
case ApiConfigRole: {
|
||||
return apiConfig;
|
||||
|
|
|
@ -112,11 +112,13 @@ ListView {
|
|||
ServersModel.processedIndex = index
|
||||
|
||||
if (ServersModel.getProcessedServerData("isServerFromGatewayApi")) {
|
||||
ApiSettingsController.getAccountInfo()
|
||||
|
||||
if (ServersModel.getProcessedServerData("isCountrySelectionAvailable")) {
|
||||
PageController.goToPage(PageEnum.PageSettingsApiAvailableCountries)
|
||||
} else {
|
||||
PageController.showBusyIndicator(true)
|
||||
ApiSettingsController.getAccountInfo()
|
||||
PageController.showBusyIndicator(false)
|
||||
|
||||
PageController.goToPage(PageEnum.PageSettingsApiServerInfo)
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -299,11 +299,13 @@ PageType {
|
|||
ServersModel.processedIndex = ServersModel.defaultIndex
|
||||
|
||||
if (ServersModel.getProcessedServerData("isServerFromGatewayApi")) {
|
||||
ApiSettingsController.getAccountInfo()
|
||||
|
||||
if (ServersModel.getProcessedServerData("isCountrySelectionAvailable")) {
|
||||
PageController.goToPage(PageEnum.PageSettingsApiAvailableCountries)
|
||||
} else {
|
||||
PageController.showBusyIndicator(true)
|
||||
ApiSettingsController.getAccountInfo()
|
||||
PageController.showBusyIndicator(false)
|
||||
|
||||
PageController.goToPage(PageEnum.PageSettingsApiServerInfo)
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -92,6 +92,10 @@ PageType {
|
|||
descriptionText: ApiServicesModel.getSelectedServiceData("serviceDescription")
|
||||
|
||||
actionButtonFunction: function() {
|
||||
PageController.showBusyIndicator(true)
|
||||
ApiSettingsController.getAccountInfo()
|
||||
PageController.showBusyIndicator(false)
|
||||
|
||||
PageController.goToPage(PageEnum.PageSettingsApiServerInfo)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,31 +20,67 @@ PageType {
|
|||
id: windows
|
||||
|
||||
readonly property string title: qsTr("Windows")
|
||||
readonly property string imageSource: "qrc:/images/controls/external-link.svg"
|
||||
readonly property var handler: function() {
|
||||
Qt.openUrlExternally(LanguageModel.getCurrentSiteUrl())
|
||||
}
|
||||
readonly property string link: qsTr("")
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: macos
|
||||
|
||||
readonly property string title: qsTr("macOS")
|
||||
readonly property string link: qsTr("")
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: android
|
||||
|
||||
readonly property string title: qsTr("Android")
|
||||
readonly property string link: qsTr("")
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: androidTv
|
||||
|
||||
readonly property string title: qsTr("AndroidTV")
|
||||
readonly property string link: qsTr("")
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: ios
|
||||
|
||||
readonly property string title: qsTr("iOS")
|
||||
readonly property string link: qsTr("")
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: linux
|
||||
|
||||
readonly property string title: qsTr("Windows")
|
||||
readonly property string imageSource: "qrc:/images/controls/external-link.svg"
|
||||
readonly property var handler: function() {
|
||||
Qt.openUrlExternally(LanguageModel.getCurrentSiteUrl())
|
||||
}
|
||||
readonly property string title: qsTr("Linux")
|
||||
readonly property string link: qsTr("")
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: routers
|
||||
|
||||
readonly property string title: qsTr("Routers")
|
||||
readonly property string link: qsTr("")
|
||||
}
|
||||
|
||||
property list<QtObject> instructionsModel: [
|
||||
windows,
|
||||
linux
|
||||
macos,
|
||||
android,
|
||||
androidTv,
|
||||
ios,
|
||||
linux,
|
||||
routers
|
||||
]
|
||||
|
||||
ListViewType {
|
||||
id: listView
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 20
|
||||
anchors.bottomMargin: 24
|
||||
|
||||
model: instructionsModel
|
||||
|
||||
|
@ -62,8 +98,8 @@ PageType {
|
|||
Layout.rightMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
|
||||
headerText: "Support"
|
||||
descriptionText: qsTr("Our technical support specialists are ready to help you at any time")
|
||||
headerText: qsTr("How to connect on another device")
|
||||
descriptionText: qsTr("Instructions on the Amnezia website")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,9 +112,11 @@ PageType {
|
|||
Layout.topMargin: 6
|
||||
|
||||
text: title
|
||||
leftImageSource: imageSource
|
||||
rightImageSource: "qrc:/images/controls/external-link.svg"
|
||||
|
||||
clickedFunction: handler
|
||||
clickedFunction: function() {
|
||||
Qt.openUrlExternally(link)
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
|
87
client/ui/qml/Pages2/PageSettingsApiNativeConfigs.qml
Normal file
87
client/ui/qml/Pages2/PageSettingsApiNativeConfigs.qml
Normal file
|
@ -0,0 +1,87 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Dialogs
|
||||
|
||||
import QtCore
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import PageEnum 1.0
|
||||
import Style 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
import "../Controls2/TextTypes"
|
||||
import "../Config"
|
||||
import "../Components"
|
||||
|
||||
PageType {
|
||||
id: root
|
||||
|
||||
property string configExtension: ".conf"
|
||||
property string configCaption: qsTr("Save AmneziaVPN config")
|
||||
|
||||
ListViewType {
|
||||
id: listView
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 20
|
||||
anchors.bottomMargin: 24
|
||||
|
||||
model: ApiCountryModel
|
||||
|
||||
header: ColumnLayout {
|
||||
width: listView.width
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
id: header
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.rightMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
|
||||
headerText: qsTr("Configuration files")
|
||||
descriptionText: qsTr("To connect a router or AmneziaWG application")
|
||||
}
|
||||
}
|
||||
|
||||
delegate: ColumnLayout {
|
||||
width: listView.width
|
||||
|
||||
LabelWithButtonType {
|
||||
id: telegramButton
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 6
|
||||
|
||||
text: countryName
|
||||
leftImageSource: "qrc:/countriesFlags/images/flagKit/" + countryImageCode + ".svg"
|
||||
rightImageSource: "qrc:/images/controls/download.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
var fileName = ""
|
||||
if (GC.isMobile()) {
|
||||
fileName = countryCode + configExtension
|
||||
} else {
|
||||
fileName = SystemController.getFileName(configCaption,
|
||||
qsTr("Config files (*" + configExtension + ")"),
|
||||
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/" + countryCode,
|
||||
true,
|
||||
configExtension)
|
||||
}
|
||||
if (fileName !== "") {
|
||||
PageController.showBusyIndicator(true)
|
||||
ApiConfigsController.exportNativeConfig(countryCode, fileName)
|
||||
PageController.showBusyIndicator(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,7 +105,7 @@ PageType {
|
|||
actionButtonImage: "qrc:/images/controls/edit-3.svg"
|
||||
|
||||
headerText: root.processedServer.name
|
||||
descriptionText: ApiServicesModel.getSelectedServiceData("serviceDescription")
|
||||
descriptionText: ApiAccountInfoModel.data("serviceDescription")
|
||||
|
||||
actionButtonFunction: function() {
|
||||
serverNameEditDrawer.openTriggered()
|
||||
|
@ -145,6 +145,8 @@ PageType {
|
|||
spacing: 0
|
||||
|
||||
LabelWithButtonType {
|
||||
id: vpnKey
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 32
|
||||
|
||||
|
@ -157,17 +159,22 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
DividerType {
|
||||
visible: false
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: vpnKey.visible ? 0 : 32
|
||||
|
||||
text: qsTr("Configuration files")
|
||||
|
||||
descriptionText: qsTr("To connect the router")
|
||||
descriptionText: qsTr("To connect a router or AmneziaWG application")
|
||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
ApiSettingsController.updateApiCountryModel()
|
||||
PageController.goToPage(PageEnum.PageSettingsApiNativeConfigs)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ PageType {
|
|||
Layout.rightMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
|
||||
headerText: "Support"
|
||||
headerText: qsTr("Support")
|
||||
descriptionText: qsTr("Our technical support specialists are ready to help you at any time")
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,9 @@ PageType {
|
|||
ServersModel.processedIndex = index
|
||||
|
||||
if (ServersModel.getProcessedServerData("isServerFromGatewayApi")) {
|
||||
PageController.showBusyIndicator(true)
|
||||
ApiSettingsController.getAccountInfo()
|
||||
PageController.showBusyIndicator(false)
|
||||
|
||||
PageController.goToPage(PageEnum.PageSettingsApiServerInfo)
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue