Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into HEAD
This commit is contained in:
commit
805bc5fb61
773 changed files with 61955 additions and 17793 deletions
143
client/ui/models/api/apiAccountInfoModel.cpp
Normal file
143
client/ui/models/api/apiAccountInfoModel.cpp
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
#include "apiAccountInfoModel.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "core/api/apiUtils.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
Logger logger("AccountInfoModel");
|
||||
}
|
||||
|
||||
ApiAccountInfoModel::ApiAccountInfoModel(QObject *parent) : QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
int ApiAccountInfoModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return 1;
|
||||
}
|
||||
|
||||
QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= static_cast<int>(rowCount()))
|
||||
return QVariant();
|
||||
|
||||
switch (role) {
|
||||
case SubscriptionStatusRole: {
|
||||
if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) {
|
||||
return tr("Active");
|
||||
}
|
||||
|
||||
return apiUtils::isSubscriptionExpired(m_accountInfoData.subscriptionEndDate) ? tr("Inactive") : tr("Active");
|
||||
}
|
||||
case EndDateRole: {
|
||||
if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return QDateTime::fromString(m_accountInfoData.subscriptionEndDate, Qt::ISODate).toLocalTime().toString("d MMM yyyy");
|
||||
}
|
||||
case ConnectedDevicesRole: {
|
||||
if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) {
|
||||
return "";
|
||||
}
|
||||
return tr("%1 out of %2").arg(m_accountInfoData.activeDeviceCount).arg(m_accountInfoData.maxDeviceCount);
|
||||
}
|
||||
case ServiceDescriptionRole: {
|
||||
if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaPremiumV2) {
|
||||
return tr("Classic VPN for seamless work, downloading large files, and watching videos. Access all websites and online resources. "
|
||||
"Speeds up to 200 Mbps");
|
||||
} 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.");
|
||||
}
|
||||
}
|
||||
case IsComponentVisibleRole: {
|
||||
return m_accountInfoData.configType == apiDefs::ConfigType::AmneziaPremiumV2;
|
||||
}
|
||||
case HasExpiredWorkerRole: {
|
||||
for (int i = 0; i < m_issuedConfigsInfo.size(); i++) {
|
||||
QJsonObject issuedConfigObject = m_issuedConfigsInfo.at(i).toObject();
|
||||
|
||||
auto lastDownloaded = QDateTime::fromString(issuedConfigObject.value(apiDefs::key::lastDownloaded).toString());
|
||||
auto workerLastUpdated = QDateTime::fromString(issuedConfigObject.value(apiDefs::key::workerLastUpdated).toString());
|
||||
|
||||
if (lastDownloaded < workerLastUpdated) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void ApiAccountInfoModel::updateModel(const QJsonObject &accountInfoObject, const QJsonObject &serverConfig)
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
AccountInfoData accountInfoData;
|
||||
|
||||
m_availableCountries = accountInfoObject.value(apiDefs::key::availableCountries).toArray();
|
||||
m_issuedConfigsInfo = accountInfoObject.value(apiDefs::key::issuedConfigs).toArray();
|
||||
|
||||
accountInfoData.activeDeviceCount = accountInfoObject.value(apiDefs::key::activeDeviceCount).toInt();
|
||||
accountInfoData.maxDeviceCount = accountInfoObject.value(apiDefs::key::maxDeviceCount).toInt();
|
||||
accountInfoData.subscriptionEndDate = accountInfoObject.value(apiDefs::key::subscriptionEndDate).toString();
|
||||
|
||||
accountInfoData.configType = apiUtils::getConfigType(serverConfig);
|
||||
|
||||
m_accountInfoData = accountInfoData;
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QVariant ApiAccountInfoModel::data(const QString &roleString)
|
||||
{
|
||||
QModelIndex modelIndex = index(0);
|
||||
auto roles = roleNames();
|
||||
for (auto it = roles.begin(); it != roles.end(); it++) {
|
||||
if (QString(it.value()) == roleString) {
|
||||
return data(modelIndex, it.key());
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
QJsonArray ApiAccountInfoModel::getAvailableCountries()
|
||||
{
|
||||
return m_availableCountries;
|
||||
}
|
||||
|
||||
QJsonArray ApiAccountInfoModel::getIssuedConfigsInfo()
|
||||
{
|
||||
return m_issuedConfigsInfo;
|
||||
}
|
||||
|
||||
QString ApiAccountInfoModel::getTelegramBotLink()
|
||||
{
|
||||
if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) {
|
||||
return tr("amnezia_free_support_bot");
|
||||
} else if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaPremiumV2) {
|
||||
return tr("amnezia_premium_support_bot");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ApiAccountInfoModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles[SubscriptionStatusRole] = "subscriptionStatus";
|
||||
roles[EndDateRole] = "endDate";
|
||||
roles[ConnectedDevicesRole] = "connectedDevices";
|
||||
roles[ServiceDescriptionRole] = "serviceDescription";
|
||||
roles[IsComponentVisibleRole] = "isComponentVisible";
|
||||
roles[HasExpiredWorkerRole] = "hasExpiredWorker";
|
||||
|
||||
return roles;
|
||||
}
|
||||
56
client/ui/models/api/apiAccountInfoModel.h
Normal file
56
client/ui/models/api/apiAccountInfoModel.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#ifndef APIACCOUNTINFOMODEL_H
|
||||
#define APIACCOUNTINFOMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "core/api/apiDefs.h"
|
||||
|
||||
class ApiAccountInfoModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
SubscriptionStatusRole = Qt::UserRole + 1,
|
||||
ConnectedDevicesRole,
|
||||
ServiceDescriptionRole,
|
||||
EndDateRole,
|
||||
IsComponentVisibleRole,
|
||||
HasExpiredWorkerRole
|
||||
};
|
||||
|
||||
explicit ApiAccountInfoModel(QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
public slots:
|
||||
void updateModel(const QJsonObject &accountInfoObject, const QJsonObject &serverConfig);
|
||||
QVariant data(const QString &roleString);
|
||||
|
||||
QJsonArray getAvailableCountries();
|
||||
QJsonArray getIssuedConfigsInfo();
|
||||
QString getTelegramBotLink();
|
||||
|
||||
protected:
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
private:
|
||||
struct AccountInfoData
|
||||
{
|
||||
QString subscriptionEndDate;
|
||||
int activeDeviceCount;
|
||||
int maxDeviceCount;
|
||||
|
||||
apiDefs::ConfigType configType;
|
||||
};
|
||||
|
||||
AccountInfoData m_accountInfoData;
|
||||
QJsonArray m_availableCountries;
|
||||
QJsonArray m_issuedConfigsInfo;
|
||||
};
|
||||
|
||||
#endif // APIACCOUNTINFOMODEL_H
|
||||
122
client/ui/models/api/apiCountryModel.cpp
Normal file
122
client/ui/models/api/apiCountryModel.cpp
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
#include "apiCountryModel.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "core/api/apiDefs.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
Logger logger("ApiCountryModel");
|
||||
|
||||
constexpr QLatin1String countryConfig("country_config");
|
||||
}
|
||||
|
||||
ApiCountryModel::ApiCountryModel(QObject *parent) : QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
int ApiCountryModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return m_countries.size();
|
||||
}
|
||||
|
||||
QVariant ApiCountryModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= static_cast<int>(rowCount()))
|
||||
return QVariant();
|
||||
|
||||
CountryInfo countryInfo = m_countries.at(index.row());
|
||||
IssuedConfigInfo issuedConfigInfo = m_issuedConfigs.value(countryInfo.countryCode);
|
||||
bool isIssued = issuedConfigInfo.sourceType == countryConfig;
|
||||
|
||||
switch (role) {
|
||||
case CountryCodeRole: {
|
||||
return countryInfo.countryCode;
|
||||
}
|
||||
case CountryNameRole: {
|
||||
return countryInfo.countryName;
|
||||
}
|
||||
case CountryImageCodeRole: {
|
||||
return countryInfo.countryCode.toUpper();
|
||||
}
|
||||
case IsIssuedRole: {
|
||||
return isIssued;
|
||||
}
|
||||
case IsWorkerExpiredRole: {
|
||||
return issuedConfigInfo.lastDownloaded < issuedConfigInfo.workerLastUpdated;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void ApiCountryModel::updateModel(const QJsonArray &countries, const QString ¤tCountryCode)
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
m_countries.clear();
|
||||
for (int i = 0; i < countries.size(); i++) {
|
||||
CountryInfo countryInfo;
|
||||
QJsonObject countryObject = countries.at(i).toObject();
|
||||
|
||||
countryInfo.countryName = countryObject.value(apiDefs::key::serverCountryName).toString();
|
||||
countryInfo.countryCode = countryObject.value(apiDefs::key::serverCountryCode).toString();
|
||||
|
||||
if (countryInfo.countryCode == currentCountryCode) {
|
||||
m_currentIndex = i;
|
||||
emit currentIndexChanged(m_currentIndex);
|
||||
}
|
||||
m_countries.push_back(countryInfo);
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void ApiCountryModel::updateIssuedConfigsInfo(const QJsonArray &issuedConfigs)
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
m_issuedConfigs.clear();
|
||||
for (int i = 0; i < issuedConfigs.size(); i++) {
|
||||
IssuedConfigInfo issuedConfigInfo;
|
||||
QJsonObject issuedConfigObject = issuedConfigs.at(i).toObject();
|
||||
|
||||
if (issuedConfigObject.value(apiDefs::key::sourceType).toString() != countryConfig) {
|
||||
continue;
|
||||
}
|
||||
|
||||
issuedConfigInfo.installationUuid = issuedConfigObject.value(apiDefs::key::installationUuid).toString();
|
||||
issuedConfigInfo.workerLastUpdated = issuedConfigObject.value(apiDefs::key::workerLastUpdated).toString();
|
||||
issuedConfigInfo.lastDownloaded = issuedConfigObject.value(apiDefs::key::lastDownloaded).toString();
|
||||
issuedConfigInfo.sourceType = issuedConfigObject.value(apiDefs::key::sourceType).toString();
|
||||
issuedConfigInfo.osVersion = issuedConfigObject.value(apiDefs::key::osVersion).toString();
|
||||
|
||||
m_issuedConfigs.insert(issuedConfigObject.value(apiDefs::key::serverCountryCode).toString(), issuedConfigInfo);
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
int ApiCountryModel::getCurrentIndex()
|
||||
{
|
||||
return m_currentIndex;
|
||||
}
|
||||
|
||||
void ApiCountryModel::setCurrentIndex(const int i)
|
||||
{
|
||||
m_currentIndex = i;
|
||||
emit currentIndexChanged(m_currentIndex);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ApiCountryModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles[CountryNameRole] = "countryName";
|
||||
roles[CountryCodeRole] = "countryCode";
|
||||
roles[CountryImageCodeRole] = "countryImageCode";
|
||||
roles[IsIssuedRole] = "isIssued";
|
||||
roles[IsWorkerExpiredRole] = "isWorkerExpired";
|
||||
return roles;
|
||||
}
|
||||
63
client/ui/models/api/apiCountryModel.h
Normal file
63
client/ui/models/api/apiCountryModel.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#ifndef APICOUNTRYMODEL_H
|
||||
#define APICOUNTRYMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QHash>
|
||||
#include <QJsonArray>
|
||||
|
||||
class ApiCountryModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
CountryNameRole = Qt::UserRole + 1,
|
||||
CountryCodeRole,
|
||||
CountryImageCodeRole,
|
||||
IsIssuedRole,
|
||||
IsWorkerExpiredRole
|
||||
};
|
||||
|
||||
explicit ApiCountryModel(QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
Q_PROPERTY(int currentIndex READ getCurrentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
|
||||
|
||||
public slots:
|
||||
void updateModel(const QJsonArray &countries, const QString ¤tCountryCode);
|
||||
void updateIssuedConfigsInfo(const QJsonArray &issuedConfigs);
|
||||
|
||||
int getCurrentIndex();
|
||||
void setCurrentIndex(const int i);
|
||||
|
||||
signals:
|
||||
void currentIndexChanged(const int index);
|
||||
|
||||
protected:
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
private:
|
||||
struct IssuedConfigInfo
|
||||
{
|
||||
QString installationUuid;
|
||||
QString workerLastUpdated;
|
||||
QString lastDownloaded;
|
||||
QString sourceType;
|
||||
QString osVersion;
|
||||
};
|
||||
|
||||
struct CountryInfo
|
||||
{
|
||||
QString countryName;
|
||||
QString countryCode;
|
||||
};
|
||||
|
||||
QVector<CountryInfo> m_countries;
|
||||
QHash<QString, IssuedConfigInfo> m_issuedConfigs;
|
||||
int m_currentIndex;
|
||||
};
|
||||
|
||||
#endif // APICOUNTRYMODEL_H
|
||||
90
client/ui/models/api/apiDevicesModel.cpp
Normal file
90
client/ui/models/api/apiDevicesModel.cpp
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
#include "apiDevicesModel.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "core/api/apiDefs.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
Logger logger("ApiDevicesModel");
|
||||
|
||||
constexpr QLatin1String gatewayAccount("gateway_account");
|
||||
}
|
||||
|
||||
ApiDevicesModel::ApiDevicesModel(std::shared_ptr<Settings> settings, QObject *parent) : m_settings(settings), QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
int ApiDevicesModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return m_issuedConfigs.size();
|
||||
}
|
||||
|
||||
QVariant ApiDevicesModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= static_cast<int>(rowCount()))
|
||||
return QVariant();
|
||||
|
||||
IssuedConfigInfo issuedConfigInfo = m_issuedConfigs.at(index.row());
|
||||
|
||||
switch (role) {
|
||||
case OsVersionRole: {
|
||||
return issuedConfigInfo.osVersion;
|
||||
}
|
||||
case SupportTagRole: {
|
||||
return issuedConfigInfo.installationUuid;
|
||||
}
|
||||
case CountryCodeRole: {
|
||||
return issuedConfigInfo.countryCode;
|
||||
}
|
||||
case LastUpdateRole: {
|
||||
return QDateTime::fromString(issuedConfigInfo.lastDownloaded, Qt::ISODate).toLocalTime().toString("d MMM yyyy");
|
||||
}
|
||||
case IsCurrentDeviceRole: {
|
||||
return issuedConfigInfo.installationUuid == m_settings->getInstallationUuid(false);
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void ApiDevicesModel::updateModel(const QJsonArray &issuedConfigs)
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
m_issuedConfigs.clear();
|
||||
for (int i = 0; i < issuedConfigs.size(); i++) {
|
||||
IssuedConfigInfo issuedConfigInfo;
|
||||
QJsonObject issuedConfigObject = issuedConfigs.at(i).toObject();
|
||||
|
||||
if (issuedConfigObject.value(apiDefs::key::sourceType).toString() != gatewayAccount) {
|
||||
continue;
|
||||
}
|
||||
|
||||
issuedConfigInfo.installationUuid = issuedConfigObject.value(apiDefs::key::installationUuid).toString();
|
||||
issuedConfigInfo.workerLastUpdated = issuedConfigObject.value(apiDefs::key::workerLastUpdated).toString();
|
||||
issuedConfigInfo.lastDownloaded = issuedConfigObject.value(apiDefs::key::lastDownloaded).toString();
|
||||
issuedConfigInfo.sourceType = issuedConfigObject.value(apiDefs::key::sourceType).toString();
|
||||
issuedConfigInfo.osVersion = issuedConfigObject.value(apiDefs::key::osVersion).toString();
|
||||
|
||||
issuedConfigInfo.countryName = issuedConfigObject.value(apiDefs::key::serverCountryName).toString();
|
||||
issuedConfigInfo.countryCode = issuedConfigObject.value(apiDefs::key::serverCountryCode).toString();
|
||||
|
||||
m_issuedConfigs.push_back(issuedConfigInfo);
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ApiDevicesModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles[OsVersionRole] = "osVersion";
|
||||
roles[SupportTagRole] = "supportTag";
|
||||
roles[CountryCodeRole] = "countryCode";
|
||||
roles[LastUpdateRole] = "lastUpdate";
|
||||
roles[IsCurrentDeviceRole] = "isCurrentDevice";
|
||||
return roles;
|
||||
}
|
||||
52
client/ui/models/api/apiDevicesModel.h
Normal file
52
client/ui/models/api/apiDevicesModel.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#ifndef APIDEVICESMODEL_H
|
||||
#define APIDEVICESMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QJsonArray>
|
||||
#include <QVector>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
class ApiDevicesModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
OsVersionRole = Qt::UserRole + 1,
|
||||
SupportTagRole,
|
||||
CountryCodeRole,
|
||||
LastUpdateRole,
|
||||
IsCurrentDeviceRole
|
||||
};
|
||||
|
||||
explicit ApiDevicesModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
public slots:
|
||||
void updateModel(const QJsonArray &issuedConfigs);
|
||||
|
||||
protected:
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
private:
|
||||
struct IssuedConfigInfo
|
||||
{
|
||||
QString installationUuid;
|
||||
QString workerLastUpdated;
|
||||
QString lastDownloaded;
|
||||
QString sourceType;
|
||||
QString osVersion;
|
||||
|
||||
QString countryName;
|
||||
QString countryCode;
|
||||
};
|
||||
|
||||
QVector<IssuedConfigInfo> m_issuedConfigs;
|
||||
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
};
|
||||
#endif // APIDEVICESMODEL_H
|
||||
264
client/ui/models/api/apiServicesModel.cpp
Normal file
264
client/ui/models/api/apiServicesModel.cpp
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
#include "apiServicesModel.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
Logger logger("ApiServicesModel");
|
||||
|
||||
namespace configKey
|
||||
{
|
||||
constexpr char userCountryCode[] = "user_country_code";
|
||||
constexpr char services[] = "services";
|
||||
constexpr char serviceInfo[] = "service_info";
|
||||
constexpr char serviceType[] = "service_type";
|
||||
constexpr char serviceProtocol[] = "service_protocol";
|
||||
|
||||
constexpr char name[] = "name";
|
||||
constexpr char price[] = "price";
|
||||
constexpr char speed[] = "speed";
|
||||
constexpr char timelimit[] = "timelimit";
|
||||
constexpr char region[] = "region";
|
||||
|
||||
constexpr char availableCountries[] = "available_countries";
|
||||
|
||||
constexpr char storeEndpoint[] = "store_endpoint";
|
||||
|
||||
constexpr char isAvailable[] = "is_available";
|
||||
|
||||
constexpr char subscription[] = "subscription";
|
||||
constexpr char endDate[] = "end_date";
|
||||
}
|
||||
|
||||
namespace serviceType
|
||||
{
|
||||
constexpr char amneziaFree[] = "amnezia-free";
|
||||
constexpr char amneziaPremium[] = "amnezia-premium";
|
||||
}
|
||||
}
|
||||
|
||||
ApiServicesModel::ApiServicesModel(QObject *parent) : QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
int ApiServicesModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return m_services.size();
|
||||
}
|
||||
|
||||
QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= static_cast<int>(rowCount()))
|
||||
return QVariant();
|
||||
|
||||
auto apiServiceData = m_services.at(index.row());
|
||||
auto serviceType = apiServiceData.type;
|
||||
auto isServiceAvailable = apiServiceData.isServiceAvailable;
|
||||
|
||||
switch (role) {
|
||||
case NameRole: {
|
||||
return apiServiceData.serviceInfo.name;
|
||||
}
|
||||
case CardDescriptionRole: {
|
||||
auto speed = apiServiceData.serviceInfo.speed;
|
||||
if (serviceType == serviceType::amneziaPremium) {
|
||||
return tr("Amnezia Premium is classic VPN for seamless work, downloading large files, and watching videos. "
|
||||
"Access all websites and online resources. Speeds up to %1 Mbps.")
|
||||
.arg(speed);
|
||||
} else if (serviceType == serviceType::amneziaFree) {
|
||||
QString description = tr("AmneziaFree provides free unlimited access to a basic set of web sites, such as Facebook, Instagram, Twitter (X), Discord, Telegram, and others. YouTube is not included in the free plan.");
|
||||
if (!isServiceAvailable) {
|
||||
description += tr("<p><a style=\"color: #EB5757;\">Not available in your region. If you have VPN enabled, disable it, "
|
||||
"return to the previous screen, and try again.</a>");
|
||||
}
|
||||
return description;
|
||||
}
|
||||
}
|
||||
case ServiceDescriptionRole: {
|
||||
if (serviceType == serviceType::amneziaPremium) {
|
||||
return tr("Amnezia Premium is classic VPN for for seamless work, downloading large files, and watching videos. "
|
||||
"Access all websites and online resources.");
|
||||
} else {
|
||||
return tr("AmneziaFree provides free unlimited access to a basic set of web sites, such as Facebook, Instagram, Twitter (X), Discord, Telegram, and others. YouTube is not included in the free plan.");
|
||||
}
|
||||
}
|
||||
case IsServiceAvailableRole: {
|
||||
if (serviceType == serviceType::amneziaFree) {
|
||||
if (!isServiceAvailable) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case SpeedRole: {
|
||||
return tr("%1 MBit/s").arg(apiServiceData.serviceInfo.speed);
|
||||
}
|
||||
case TimeLimitRole: {
|
||||
auto timeLimit = apiServiceData.serviceInfo.timeLimit;
|
||||
if (timeLimit == "0") {
|
||||
return "";
|
||||
}
|
||||
return tr("%1 days").arg(timeLimit);
|
||||
}
|
||||
case RegionRole: {
|
||||
return apiServiceData.serviceInfo.region;
|
||||
}
|
||||
case FeaturesRole: {
|
||||
if (serviceType == serviceType::amneziaPremium) {
|
||||
return tr("");
|
||||
} else {
|
||||
return tr("VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. "
|
||||
"Other sites will be opened from your real IP address, "
|
||||
"<a href=\"%1/free\" style=\"color: #FBB26A;\">more details on the website.</a>");
|
||||
}
|
||||
}
|
||||
case PriceRole: {
|
||||
auto price = apiServiceData.serviceInfo.price;
|
||||
if (price == "free") {
|
||||
return tr("Free");
|
||||
}
|
||||
return tr("%1 $/month").arg(price);
|
||||
}
|
||||
case EndDateRole: {
|
||||
return QDateTime::fromString(apiServiceData.subscription.endDate, Qt::ISODate).toLocalTime().toString("d MMM yyyy");
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void ApiServicesModel::updateModel(const QJsonObject &data)
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
m_services.clear();
|
||||
|
||||
m_countryCode = data.value(configKey::userCountryCode).toString();
|
||||
auto services = data.value(configKey::services).toArray();
|
||||
|
||||
if (services.isEmpty()) {
|
||||
m_services.push_back(getApiServicesData(data));
|
||||
m_selectedServiceIndex = 0;
|
||||
} else {
|
||||
for (const auto &service : services) {
|
||||
auto serviceObject = service.toObject();
|
||||
m_services.push_back(getApiServicesData(serviceObject));
|
||||
}
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void ApiServicesModel::setServiceIndex(const int index)
|
||||
{
|
||||
m_selectedServiceIndex = index;
|
||||
}
|
||||
|
||||
QJsonObject ApiServicesModel::getSelectedServiceInfo()
|
||||
{
|
||||
auto service = m_services.at(m_selectedServiceIndex);
|
||||
return service.serviceInfo.object;
|
||||
}
|
||||
|
||||
QString ApiServicesModel::getSelectedServiceType()
|
||||
{
|
||||
auto service = m_services.at(m_selectedServiceIndex);
|
||||
return service.type;
|
||||
}
|
||||
|
||||
QString ApiServicesModel::getSelectedServiceProtocol()
|
||||
{
|
||||
auto service = m_services.at(m_selectedServiceIndex);
|
||||
return service.protocol;
|
||||
}
|
||||
|
||||
QString ApiServicesModel::getSelectedServiceName()
|
||||
{
|
||||
auto service = m_services.at(m_selectedServiceIndex);
|
||||
return service.serviceInfo.name;
|
||||
}
|
||||
|
||||
QJsonArray ApiServicesModel::getSelectedServiceCountries()
|
||||
{
|
||||
auto service = m_services.at(m_selectedServiceIndex);
|
||||
return service.availableCountries;
|
||||
}
|
||||
|
||||
QString ApiServicesModel::getCountryCode()
|
||||
{
|
||||
return m_countryCode;
|
||||
}
|
||||
|
||||
QString ApiServicesModel::getStoreEndpoint()
|
||||
{
|
||||
auto service = m_services.at(m_selectedServiceIndex);
|
||||
return service.storeEndpoint;
|
||||
}
|
||||
|
||||
QVariant ApiServicesModel::getSelectedServiceData(const QString roleString)
|
||||
{
|
||||
QModelIndex modelIndex = index(m_selectedServiceIndex);
|
||||
auto roles = roleNames();
|
||||
for (auto it = roles.begin(); it != roles.end(); it++) {
|
||||
if (QString(it.value()) == roleString) {
|
||||
return data(modelIndex, it.key());
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ApiServicesModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles[NameRole] = "name";
|
||||
roles[CardDescriptionRole] = "cardDescription";
|
||||
roles[ServiceDescriptionRole] = "serviceDescription";
|
||||
roles[IsServiceAvailableRole] = "isServiceAvailable";
|
||||
roles[SpeedRole] = "speed";
|
||||
roles[TimeLimitRole] = "timeLimit";
|
||||
roles[RegionRole] = "region";
|
||||
roles[FeaturesRole] = "features";
|
||||
roles[PriceRole] = "price";
|
||||
roles[EndDateRole] = "endDate";
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
ApiServicesModel::ApiServicesData ApiServicesModel::getApiServicesData(const QJsonObject &data)
|
||||
{
|
||||
auto serviceInfo = data.value(configKey::serviceInfo).toObject();
|
||||
auto serviceType = data.value(configKey::serviceType).toString();
|
||||
auto serviceProtocol = data.value(configKey::serviceProtocol).toString();
|
||||
auto availableCountries = data.value(configKey::availableCountries).toArray();
|
||||
|
||||
auto subscriptionObject = data.value(configKey::subscription).toObject();
|
||||
|
||||
ApiServicesData serviceData;
|
||||
serviceData.serviceInfo.name = serviceInfo.value(configKey::name).toString();
|
||||
serviceData.serviceInfo.price = serviceInfo.value(configKey::price).toString();
|
||||
serviceData.serviceInfo.region = serviceInfo.value(configKey::region).toString();
|
||||
serviceData.serviceInfo.speed = serviceInfo.value(configKey::speed).toString();
|
||||
serviceData.serviceInfo.timeLimit = serviceInfo.value(configKey::timelimit).toString();
|
||||
|
||||
serviceData.type = serviceType;
|
||||
serviceData.protocol = serviceProtocol;
|
||||
|
||||
serviceData.storeEndpoint = data.value(configKey::storeEndpoint).toString();
|
||||
|
||||
if (data.value(configKey::isAvailable).isBool()) {
|
||||
serviceData.isServiceAvailable = data.value(configKey::isAvailable).toBool();
|
||||
} else {
|
||||
serviceData.isServiceAvailable = true;
|
||||
}
|
||||
|
||||
serviceData.serviceInfo.object = serviceInfo;
|
||||
serviceData.availableCountries = availableCountries;
|
||||
|
||||
serviceData.subscription.endDate = subscriptionObject.value(configKey::endDate).toString();
|
||||
|
||||
return serviceData;
|
||||
}
|
||||
91
client/ui/models/api/apiServicesModel.h
Normal file
91
client/ui/models/api/apiServicesModel.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
#ifndef APISERVICESMODEL_H
|
||||
#define APISERVICESMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
class ApiServicesModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
NameRole = Qt::UserRole + 1,
|
||||
CardDescriptionRole,
|
||||
ServiceDescriptionRole,
|
||||
IsServiceAvailableRole,
|
||||
SpeedRole,
|
||||
TimeLimitRole,
|
||||
RegionRole,
|
||||
FeaturesRole,
|
||||
PriceRole,
|
||||
EndDateRole
|
||||
};
|
||||
|
||||
explicit ApiServicesModel(QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
public slots:
|
||||
void updateModel(const QJsonObject &data);
|
||||
|
||||
void setServiceIndex(const int index);
|
||||
|
||||
QJsonObject getSelectedServiceInfo();
|
||||
QString getSelectedServiceType();
|
||||
QString getSelectedServiceProtocol();
|
||||
QString getSelectedServiceName();
|
||||
QJsonArray getSelectedServiceCountries();
|
||||
|
||||
QString getCountryCode();
|
||||
|
||||
QString getStoreEndpoint();
|
||||
|
||||
QVariant getSelectedServiceData(const QString roleString);
|
||||
|
||||
protected:
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
private:
|
||||
struct ServiceInfo
|
||||
{
|
||||
QString name;
|
||||
QString speed;
|
||||
QString timeLimit;
|
||||
QString region;
|
||||
QString price;
|
||||
|
||||
QJsonObject object;
|
||||
};
|
||||
|
||||
struct Subscription
|
||||
{
|
||||
QString endDate;
|
||||
};
|
||||
|
||||
struct ApiServicesData
|
||||
{
|
||||
bool isServiceAvailable;
|
||||
|
||||
QString type;
|
||||
QString protocol;
|
||||
QString storeEndpoint;
|
||||
|
||||
ServiceInfo serviceInfo;
|
||||
Subscription subscription;
|
||||
|
||||
QJsonArray availableCountries;
|
||||
};
|
||||
|
||||
ApiServicesData getApiServicesData(const QJsonObject &data);
|
||||
|
||||
QString m_countryCode;
|
||||
QVector<ApiServicesData> m_services;
|
||||
|
||||
int m_selectedServiceIndex;
|
||||
};
|
||||
|
||||
#endif // APISERVICESMODEL_H
|
||||
|
|
@ -20,6 +20,7 @@ namespace
|
|||
constexpr char latestHandshake[] = "latestHandshake";
|
||||
constexpr char dataReceived[] = "dataReceived";
|
||||
constexpr char dataSent[] = "dataSent";
|
||||
constexpr char allowedIps[] = "allowedIps";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,6 +50,7 @@ QVariant ClientManagementModel::data(const QModelIndex &index, int role) const
|
|||
case LatestHandshakeRole: return userData.value(configKey::latestHandshake).toString();
|
||||
case DataReceivedRole: return userData.value(configKey::dataReceived).toString();
|
||||
case DataSentRole: return userData.value(configKey::dataSent).toString();
|
||||
case AllowedIpsRole: return userData.value(configKey::allowedIps).toString();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
|
|
@ -75,6 +77,7 @@ ErrorCode ClientManagementModel::updateModel(const DockerContainer container, co
|
|||
{
|
||||
beginResetModel();
|
||||
m_clientsTable = QJsonArray();
|
||||
endResetModel();
|
||||
|
||||
ErrorCode error = ErrorCode::NoError;
|
||||
|
||||
|
|
@ -88,10 +91,10 @@ ErrorCode ClientManagementModel::updateModel(const DockerContainer container, co
|
|||
const QByteArray clientsTableString = serverController->getTextFileFromContainer(container, credentials, clientsTableFile, error);
|
||||
if (error != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to get the clientsTable file from the server";
|
||||
endResetModel();
|
||||
return error;
|
||||
}
|
||||
|
||||
beginResetModel();
|
||||
m_clientsTable = QJsonDocument::fromJson(clientsTableString).array();
|
||||
|
||||
if (m_clientsTable.isEmpty()) {
|
||||
|
|
@ -103,6 +106,8 @@ ErrorCode ClientManagementModel::updateModel(const DockerContainer container, co
|
|||
error = getOpenVpnClients(container, credentials, serverController, count);
|
||||
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
|
||||
error = getWireGuardClients(container, credentials, serverController, count);
|
||||
} else if (container == DockerContainer::Xray) {
|
||||
error = getXrayClients(container, credentials, serverController, count);
|
||||
}
|
||||
if (error != ErrorCode::NoError) {
|
||||
endResetModel();
|
||||
|
|
@ -141,6 +146,10 @@ ErrorCode ClientManagementModel::updateModel(const DockerContainer container, co
|
|||
userData[configKey::dataSent] = client.dataSent;
|
||||
}
|
||||
|
||||
if (!client.allowedIps.isEmpty()) {
|
||||
userData[configKey::allowedIps] = client.allowedIps;
|
||||
}
|
||||
|
||||
obj[configKey::userData] = userData;
|
||||
m_clientsTable.replace(i, obj);
|
||||
break;
|
||||
|
|
@ -233,6 +242,68 @@ ErrorCode ClientManagementModel::getWireGuardClients(const DockerContainer conta
|
|||
}
|
||||
return error;
|
||||
}
|
||||
ErrorCode ClientManagementModel::getXrayClients(const DockerContainer container, const ServerCredentials& credentials,
|
||||
const QSharedPointer<ServerController> &serverController, int &count)
|
||||
{
|
||||
ErrorCode error = ErrorCode::NoError;
|
||||
|
||||
const QString serverConfigPath = amnezia::protocols::xray::serverConfigPath;
|
||||
const QString configString = serverController->getTextFileFromContainer(container, credentials, serverConfigPath, error);
|
||||
if (error != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to get the xray server config file from the server";
|
||||
return error;
|
||||
}
|
||||
|
||||
QJsonDocument serverConfig = QJsonDocument::fromJson(configString.toUtf8());
|
||||
if (serverConfig.isNull()) {
|
||||
logger.error() << "Failed to parse xray server config JSON";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
if (!serverConfig.object().contains("inbounds") || serverConfig.object()["inbounds"].toArray().isEmpty()) {
|
||||
logger.error() << "Invalid xray server config structure";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
const QJsonObject inbound = serverConfig.object()["inbounds"].toArray()[0].toObject();
|
||||
if (!inbound.contains("settings")) {
|
||||
logger.error() << "Missing settings in xray inbound config";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
const QJsonObject settings = inbound["settings"].toObject();
|
||||
if (!settings.contains("clients")) {
|
||||
logger.error() << "Missing clients in xray settings config";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
const QJsonArray clients = settings["clients"].toArray();
|
||||
for (const auto &clientValue : clients) {
|
||||
const QJsonObject clientObj = clientValue.toObject();
|
||||
if (!clientObj.contains("id")) {
|
||||
logger.error() << "Missing id in xray client config";
|
||||
continue;
|
||||
}
|
||||
QString clientId = clientObj["id"].toString();
|
||||
|
||||
QString xrayDefaultUuid = serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::xray::uuidPath, error);
|
||||
xrayDefaultUuid.replace("\n", "");
|
||||
|
||||
if (!isClientExists(clientId) && clientId != xrayDefaultUuid) {
|
||||
QJsonObject client;
|
||||
client[configKey::clientId] = clientId;
|
||||
|
||||
QJsonObject userData;
|
||||
userData[configKey::clientName] = QString("Client %1").arg(count);
|
||||
client[configKey::userData] = userData;
|
||||
|
||||
m_clientsTable.push_back(client);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementModel::wgShow(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, std::vector<WgShowData> &data)
|
||||
|
|
@ -267,8 +338,9 @@ ErrorCode ClientManagementModel::wgShow(const DockerContainer container, const S
|
|||
const auto peerList = parts.filter("peer:");
|
||||
const auto latestHandshakeList = parts.filter("latest handshake:");
|
||||
const auto transferredDataList = parts.filter("transfer:");
|
||||
const auto allowedIpsList = parts.filter("allowed ips:");
|
||||
|
||||
if (latestHandshakeList.isEmpty() || transferredDataList.isEmpty() || peerList.isEmpty()) {
|
||||
if (allowedIpsList.isEmpty() || latestHandshakeList.isEmpty() || transferredDataList.isEmpty() || peerList.isEmpty()) {
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
@ -282,18 +354,20 @@ ErrorCode ClientManagementModel::wgShow(const DockerContainer container, const S
|
|||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i < peerList.size() && i < transferredDataList.size(); ++i) {
|
||||
for (int i = 0; i < peerList.size() && i < transferredDataList.size() && i < latestHandshakeList.size() && i < allowedIpsList.size(); ++i) {
|
||||
|
||||
const auto transferredData = getStrValue(transferredDataList[i]).split(",");
|
||||
auto latestHandshake = getStrValue(latestHandshakeList[i]);
|
||||
auto serverBytesReceived = transferredData.front().trimmed();
|
||||
auto serverBytesSent = transferredData.back().trimmed();
|
||||
auto allowedIps = getStrValue(allowedIpsList[i]);
|
||||
|
||||
changeHandshakeFormat(latestHandshake);
|
||||
|
||||
serverBytesReceived.chop(QStringLiteral(" received").length());
|
||||
serverBytesSent.chop(QStringLiteral(" sent").length());
|
||||
|
||||
data.push_back({ getStrValue(peerList[i]), latestHandshake, serverBytesSent, serverBytesReceived });
|
||||
data.push_back({ getStrValue(peerList[i]), latestHandshake, serverBytesSent, serverBytesReceived, allowedIps });
|
||||
}
|
||||
|
||||
return error;
|
||||
|
|
@ -317,17 +391,67 @@ ErrorCode ClientManagementModel::appendClient(const DockerContainer container, c
|
|||
const QSharedPointer<ServerController> &serverController)
|
||||
{
|
||||
Proto protocol;
|
||||
if (container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
|
||||
protocol = Proto::OpenVpn;
|
||||
} else if (container == DockerContainer::OpenVpn || container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
|
||||
protocol = ContainerProps::defaultProtocol(container);
|
||||
} else {
|
||||
return ErrorCode::NoError;
|
||||
switch (container) {
|
||||
case DockerContainer::ShadowSocks:
|
||||
case DockerContainer::Cloak:
|
||||
protocol = Proto::OpenVpn;
|
||||
break;
|
||||
case DockerContainer::OpenVpn:
|
||||
case DockerContainer::WireGuard:
|
||||
case DockerContainer::Awg:
|
||||
case DockerContainer::Xray:
|
||||
protocol = ContainerProps::defaultProtocol(container);
|
||||
break;
|
||||
default:
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
auto protocolConfig = ContainerProps::getProtocolConfigFromContainer(protocol, containerConfig);
|
||||
return appendClient(protocolConfig, clientName, container, credentials, serverController);
|
||||
}
|
||||
|
||||
return appendClient(protocolConfig.value(config_key::clientId).toString(), clientName, container, credentials, serverController);
|
||||
ErrorCode ClientManagementModel::appendClient(QJsonObject &protocolConfig, const QString &clientName, const DockerContainer container,
|
||||
const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController)
|
||||
{
|
||||
QString clientId;
|
||||
if (container == DockerContainer::Xray) {
|
||||
if (!protocolConfig.contains("outbounds")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray outbounds = protocolConfig.value("outbounds").toArray();
|
||||
if (outbounds.isEmpty()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject outbound = outbounds[0].toObject();
|
||||
if (!outbound.contains("settings")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject settings = outbound["settings"].toObject();
|
||||
if (!settings.contains("vnext")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray vnext = settings["vnext"].toArray();
|
||||
if (vnext.isEmpty()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject vnextObj = vnext[0].toObject();
|
||||
if (!vnextObj.contains("users")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray users = vnextObj["users"].toArray();
|
||||
if (users.isEmpty()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject user = users[0].toObject();
|
||||
if (!user.contains("id")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
clientId = user["id"].toString();
|
||||
} else {
|
||||
clientId = protocolConfig.value(config_key::clientId).toString();
|
||||
}
|
||||
|
||||
return appendClient(clientId, clientName, container, credentials, serverController);
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QString &clientName, const DockerContainer container,
|
||||
|
|
@ -413,10 +537,27 @@ ErrorCode ClientManagementModel::revokeClient(const int row, const DockerContain
|
|||
auto client = m_clientsTable.at(row).toObject();
|
||||
QString clientId = client.value(configKey::clientId).toString();
|
||||
|
||||
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
|
||||
errorCode = revokeOpenVpn(row, container, credentials, serverIndex, serverController);
|
||||
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
|
||||
errorCode = revokeWireGuard(row, container, credentials, serverController);
|
||||
switch(container)
|
||||
{
|
||||
case DockerContainer::OpenVpn:
|
||||
case DockerContainer::ShadowSocks:
|
||||
case DockerContainer::Cloak: {
|
||||
errorCode = revokeOpenVpn(row, container, credentials, serverIndex, serverController);
|
||||
break;
|
||||
}
|
||||
case DockerContainer::WireGuard:
|
||||
case DockerContainer::Awg: {
|
||||
errorCode = revokeWireGuard(row, container, credentials, serverController);
|
||||
break;
|
||||
}
|
||||
case DockerContainer::Xray: {
|
||||
errorCode = revokeXray(row, container, credentials, serverController);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
logger.error() << "Internal error: received unexpected container type";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
}
|
||||
|
||||
if (errorCode == ErrorCode::NoError) {
|
||||
|
|
@ -454,19 +595,69 @@ ErrorCode ClientManagementModel::revokeClient(const QJsonObject &containerConfig
|
|||
}
|
||||
|
||||
Proto protocol;
|
||||
if (container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
|
||||
protocol = Proto::OpenVpn;
|
||||
} else if (container == DockerContainer::OpenVpn || container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
|
||||
protocol = ContainerProps::defaultProtocol(container);
|
||||
} else {
|
||||
return ErrorCode::NoError;
|
||||
|
||||
switch(container)
|
||||
{
|
||||
case DockerContainer::ShadowSocks:
|
||||
case DockerContainer::Cloak: {
|
||||
protocol = Proto::OpenVpn;
|
||||
break;
|
||||
}
|
||||
case DockerContainer::OpenVpn:
|
||||
case DockerContainer::WireGuard:
|
||||
case DockerContainer::Awg:
|
||||
case DockerContainer::Xray: {
|
||||
protocol = ContainerProps::defaultProtocol(container);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
logger.error() << "Internal error: received unexpected container type";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
}
|
||||
|
||||
auto protocolConfig = ContainerProps::getProtocolConfigFromContainer(protocol, containerConfig);
|
||||
|
||||
QString clientId;
|
||||
if (container == DockerContainer::Xray) {
|
||||
if (!protocolConfig.contains("outbounds")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray outbounds = protocolConfig.value("outbounds").toArray();
|
||||
if (outbounds.isEmpty()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject outbound = outbounds[0].toObject();
|
||||
if (!outbound.contains("settings")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject settings = outbound["settings"].toObject();
|
||||
if (!settings.contains("vnext")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray vnext = settings["vnext"].toArray();
|
||||
if (vnext.isEmpty()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject vnextObj = vnext[0].toObject();
|
||||
if (!vnextObj.contains("users")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonArray users = vnextObj["users"].toArray();
|
||||
if (users.isEmpty()) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
QJsonObject user = users[0].toObject();
|
||||
if (!user.contains("id")) {
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
clientId = user["id"].toString();
|
||||
} else {
|
||||
clientId = protocolConfig.value(config_key::clientId).toString();
|
||||
}
|
||||
|
||||
int row;
|
||||
bool clientExists = false;
|
||||
QString clientId = protocolConfig.value(config_key::clientId).toString();
|
||||
for (row = 0; row < rowCount(); row++) {
|
||||
auto client = m_clientsTable.at(row).toObject();
|
||||
if (clientId == client.value(configKey::clientId).toString()) {
|
||||
|
|
@ -478,11 +669,28 @@ ErrorCode ClientManagementModel::revokeClient(const QJsonObject &containerConfig
|
|||
return errorCode;
|
||||
}
|
||||
|
||||
if (container == DockerContainer::OpenVpn || container == DockerContainer::ShadowSocks || container == DockerContainer::Cloak) {
|
||||
switch (container)
|
||||
{
|
||||
case DockerContainer::OpenVpn:
|
||||
case DockerContainer::ShadowSocks:
|
||||
case DockerContainer::Cloak: {
|
||||
errorCode = revokeOpenVpn(row, container, credentials, serverIndex, serverController);
|
||||
} else if (container == DockerContainer::WireGuard || container == DockerContainer::Awg) {
|
||||
errorCode = revokeWireGuard(row, container, credentials, serverController);
|
||||
break;
|
||||
}
|
||||
case DockerContainer::WireGuard:
|
||||
case DockerContainer::Awg: {
|
||||
errorCode = revokeWireGuard(row, container, credentials, serverController);
|
||||
break;
|
||||
}
|
||||
case DockerContainer::Xray: {
|
||||
errorCode = revokeXray(row, container, credentials, serverController);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
logger.error() << "Internal error: received unexpected container type";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
|
|
@ -598,6 +806,117 @@ ErrorCode ClientManagementModel::revokeWireGuard(const int row, const DockerCont
|
|||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
ErrorCode ClientManagementModel::revokeXray(const int row,
|
||||
const DockerContainer container,
|
||||
const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController)
|
||||
{
|
||||
ErrorCode error = ErrorCode::NoError;
|
||||
|
||||
// Get server config
|
||||
const QString serverConfigPath = amnezia::protocols::xray::serverConfigPath;
|
||||
const QString configString = serverController->getTextFileFromContainer(container, credentials, serverConfigPath, error);
|
||||
if (error != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to get the xray server config file";
|
||||
return error;
|
||||
}
|
||||
|
||||
QJsonDocument serverConfig = QJsonDocument::fromJson(configString.toUtf8());
|
||||
if (serverConfig.isNull()) {
|
||||
logger.error() << "Failed to parse xray server config JSON";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
// Get client ID to remove
|
||||
auto client = m_clientsTable.at(row).toObject();
|
||||
QString clientId = client.value(configKey::clientId).toString();
|
||||
|
||||
// Remove client from server config
|
||||
QJsonObject configObj = serverConfig.object();
|
||||
if (!configObj.contains("inbounds")) {
|
||||
logger.error() << "Missing inbounds in xray config";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
QJsonArray inbounds = configObj["inbounds"].toArray();
|
||||
if (inbounds.isEmpty()) {
|
||||
logger.error() << "Empty inbounds array in xray config";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
QJsonObject inbound = inbounds[0].toObject();
|
||||
if (!inbound.contains("settings")) {
|
||||
logger.error() << "Missing settings in xray inbound config";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
QJsonObject settings = inbound["settings"].toObject();
|
||||
if (!settings.contains("clients")) {
|
||||
logger.error() << "Missing clients in xray settings";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
QJsonArray clients = settings["clients"].toArray();
|
||||
if (clients.isEmpty()) {
|
||||
logger.error() << "Empty clients array in xray config";
|
||||
return ErrorCode::InternalError;
|
||||
}
|
||||
|
||||
for (int i = 0; i < clients.size(); ++i) {
|
||||
QJsonObject clientObj = clients[i].toObject();
|
||||
if (clientObj.contains("id") && clientObj["id"].toString() == clientId) {
|
||||
clients.removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update server config
|
||||
settings["clients"] = clients;
|
||||
inbound["settings"] = settings;
|
||||
inbounds[0] = inbound;
|
||||
configObj["inbounds"] = inbounds;
|
||||
|
||||
// Upload updated config
|
||||
error = serverController->uploadTextFileToContainer(
|
||||
container,
|
||||
credentials,
|
||||
QJsonDocument(configObj).toJson(),
|
||||
serverConfigPath
|
||||
);
|
||||
if (error != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to upload updated xray config";
|
||||
return error;
|
||||
}
|
||||
|
||||
// Remove from local table
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
m_clientsTable.removeAt(row);
|
||||
endRemoveRows();
|
||||
|
||||
// Update clients table file on server
|
||||
const QByteArray clientsTableString = QJsonDocument(m_clientsTable).toJson();
|
||||
QString clientsTableFile = QString("/opt/amnezia/%1/clientsTable")
|
||||
.arg(ContainerProps::containerTypeToString(container));
|
||||
|
||||
error = serverController->uploadTextFileToContainer(container, credentials, clientsTableString, clientsTableFile);
|
||||
if (error != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to upload the clientsTable file";
|
||||
}
|
||||
|
||||
// Restart container
|
||||
QString restartScript = QString("sudo docker restart $CONTAINER_NAME");
|
||||
error = serverController->runScript(
|
||||
credentials,
|
||||
serverController->replaceVars(restartScript, serverController->genVarsForScript(credentials, container))
|
||||
);
|
||||
if (error != ErrorCode::NoError) {
|
||||
logger.error() << "Failed to restart xray container";
|
||||
return error;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ClientManagementModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
|
|
@ -606,5 +925,6 @@ QHash<int, QByteArray> ClientManagementModel::roleNames() const
|
|||
roles[LatestHandshakeRole] = "latestHandshake";
|
||||
roles[DataReceivedRole] = "dataReceived";
|
||||
roles[DataSentRole] = "dataSent";
|
||||
roles[AllowedIpsRole] = "allowedIps";
|
||||
return roles;
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,8 @@ public:
|
|||
CreationDateRole,
|
||||
LatestHandshakeRole,
|
||||
DataReceivedRole,
|
||||
DataSentRole
|
||||
DataSentRole,
|
||||
AllowedIpsRole
|
||||
};
|
||||
|
||||
struct WgShowData
|
||||
|
|
@ -26,6 +27,7 @@ public:
|
|||
QString latestHandshake;
|
||||
QString dataReceived;
|
||||
QString dataSent;
|
||||
QString allowedIps;
|
||||
};
|
||||
|
||||
ClientManagementModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||
|
|
@ -38,6 +40,8 @@ public slots:
|
|||
const QSharedPointer<ServerController> &serverController);
|
||||
ErrorCode appendClient(const DockerContainer container, const ServerCredentials &credentials, const QJsonObject &containerConfig,
|
||||
const QString &clientName, const QSharedPointer<ServerController> &serverController);
|
||||
ErrorCode appendClient(QJsonObject &protocolConfig, const QString &clientName,const DockerContainer container,
|
||||
const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController);
|
||||
ErrorCode appendClient(const QString &clientId, const QString &clientName, const DockerContainer container,
|
||||
const ServerCredentials &credentials, const QSharedPointer<ServerController> &serverController);
|
||||
ErrorCode renameClient(const int row, const QString &userName, const DockerContainer container, const ServerCredentials &credentials,
|
||||
|
|
@ -62,11 +66,15 @@ private:
|
|||
const QSharedPointer<ServerController> &serverController);
|
||||
ErrorCode revokeWireGuard(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController);
|
||||
ErrorCode revokeXray(const int row, const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController);
|
||||
|
||||
ErrorCode getOpenVpnClients(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, int &count);
|
||||
ErrorCode getWireGuardClients(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, int &count);
|
||||
ErrorCode getXrayClients(const DockerContainer container, const ServerCredentials& credentials,
|
||||
const QSharedPointer<ServerController> &serverController, int &count);
|
||||
|
||||
ErrorCode wgShow(const DockerContainer container, const ServerCredentials &credentials,
|
||||
const QSharedPointer<ServerController> &serverController, std::vector<WgShowData> &data);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const
|
|||
case IsCurrentlyProcessedRole: return container == static_cast<DockerContainer>(m_processedContainerIndex);
|
||||
case IsSupportedRole: return ContainerProps::isSupportedByCurrentPlatform(container);
|
||||
case IsShareableRole: return ContainerProps::isShareable(container);
|
||||
case InstallPageOrderRole: return ContainerProps::installPageOrder(container);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
|
|
@ -93,6 +94,26 @@ bool ContainersModel::isServiceContainer(const int containerIndex)
|
|||
return qvariant_cast<amnezia::ServiceType>(data(index(containerIndex), ServiceTypeRole) == ServiceType::Other);
|
||||
}
|
||||
|
||||
bool ContainersModel::hasInstalledServices()
|
||||
{
|
||||
for (const auto &container : m_containers.keys()) {
|
||||
if (ContainerProps::containerService(container) == ServiceType::Other) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ContainersModel::hasInstalledProtocols()
|
||||
{
|
||||
for (const auto &container : m_containers.keys()) {
|
||||
if (ContainerProps::containerService(container) == ServiceType::Vpn) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ContainersModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
|
|
@ -112,5 +133,7 @@ QHash<int, QByteArray> ContainersModel::roleNames() const
|
|||
roles[IsCurrentlyProcessedRole] = "isCurrentlyProcessed";
|
||||
roles[IsSupportedRole] = "isSupported";
|
||||
roles[IsShareableRole] = "isShareable";
|
||||
|
||||
roles[InstallPageOrderRole] = "installPageOrder";
|
||||
return roles;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,9 @@ public:
|
|||
IsCurrentlyProcessedRole,
|
||||
IsDefaultRole,
|
||||
IsSupportedRole,
|
||||
IsShareableRole
|
||||
IsShareableRole,
|
||||
|
||||
InstallPageOrderRole
|
||||
};
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
|
@ -52,6 +54,9 @@ public slots:
|
|||
bool isSupportedByCurrentPlatform(const int containerIndex);
|
||||
bool isServiceContainer(const int containerIndex);
|
||||
|
||||
bool hasInstalledServices();
|
||||
bool hasInstalledProtocols();
|
||||
|
||||
protected:
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
|
|
|
|||
|
|
@ -92,9 +92,9 @@ int LanguageModel::getCurrentLanguageIndex()
|
|||
|
||||
int LanguageModel::getLineHeightAppend()
|
||||
{
|
||||
int langIndex = getCurrentLanguageIndex();
|
||||
switch (langIndex) {
|
||||
case 5: return 10; break; // Burmese
|
||||
auto language = static_cast<LanguageSettings::AvailableLanguageEnum>(getCurrentLanguageIndex());
|
||||
switch (language) {
|
||||
case LanguageSettings::AvailableLanguageEnum::Burmese: return 10; break;
|
||||
default: return 0; break;
|
||||
}
|
||||
}
|
||||
|
|
@ -103,3 +103,12 @@ QString LanguageModel::getCurrentLanguageName()
|
|||
{
|
||||
return m_availableLanguages[getCurrentLanguageIndex()].name;
|
||||
}
|
||||
|
||||
QString LanguageModel::getCurrentSiteUrl()
|
||||
{
|
||||
auto language = static_cast<LanguageSettings::AvailableLanguageEnum>(getCurrentLanguageIndex());
|
||||
switch (language) {
|
||||
case LanguageSettings::AvailableLanguageEnum::Russian: return "https://storage.googleapis.com/amnezia/amnezia.org";
|
||||
default: return "https://amnezia.org";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ public slots:
|
|||
int getCurrentLanguageIndex();
|
||||
int getLineHeightAppend();
|
||||
QString getCurrentLanguageName();
|
||||
QString getCurrentSiteUrl();
|
||||
|
||||
signals:
|
||||
void updateTranslations(const QLocale &locale);
|
||||
|
|
|
|||
|
|
@ -21,28 +21,30 @@ bool AwgConfigModel::setData(const QModelIndex &index, const QVariant &value, in
|
|||
}
|
||||
|
||||
switch (role) {
|
||||
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
|
||||
case Roles::MtuRole: m_protocolConfig.insert(config_key::mtu, value.toString()); break;
|
||||
case Roles::JunkPacketCountRole: m_protocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
|
||||
case Roles::JunkPacketMinSizeRole: m_protocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
|
||||
case Roles::JunkPacketMaxSizeRole: m_protocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
|
||||
case Roles::InitPacketJunkSizeRole:
|
||||
m_protocolConfig.insert(config_key::initPacketJunkSize, value.toString());
|
||||
case Roles::SubnetAddressRole: m_serverProtocolConfig.insert(config_key::subnet_address, value.toString()); break;
|
||||
case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, value.toString()); break;
|
||||
|
||||
case Roles::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break;
|
||||
case Roles::ClientJunkPacketCountRole: m_clientProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
|
||||
case Roles::ClientJunkPacketMinSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
|
||||
case Roles::ClientJunkPacketMaxSizeRole: m_clientProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
|
||||
|
||||
case Roles::ServerJunkPacketCountRole: m_serverProtocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
|
||||
case Roles::ServerJunkPacketMinSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
|
||||
case Roles::ServerJunkPacketMaxSizeRole: m_serverProtocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
|
||||
case Roles::ServerInitPacketJunkSizeRole: m_serverProtocolConfig.insert(config_key::initPacketJunkSize, value.toString()); break;
|
||||
case Roles::ServerResponsePacketJunkSizeRole:
|
||||
m_serverProtocolConfig.insert(config_key::responsePacketJunkSize, value.toString());
|
||||
break;
|
||||
case Roles::ResponsePacketJunkSizeRole:
|
||||
m_protocolConfig.insert(config_key::responsePacketJunkSize, value.toString());
|
||||
case Roles::ServerInitPacketMagicHeaderRole: m_serverProtocolConfig.insert(config_key::initPacketMagicHeader, value.toString()); break;
|
||||
case Roles::ServerResponsePacketMagicHeaderRole:
|
||||
m_serverProtocolConfig.insert(config_key::responsePacketMagicHeader, value.toString());
|
||||
break;
|
||||
case Roles::InitPacketMagicHeaderRole:
|
||||
m_protocolConfig.insert(config_key::initPacketMagicHeader, value.toString());
|
||||
case Roles::ServerUnderloadPacketMagicHeaderRole:
|
||||
m_serverProtocolConfig.insert(config_key::underloadPacketMagicHeader, value.toString());
|
||||
break;
|
||||
case Roles::ResponsePacketMagicHeaderRole:
|
||||
m_protocolConfig.insert(config_key::responsePacketMagicHeader, value.toString());
|
||||
break;
|
||||
case Roles::UnderloadPacketMagicHeaderRole:
|
||||
m_protocolConfig.insert(config_key::underloadPacketMagicHeader, value.toString());
|
||||
break;
|
||||
case Roles::TransportPacketMagicHeaderRole:
|
||||
m_protocolConfig.insert(config_key::transportPacketMagicHeader, value.toString());
|
||||
case Roles::ServerTransportPacketMagicHeaderRole:
|
||||
m_serverProtocolConfig.insert(config_key::transportPacketMagicHeader, value.toString());
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -57,17 +59,23 @@ QVariant AwgConfigModel::data(const QModelIndex &index, int role) const
|
|||
}
|
||||
|
||||
switch (role) {
|
||||
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString();
|
||||
case Roles::MtuRole: return m_protocolConfig.value(config_key::mtu).toString();
|
||||
case Roles::JunkPacketCountRole: return m_protocolConfig.value(config_key::junkPacketCount);
|
||||
case Roles::JunkPacketMinSizeRole: return m_protocolConfig.value(config_key::junkPacketMinSize);
|
||||
case Roles::JunkPacketMaxSizeRole: return m_protocolConfig.value(config_key::junkPacketMaxSize);
|
||||
case Roles::InitPacketJunkSizeRole: return m_protocolConfig.value(config_key::initPacketJunkSize);
|
||||
case Roles::ResponsePacketJunkSizeRole: return m_protocolConfig.value(config_key::responsePacketJunkSize);
|
||||
case Roles::InitPacketMagicHeaderRole: return m_protocolConfig.value(config_key::initPacketMagicHeader);
|
||||
case Roles::ResponsePacketMagicHeaderRole: return m_protocolConfig.value(config_key::responsePacketMagicHeader);
|
||||
case Roles::UnderloadPacketMagicHeaderRole: return m_protocolConfig.value(config_key::underloadPacketMagicHeader);
|
||||
case Roles::TransportPacketMagicHeaderRole: return m_protocolConfig.value(config_key::transportPacketMagicHeader);
|
||||
case Roles::SubnetAddressRole: return m_serverProtocolConfig.value(config_key::subnet_address).toString();
|
||||
case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString();
|
||||
|
||||
case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu);
|
||||
case Roles::ClientJunkPacketCountRole: return m_clientProtocolConfig.value(config_key::junkPacketCount);
|
||||
case Roles::ClientJunkPacketMinSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMinSize);
|
||||
case Roles::ClientJunkPacketMaxSizeRole: return m_clientProtocolConfig.value(config_key::junkPacketMaxSize);
|
||||
|
||||
case Roles::ServerJunkPacketCountRole: return m_serverProtocolConfig.value(config_key::junkPacketCount);
|
||||
case Roles::ServerJunkPacketMinSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMinSize);
|
||||
case Roles::ServerJunkPacketMaxSizeRole: return m_serverProtocolConfig.value(config_key::junkPacketMaxSize);
|
||||
case Roles::ServerInitPacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::initPacketJunkSize);
|
||||
case Roles::ServerResponsePacketJunkSizeRole: return m_serverProtocolConfig.value(config_key::responsePacketJunkSize);
|
||||
case Roles::ServerInitPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::initPacketMagicHeader);
|
||||
case Roles::ServerResponsePacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::responsePacketMagicHeader);
|
||||
case Roles::ServerUnderloadPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::underloadPacketMagicHeader);
|
||||
case Roles::ServerTransportPacketMagicHeaderRole: return m_serverProtocolConfig.value(config_key::transportPacketMagicHeader);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
|
|
@ -80,52 +88,64 @@ void AwgConfigModel::updateModel(const QJsonObject &config)
|
|||
|
||||
m_fullConfig = config;
|
||||
|
||||
QJsonObject protocolConfig = config.value(config_key::awg).toObject();
|
||||
QJsonObject serverProtocolConfig = config.value(config_key::awg).toObject();
|
||||
|
||||
m_protocolConfig[config_key::last_config] = protocolConfig.value(config_key::last_config);
|
||||
m_protocolConfig[config_key::port] = protocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
||||
m_protocolConfig[config_key::mtu] = protocolConfig.value(config_key::mtu).toString(protocols::awg::defaultMtu);
|
||||
m_protocolConfig[config_key::junkPacketCount] =
|
||||
protocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
||||
m_protocolConfig[config_key::junkPacketMinSize] =
|
||||
protocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
||||
m_protocolConfig[config_key::junkPacketMaxSize] =
|
||||
protocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
||||
m_protocolConfig[config_key::initPacketJunkSize] =
|
||||
protocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
|
||||
m_protocolConfig[config_key::responsePacketJunkSize] =
|
||||
protocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
|
||||
m_protocolConfig[config_key::initPacketMagicHeader] =
|
||||
protocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
||||
m_protocolConfig[config_key::responsePacketMagicHeader] =
|
||||
protocolConfig.value(config_key::responsePacketMagicHeader)
|
||||
.toString(protocols::awg::defaultResponsePacketMagicHeader);
|
||||
m_protocolConfig[config_key::underloadPacketMagicHeader] =
|
||||
protocolConfig.value(config_key::underloadPacketMagicHeader)
|
||||
.toString(protocols::awg::defaultUnderloadPacketMagicHeader);
|
||||
m_protocolConfig[config_key::transportPacketMagicHeader] =
|
||||
protocolConfig.value(config_key::transportPacketMagicHeader)
|
||||
.toString(protocols::awg::defaultTransportPacketMagicHeader);
|
||||
auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::Awg), Proto::Awg);
|
||||
m_serverProtocolConfig.insert(config_key::transport_proto,
|
||||
serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
|
||||
m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config);
|
||||
m_serverProtocolConfig[config_key::subnet_address] = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
|
||||
m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
||||
m_serverProtocolConfig[config_key::junkPacketCount] =
|
||||
serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
||||
m_serverProtocolConfig[config_key::junkPacketMinSize] =
|
||||
serverProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
||||
m_serverProtocolConfig[config_key::junkPacketMaxSize] =
|
||||
serverProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
||||
m_serverProtocolConfig[config_key::initPacketJunkSize] =
|
||||
serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
|
||||
m_serverProtocolConfig[config_key::responsePacketJunkSize] =
|
||||
serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
|
||||
m_serverProtocolConfig[config_key::initPacketMagicHeader] =
|
||||
serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
||||
m_serverProtocolConfig[config_key::responsePacketMagicHeader] =
|
||||
serverProtocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader);
|
||||
m_serverProtocolConfig[config_key::underloadPacketMagicHeader] =
|
||||
serverProtocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader);
|
||||
m_serverProtocolConfig[config_key::transportPacketMagicHeader] =
|
||||
serverProtocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader);
|
||||
|
||||
auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
|
||||
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
||||
m_clientProtocolConfig[config_key::mtu] = clientProtocolConfig[config_key::mtu].toString(protocols::awg::defaultMtu);
|
||||
m_clientProtocolConfig[config_key::junkPacketCount] =
|
||||
clientProtocolConfig.value(config_key::junkPacketCount).toString(m_serverProtocolConfig[config_key::junkPacketCount].toString());
|
||||
m_clientProtocolConfig[config_key::junkPacketMinSize] =
|
||||
clientProtocolConfig.value(config_key::junkPacketMinSize).toString(m_serverProtocolConfig[config_key::junkPacketMinSize].toString());
|
||||
m_clientProtocolConfig[config_key::junkPacketMaxSize] =
|
||||
clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(m_serverProtocolConfig[config_key::junkPacketMaxSize].toString());
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QJsonObject AwgConfigModel::getConfig()
|
||||
{
|
||||
const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject());
|
||||
const AwgConfig newConfig(m_protocolConfig);
|
||||
const AwgConfig newConfig(m_serverProtocolConfig);
|
||||
|
||||
if (!oldConfig.hasEqualServerSettings(newConfig)) {
|
||||
m_protocolConfig.remove(config_key::last_config);
|
||||
m_serverProtocolConfig.remove(config_key::last_config);
|
||||
} else {
|
||||
auto lastConfig = m_protocolConfig.value(config_key::last_config).toString();
|
||||
auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
|
||||
QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
||||
jsonConfig[config_key::mtu] = newConfig.mtu;
|
||||
jsonConfig[config_key::mtu] = m_clientProtocolConfig[config_key::mtu];
|
||||
jsonConfig[config_key::junkPacketCount] = m_clientProtocolConfig[config_key::junkPacketCount];
|
||||
jsonConfig[config_key::junkPacketMinSize] = m_clientProtocolConfig[config_key::junkPacketMinSize];
|
||||
jsonConfig[config_key::junkPacketMaxSize] = m_clientProtocolConfig[config_key::junkPacketMaxSize];
|
||||
|
||||
m_protocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
|
||||
m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
|
||||
}
|
||||
|
||||
m_fullConfig.insert(config_key::awg, m_protocolConfig);
|
||||
m_fullConfig.insert(config_key::awg, m_serverProtocolConfig);
|
||||
return m_fullConfig;
|
||||
}
|
||||
|
||||
|
|
@ -139,56 +159,75 @@ bool AwgConfigModel::isPacketSizeEqual(const int s1, const int s2)
|
|||
return (AwgConstant::messageInitiationSize + s1 == AwgConstant::messageResponseSize + s2);
|
||||
}
|
||||
|
||||
bool AwgConfigModel::isServerSettingsEqual()
|
||||
{
|
||||
const AwgConfig oldConfig(m_fullConfig.value(config_key::awg).toObject());
|
||||
const AwgConfig newConfig(m_serverProtocolConfig);
|
||||
|
||||
return oldConfig.hasEqualServerSettings(newConfig);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> AwgConfigModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
|
||||
roles[SubnetAddressRole] = "subnetAddress";
|
||||
roles[PortRole] = "port";
|
||||
roles[MtuRole] = "mtu";
|
||||
roles[JunkPacketCountRole] = "junkPacketCount";
|
||||
roles[JunkPacketMinSizeRole] = "junkPacketMinSize";
|
||||
roles[JunkPacketMaxSizeRole] = "junkPacketMaxSize";
|
||||
roles[InitPacketJunkSizeRole] = "initPacketJunkSize";
|
||||
roles[ResponsePacketJunkSizeRole] = "responsePacketJunkSize";
|
||||
roles[InitPacketMagicHeaderRole] = "initPacketMagicHeader";
|
||||
roles[ResponsePacketMagicHeaderRole] = "responsePacketMagicHeader";
|
||||
roles[UnderloadPacketMagicHeaderRole] = "underloadPacketMagicHeader";
|
||||
roles[TransportPacketMagicHeaderRole] = "transportPacketMagicHeader";
|
||||
|
||||
roles[ClientMtuRole] = "clientMtu";
|
||||
roles[ClientJunkPacketCountRole] = "clientJunkPacketCount";
|
||||
roles[ClientJunkPacketMinSizeRole] = "clientJunkPacketMinSize";
|
||||
roles[ClientJunkPacketMaxSizeRole] = "clientJunkPacketMaxSize";
|
||||
|
||||
roles[ServerJunkPacketCountRole] = "serverJunkPacketCount";
|
||||
roles[ServerJunkPacketMinSizeRole] = "serverJunkPacketMinSize";
|
||||
roles[ServerJunkPacketMaxSizeRole] = "serverJunkPacketMaxSize";
|
||||
roles[ServerInitPacketJunkSizeRole] = "serverInitPacketJunkSize";
|
||||
roles[ServerResponsePacketJunkSizeRole] = "serverResponsePacketJunkSize";
|
||||
roles[ServerInitPacketMagicHeaderRole] = "serverInitPacketMagicHeader";
|
||||
roles[ServerResponsePacketMagicHeaderRole] = "serverResponsePacketMagicHeader";
|
||||
roles[ServerUnderloadPacketMagicHeaderRole] = "serverUnderloadPacketMagicHeader";
|
||||
roles[ServerTransportPacketMagicHeaderRole] = "serverTransportPacketMagicHeader";
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
AwgConfig::AwgConfig(const QJsonObject &jsonConfig)
|
||||
AwgConfig::AwgConfig(const QJsonObject &serverProtocolConfig)
|
||||
{
|
||||
port = jsonConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
||||
mtu = jsonConfig.value(config_key::mtu).toString(protocols::awg::defaultMtu);
|
||||
junkPacketCount = jsonConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
||||
junkPacketMinSize =
|
||||
jsonConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
||||
junkPacketMaxSize =
|
||||
jsonConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
||||
initPacketJunkSize =
|
||||
jsonConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
|
||||
responsePacketJunkSize =
|
||||
jsonConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
|
||||
initPacketMagicHeader =
|
||||
jsonConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
||||
responsePacketMagicHeader = jsonConfig.value(config_key::responsePacketMagicHeader)
|
||||
.toString(protocols::awg::defaultResponsePacketMagicHeader);
|
||||
underloadPacketMagicHeader = jsonConfig.value(config_key::underloadPacketMagicHeader)
|
||||
.toString(protocols::awg::defaultUnderloadPacketMagicHeader);
|
||||
transportPacketMagicHeader = jsonConfig.value(config_key::transportPacketMagicHeader)
|
||||
.toString(protocols::awg::defaultTransportPacketMagicHeader);
|
||||
auto lastConfig = serverProtocolConfig.value(config_key::last_config).toString();
|
||||
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
||||
clientMtu = clientProtocolConfig[config_key::mtu].toString(protocols::awg::defaultMtu);
|
||||
clientJunkPacketCount = clientProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
||||
clientJunkPacketMinSize = clientProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
||||
clientJunkPacketMaxSize = clientProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
||||
|
||||
subnetAddress = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
|
||||
port = serverProtocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
||||
serverJunkPacketCount = serverProtocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
||||
serverJunkPacketMinSize = serverProtocolConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize);
|
||||
serverJunkPacketMaxSize = serverProtocolConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize);
|
||||
serverInitPacketJunkSize = serverProtocolConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize);
|
||||
serverResponsePacketJunkSize =
|
||||
serverProtocolConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize);
|
||||
serverInitPacketMagicHeader =
|
||||
serverProtocolConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader);
|
||||
serverResponsePacketMagicHeader =
|
||||
serverProtocolConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader);
|
||||
serverUnderloadPacketMagicHeader =
|
||||
serverProtocolConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader);
|
||||
serverTransportPacketMagicHeader =
|
||||
serverProtocolConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader);
|
||||
}
|
||||
|
||||
bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const
|
||||
{
|
||||
if (port != other.port || junkPacketCount != other.junkPacketCount || junkPacketMinSize != other.junkPacketMinSize
|
||||
|| junkPacketMaxSize != other.junkPacketMaxSize || initPacketJunkSize != other.initPacketJunkSize
|
||||
|| responsePacketJunkSize != other.responsePacketJunkSize || initPacketMagicHeader != other.initPacketMagicHeader
|
||||
|| responsePacketMagicHeader != other.responsePacketMagicHeader
|
||||
|| underloadPacketMagicHeader != other.underloadPacketMagicHeader
|
||||
|| transportPacketMagicHeader != other.transportPacketMagicHeader) {
|
||||
if (subnetAddress != other.subnetAddress || port != other.port || serverJunkPacketCount != other.serverJunkPacketCount
|
||||
|| serverJunkPacketMinSize != other.serverJunkPacketMinSize || serverJunkPacketMaxSize != other.serverJunkPacketMaxSize
|
||||
|| serverInitPacketJunkSize != other.serverInitPacketJunkSize || serverResponsePacketJunkSize != other.serverResponsePacketJunkSize
|
||||
|| serverInitPacketMagicHeader != other.serverInitPacketMagicHeader
|
||||
|| serverResponsePacketMagicHeader != other.serverResponsePacketMagicHeader
|
||||
|| serverUnderloadPacketMagicHeader != other.serverUnderloadPacketMagicHeader
|
||||
|| serverTransportPacketMagicHeader != other.serverTransportPacketMagicHeader) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -196,7 +235,8 @@ bool AwgConfig::hasEqualServerSettings(const AwgConfig &other) const
|
|||
|
||||
bool AwgConfig::hasEqualClientSettings(const AwgConfig &other) const
|
||||
{
|
||||
if (mtu != other.mtu) {
|
||||
if (clientMtu != other.clientMtu || clientJunkPacketCount != other.clientJunkPacketCount
|
||||
|| clientJunkPacketMinSize != other.clientJunkPacketMinSize || clientJunkPacketMaxSize != other.clientJunkPacketMaxSize) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -15,17 +15,23 @@ struct AwgConfig
|
|||
{
|
||||
AwgConfig(const QJsonObject &jsonConfig);
|
||||
|
||||
QString subnetAddress;
|
||||
QString port;
|
||||
QString mtu;
|
||||
QString junkPacketCount;
|
||||
QString junkPacketMinSize;
|
||||
QString junkPacketMaxSize;
|
||||
QString initPacketJunkSize;
|
||||
QString responsePacketJunkSize;
|
||||
QString initPacketMagicHeader;
|
||||
QString responsePacketMagicHeader;
|
||||
QString underloadPacketMagicHeader;
|
||||
QString transportPacketMagicHeader;
|
||||
|
||||
QString clientMtu;
|
||||
QString clientJunkPacketCount;
|
||||
QString clientJunkPacketMinSize;
|
||||
QString clientJunkPacketMaxSize;
|
||||
|
||||
QString serverJunkPacketCount;
|
||||
QString serverJunkPacketMinSize;
|
||||
QString serverJunkPacketMaxSize;
|
||||
QString serverInitPacketJunkSize;
|
||||
QString serverResponsePacketJunkSize;
|
||||
QString serverInitPacketMagicHeader;
|
||||
QString serverResponsePacketMagicHeader;
|
||||
QString serverUnderloadPacketMagicHeader;
|
||||
QString serverTransportPacketMagicHeader;
|
||||
|
||||
bool hasEqualServerSettings(const AwgConfig &other) const;
|
||||
bool hasEqualClientSettings(const AwgConfig &other) const;
|
||||
|
|
@ -38,17 +44,23 @@ class AwgConfigModel : public QAbstractListModel
|
|||
|
||||
public:
|
||||
enum Roles {
|
||||
PortRole = Qt::UserRole + 1,
|
||||
MtuRole,
|
||||
JunkPacketCountRole,
|
||||
JunkPacketMinSizeRole,
|
||||
JunkPacketMaxSizeRole,
|
||||
InitPacketJunkSizeRole,
|
||||
ResponsePacketJunkSizeRole,
|
||||
InitPacketMagicHeaderRole,
|
||||
ResponsePacketMagicHeaderRole,
|
||||
UnderloadPacketMagicHeaderRole,
|
||||
TransportPacketMagicHeaderRole
|
||||
SubnetAddressRole = Qt::UserRole + 1,
|
||||
PortRole,
|
||||
|
||||
ClientMtuRole,
|
||||
ClientJunkPacketCountRole,
|
||||
ClientJunkPacketMinSizeRole,
|
||||
ClientJunkPacketMaxSizeRole,
|
||||
|
||||
ServerJunkPacketCountRole,
|
||||
ServerJunkPacketMinSizeRole,
|
||||
ServerJunkPacketMaxSizeRole,
|
||||
ServerInitPacketJunkSizeRole,
|
||||
ServerResponsePacketJunkSizeRole,
|
||||
ServerInitPacketMagicHeaderRole,
|
||||
ServerResponsePacketMagicHeaderRole,
|
||||
ServerUnderloadPacketMagicHeaderRole,
|
||||
ServerTransportPacketMagicHeaderRole
|
||||
};
|
||||
|
||||
explicit AwgConfigModel(QObject *parent = nullptr);
|
||||
|
|
@ -65,12 +77,15 @@ public slots:
|
|||
bool isHeadersEqual(const QString &h1, const QString &h2, const QString &h3, const QString &h4);
|
||||
bool isPacketSizeEqual(const int s1, const int s2);
|
||||
|
||||
bool isServerSettingsEqual();
|
||||
|
||||
protected:
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
private:
|
||||
DockerContainer m_container;
|
||||
QJsonObject m_protocolConfig;
|
||||
QJsonObject m_serverProtocolConfig;
|
||||
QJsonObject m_clientProtocolConfig;
|
||||
QJsonObject m_fullConfig;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -51,14 +51,11 @@ void CloakConfigModel::updateModel(const QJsonObject &config)
|
|||
m_fullConfig = config;
|
||||
QJsonObject protocolConfig = config.value(config_key::cloak).toObject();
|
||||
|
||||
m_protocolConfig.insert(config_key::cipher,
|
||||
protocolConfig.value(config_key::cipher).toString(protocols::cloak::defaultCipher));
|
||||
|
||||
m_protocolConfig.insert(config_key::port,
|
||||
protocolConfig.value(config_key::port).toString(protocols::cloak::defaultPort));
|
||||
|
||||
m_protocolConfig.insert(config_key::site,
|
||||
protocolConfig.value(config_key::site).toString(protocols::cloak::defaultRedirSite));
|
||||
auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::Cloak), Proto::Cloak);
|
||||
m_protocolConfig.insert(config_key::transport_proto, protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
|
||||
m_protocolConfig.insert(config_key::cipher, protocolConfig.value(config_key::cipher).toString(protocols::cloak::defaultCipher));
|
||||
m_protocolConfig.insert(config_key::port, protocolConfig.value(config_key::port).toString(protocols::cloak::defaultPort));
|
||||
m_protocolConfig.insert(config_key::site, protocolConfig.value(config_key::site).toString(protocols::cloak::defaultRedirSite));
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,8 +35,7 @@ QVariant Ikev2ConfigModel::data(const QModelIndex &index, int role) const
|
|||
|
||||
switch (role) {
|
||||
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort);
|
||||
case Roles::CipherRole:
|
||||
return m_protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher);
|
||||
case Roles::CipherRole: return m_protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
|
|
@ -50,11 +49,8 @@ void Ikev2ConfigModel::updateModel(const QJsonObject &config)
|
|||
m_fullConfig = config;
|
||||
QJsonObject protocolConfig = config.value(config_key::shadowsocks).toObject();
|
||||
|
||||
m_protocolConfig.insert(config_key::cipher,
|
||||
protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher));
|
||||
|
||||
m_protocolConfig.insert(config_key::port,
|
||||
protocolConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort));
|
||||
m_protocolConfig.insert(config_key::cipher, protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher));
|
||||
m_protocolConfig.insert(config_key::port, protocolConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort));
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,7 @@ bool OpenVpnConfigModel::setData(const QModelIndex &index, const QVariant &value
|
|||
}
|
||||
|
||||
switch (role) {
|
||||
case Roles::SubnetAddressRole:
|
||||
m_protocolConfig.insert(amnezia::config_key::subnet_address, value.toString());
|
||||
break;
|
||||
case Roles::SubnetAddressRole: m_protocolConfig.insert(amnezia::config_key::subnet_address, value.toString()); break;
|
||||
case Roles::TransportProtoRole: m_protocolConfig.insert(config_key::transport_proto, value.toString()); break;
|
||||
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
|
||||
case Roles::AutoNegotiateEncryprionRole: m_protocolConfig.insert(config_key::ncp_disable, !value.toBool()); break;
|
||||
|
|
@ -29,12 +27,8 @@ bool OpenVpnConfigModel::setData(const QModelIndex &index, const QVariant &value
|
|||
case Roles::CipherRole: m_protocolConfig.insert(config_key::cipher, value.toString()); break;
|
||||
case Roles::TlsAuthRole: m_protocolConfig.insert(config_key::tls_auth, value.toBool()); break;
|
||||
case Roles::BlockDnsRole: m_protocolConfig.insert(config_key::block_outside_dns, value.toBool()); break;
|
||||
case Roles::AdditionalClientCommandsRole:
|
||||
m_protocolConfig.insert(config_key::additional_client_config, value.toString());
|
||||
break;
|
||||
case Roles::AdditionalServerCommandsRole:
|
||||
m_protocolConfig.insert(config_key::additional_server_config, value.toString());
|
||||
break;
|
||||
case Roles::AdditionalClientCommandsRole: m_protocolConfig.insert(config_key::additional_client_config, value.toString()); break;
|
||||
case Roles::AdditionalServerCommandsRole: m_protocolConfig.insert(config_key::additional_server_config, value.toString()); break;
|
||||
}
|
||||
|
||||
emit dataChanged(index, index, QList { role });
|
||||
|
|
@ -49,26 +43,21 @@ QVariant OpenVpnConfigModel::data(const QModelIndex &index, int role) const
|
|||
|
||||
switch (role) {
|
||||
case Roles::SubnetAddressRole:
|
||||
return m_protocolConfig.value(amnezia::config_key::subnet_address)
|
||||
.toString(amnezia::protocols::openvpn::defaultSubnetAddress);
|
||||
return m_protocolConfig.value(amnezia::config_key::subnet_address).toString(amnezia::protocols::openvpn::defaultSubnetAddress);
|
||||
case Roles::TransportProtoRole:
|
||||
return m_protocolConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto);
|
||||
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::openvpn::defaultPort);
|
||||
case Roles::AutoNegotiateEncryprionRole:
|
||||
return !m_protocolConfig.value(config_key::ncp_disable).toBool(protocols::openvpn::defaultNcpDisable);
|
||||
case Roles::HashRole: return m_protocolConfig.value(config_key::hash).toString(protocols::openvpn::defaultHash);
|
||||
case Roles::CipherRole:
|
||||
return m_protocolConfig.value(config_key::cipher).toString(protocols::openvpn::defaultCipher);
|
||||
case Roles::TlsAuthRole:
|
||||
return m_protocolConfig.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth);
|
||||
case Roles::CipherRole: return m_protocolConfig.value(config_key::cipher).toString(protocols::openvpn::defaultCipher);
|
||||
case Roles::TlsAuthRole: return m_protocolConfig.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth);
|
||||
case Roles::BlockDnsRole:
|
||||
return m_protocolConfig.value(config_key::block_outside_dns).toBool(protocols::openvpn::defaultBlockOutsideDns);
|
||||
case Roles::AdditionalClientCommandsRole:
|
||||
return m_protocolConfig.value(config_key::additional_client_config)
|
||||
.toString(protocols::openvpn::defaultAdditionalClientConfig);
|
||||
return m_protocolConfig.value(config_key::additional_client_config).toString(protocols::openvpn::defaultAdditionalClientConfig);
|
||||
case Roles::AdditionalServerCommandsRole:
|
||||
return m_protocolConfig.value(config_key::additional_server_config)
|
||||
.toString(protocols::openvpn::defaultAdditionalServerConfig);
|
||||
return m_protocolConfig.value(config_key::additional_server_config).toString(protocols::openvpn::defaultAdditionalServerConfig);
|
||||
case Roles::IsPortEditable: return m_container == DockerContainer::OpenVpn ? true : false;
|
||||
case Roles::IsTransportProtoEditable: return m_container == DockerContainer::OpenVpn ? true : false;
|
||||
case Roles::HasRemoveButton: return m_container == DockerContainer::OpenVpn ? true : false;
|
||||
|
|
@ -84,14 +73,13 @@ void OpenVpnConfigModel::updateModel(const QJsonObject &config)
|
|||
m_fullConfig = config;
|
||||
QJsonObject protocolConfig = config.value(config_key::openvpn).toObject();
|
||||
|
||||
m_protocolConfig.insert(config_key::subnet_address,
|
||||
protocolConfig.value(amnezia::config_key::subnet_address)
|
||||
.toString(amnezia::protocols::openvpn::defaultSubnetAddress));
|
||||
m_protocolConfig.insert(
|
||||
config_key::subnet_address,
|
||||
protocolConfig.value(amnezia::config_key::subnet_address).toString(amnezia::protocols::openvpn::defaultSubnetAddress));
|
||||
|
||||
QString transportProto;
|
||||
if (m_container == DockerContainer::OpenVpn) {
|
||||
transportProto =
|
||||
protocolConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto);
|
||||
transportProto = protocolConfig.value(config_key::transport_proto).toString(protocols::openvpn::defaultTransportProto);
|
||||
} else {
|
||||
transportProto = "tcp";
|
||||
}
|
||||
|
|
@ -100,23 +88,18 @@ void OpenVpnConfigModel::updateModel(const QJsonObject &config)
|
|||
|
||||
m_protocolConfig.insert(config_key::ncp_disable,
|
||||
protocolConfig.value(config_key::ncp_disable).toBool(protocols::openvpn::defaultNcpDisable));
|
||||
m_protocolConfig.insert(config_key::cipher,
|
||||
protocolConfig.value(config_key::cipher).toString(protocols::openvpn::defaultCipher));
|
||||
m_protocolConfig.insert(config_key::hash,
|
||||
protocolConfig.value(config_key::hash).toString(protocols::openvpn::defaultHash));
|
||||
m_protocolConfig.insert(config_key::cipher, protocolConfig.value(config_key::cipher).toString(protocols::openvpn::defaultCipher));
|
||||
m_protocolConfig.insert(config_key::hash, protocolConfig.value(config_key::hash).toString(protocols::openvpn::defaultHash));
|
||||
m_protocolConfig.insert(config_key::block_outside_dns,
|
||||
protocolConfig.value(config_key::block_outside_dns).toBool(protocols::openvpn::defaultBlockOutsideDns));
|
||||
m_protocolConfig.insert(config_key::port,
|
||||
protocolConfig.value(config_key::port).toString(protocols::openvpn::defaultPort));
|
||||
m_protocolConfig.insert(config_key::port, protocolConfig.value(config_key::port).toString(protocols::openvpn::defaultPort));
|
||||
m_protocolConfig.insert(config_key::tls_auth, protocolConfig.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth));
|
||||
m_protocolConfig.insert(
|
||||
config_key::tls_auth,
|
||||
protocolConfig.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth));
|
||||
m_protocolConfig.insert(config_key::additional_client_config,
|
||||
protocolConfig.value(config_key::additional_client_config)
|
||||
.toString(protocols::openvpn::defaultAdditionalClientConfig));
|
||||
m_protocolConfig.insert(config_key::additional_server_config,
|
||||
protocolConfig.value(config_key::additional_server_config)
|
||||
.toString(protocols::openvpn::defaultAdditionalServerConfig));
|
||||
config_key::additional_client_config,
|
||||
protocolConfig.value(config_key::additional_client_config).toString(protocols::openvpn::defaultAdditionalClientConfig));
|
||||
m_protocolConfig.insert(
|
||||
config_key::additional_server_config,
|
||||
protocolConfig.value(config_key::additional_server_config).toString(protocols::openvpn::defaultAdditionalServerConfig));
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,8 +35,7 @@ QVariant ShadowSocksConfigModel::data(const QModelIndex &index, int role) const
|
|||
|
||||
switch (role) {
|
||||
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort);
|
||||
case Roles::CipherRole:
|
||||
return m_protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher);
|
||||
case Roles::CipherRole: return m_protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher);
|
||||
case Roles::IsPortEditableRole: return m_container == DockerContainer::ShadowSocks ? true : false;
|
||||
case Roles::IsCipherEditableRole: return m_container == DockerContainer::ShadowSocks ? true : false;
|
||||
}
|
||||
|
|
@ -52,11 +51,11 @@ void ShadowSocksConfigModel::updateModel(const QJsonObject &config)
|
|||
m_fullConfig = config;
|
||||
QJsonObject protocolConfig = config.value(config_key::shadowsocks).toObject();
|
||||
|
||||
m_protocolConfig.insert(config_key::cipher,
|
||||
protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher));
|
||||
|
||||
m_protocolConfig.insert(config_key::port,
|
||||
protocolConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort));
|
||||
auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::ShadowSocks), Proto::ShadowSocks);
|
||||
m_protocolConfig.insert(config_key::transport_proto,
|
||||
protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
|
||||
m_protocolConfig.insert(config_key::cipher, protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher));
|
||||
m_protocolConfig.insert(config_key::port, protocolConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort));
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,9 @@ bool WireGuardConfigModel::setData(const QModelIndex &index, const QVariant &val
|
|||
}
|
||||
|
||||
switch (role) {
|
||||
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
|
||||
case Roles::MtuRole: m_protocolConfig.insert(config_key::mtu, value.toString()); break;
|
||||
case Roles::SubnetAddressRole: m_serverProtocolConfig.insert(config_key::subnet_address, value.toString()); break;
|
||||
case Roles::PortRole: m_serverProtocolConfig.insert(config_key::port, value.toString()); break;
|
||||
case Roles::ClientMtuRole: m_clientProtocolConfig.insert(config_key::mtu, value.toString()); break;
|
||||
}
|
||||
|
||||
emit dataChanged(index, index, QList { role });
|
||||
|
|
@ -36,8 +37,9 @@ QVariant WireGuardConfigModel::data(const QModelIndex &index, int role) const
|
|||
}
|
||||
|
||||
switch (role) {
|
||||
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString();
|
||||
case Roles::MtuRole: return m_protocolConfig.value(config_key::mtu).toString();
|
||||
case Roles::SubnetAddressRole: return m_serverProtocolConfig.value(config_key::subnet_address).toString();
|
||||
case Roles::PortRole: return m_serverProtocolConfig.value(config_key::port).toString();
|
||||
case Roles::ClientMtuRole: return m_clientProtocolConfig.value(config_key::mtu);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
|
|
@ -49,14 +51,19 @@ void WireGuardConfigModel::updateModel(const QJsonObject &config)
|
|||
m_container = ContainerProps::containerFromString(config.value(config_key::container).toString());
|
||||
|
||||
m_fullConfig = config;
|
||||
QJsonObject protocolConfig = config.value(config_key::wireguard).toObject();
|
||||
QJsonObject serverProtocolConfig = config.value(config_key::wireguard).toObject();
|
||||
|
||||
m_protocolConfig[config_key::last_config] = protocolConfig.value(config_key::last_config);
|
||||
m_protocolConfig[config_key::port] =
|
||||
protocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
|
||||
auto defaultTransportProto =
|
||||
ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::WireGuard), Proto::WireGuard);
|
||||
m_serverProtocolConfig.insert(config_key::transport_proto,
|
||||
serverProtocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
|
||||
m_serverProtocolConfig[config_key::last_config] = serverProtocolConfig.value(config_key::last_config);
|
||||
m_serverProtocolConfig[config_key::subnet_address] = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
|
||||
m_serverProtocolConfig[config_key::port] = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
|
||||
|
||||
m_protocolConfig[config_key::mtu] =
|
||||
protocolConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
|
||||
auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
|
||||
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
||||
m_clientProtocolConfig[config_key::mtu] = clientProtocolConfig[config_key::mtu].toString(protocols::wireguard::defaultMtu);
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
|
@ -64,41 +71,54 @@ void WireGuardConfigModel::updateModel(const QJsonObject &config)
|
|||
QJsonObject WireGuardConfigModel::getConfig()
|
||||
{
|
||||
const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject());
|
||||
const WgConfig newConfig(m_protocolConfig);
|
||||
const WgConfig newConfig(m_serverProtocolConfig);
|
||||
|
||||
if (!oldConfig.hasEqualServerSettings(newConfig)) {
|
||||
m_protocolConfig.remove(config_key::last_config);
|
||||
m_serverProtocolConfig.remove(config_key::last_config);
|
||||
} else {
|
||||
auto lastConfig = m_protocolConfig.value(config_key::last_config).toString();
|
||||
auto lastConfig = m_serverProtocolConfig.value(config_key::last_config).toString();
|
||||
QJsonObject jsonConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
||||
jsonConfig[config_key::mtu] = newConfig.mtu;
|
||||
jsonConfig[config_key::mtu] = m_clientProtocolConfig[config_key::mtu];
|
||||
|
||||
m_protocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
|
||||
m_serverProtocolConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
|
||||
}
|
||||
|
||||
m_fullConfig.insert(config_key::wireguard, m_protocolConfig);
|
||||
m_fullConfig.insert(config_key::wireguard, m_serverProtocolConfig);
|
||||
return m_fullConfig;
|
||||
}
|
||||
|
||||
bool WireGuardConfigModel::isServerSettingsEqual()
|
||||
{
|
||||
const WgConfig oldConfig(m_fullConfig.value(config_key::wireguard).toObject());
|
||||
const WgConfig newConfig(m_serverProtocolConfig);
|
||||
|
||||
return oldConfig.hasEqualServerSettings(newConfig);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> WireGuardConfigModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
|
||||
roles[SubnetAddressRole] = "subnetAddress";
|
||||
roles[PortRole] = "port";
|
||||
roles[MtuRole] = "mtu";
|
||||
roles[ClientMtuRole] = "clientMtu";
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
WgConfig::WgConfig(const QJsonObject &jsonConfig)
|
||||
WgConfig::WgConfig(const QJsonObject &serverProtocolConfig)
|
||||
{
|
||||
port = jsonConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
|
||||
mtu = jsonConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
|
||||
auto lastConfig = serverProtocolConfig.value(config_key::last_config).toString();
|
||||
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(lastConfig.toUtf8()).object();
|
||||
clientMtu = clientProtocolConfig[config_key::mtu].toString(protocols::wireguard::defaultMtu);
|
||||
|
||||
subnetAddress = serverProtocolConfig.value(config_key::subnet_address).toString(protocols::wireguard::defaultSubnetAddress);
|
||||
port = serverProtocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
|
||||
}
|
||||
|
||||
bool WgConfig::hasEqualServerSettings(const WgConfig &other) const
|
||||
{
|
||||
if (port != other.port) {
|
||||
if (subnetAddress != other.subnetAddress || port != other.port) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -106,7 +126,7 @@ bool WgConfig::hasEqualServerSettings(const WgConfig &other) const
|
|||
|
||||
bool WgConfig::hasEqualClientSettings(const WgConfig &other) const
|
||||
{
|
||||
if (mtu != other.mtu) {
|
||||
if (clientMtu != other.clientMtu) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@ struct WgConfig
|
|||
{
|
||||
WgConfig(const QJsonObject &jsonConfig);
|
||||
|
||||
QString subnetAddress;
|
||||
QString port;
|
||||
QString mtu;
|
||||
QString clientMtu;
|
||||
|
||||
bool hasEqualServerSettings(const WgConfig &other) const;
|
||||
bool hasEqualClientSettings(const WgConfig &other) const;
|
||||
|
|
@ -24,8 +25,9 @@ class WireGuardConfigModel : public QAbstractListModel
|
|||
|
||||
public:
|
||||
enum Roles {
|
||||
PortRole = Qt::UserRole + 1,
|
||||
MtuRole
|
||||
SubnetAddressRole = Qt::UserRole + 1,
|
||||
PortRole,
|
||||
ClientMtuRole
|
||||
};
|
||||
|
||||
explicit WireGuardConfigModel(QObject *parent = nullptr);
|
||||
|
|
@ -39,12 +41,15 @@ public slots:
|
|||
void updateModel(const QJsonObject &config);
|
||||
QJsonObject getConfig();
|
||||
|
||||
bool isServerSettingsEqual();
|
||||
|
||||
protected:
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
private:
|
||||
DockerContainer m_container;
|
||||
QJsonObject m_protocolConfig;
|
||||
QJsonObject m_serverProtocolConfig;
|
||||
QJsonObject m_clientProtocolConfig;
|
||||
QJsonObject m_fullConfig;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -47,8 +47,11 @@ void XrayConfigModel::updateModel(const QJsonObject &config)
|
|||
m_fullConfig = config;
|
||||
QJsonObject protocolConfig = config.value(config_key::xray).toObject();
|
||||
|
||||
m_protocolConfig.insert(config_key::site,
|
||||
protocolConfig.value(config_key::site).toString(protocols::xray::defaultSite));
|
||||
auto defaultTransportProto = ProtocolProps::transportProtoToString(ProtocolProps::defaultTransportProto(Proto::Xray), Proto::Xray);
|
||||
m_protocolConfig.insert(config_key::transport_proto,
|
||||
protocolConfig.value(config_key::transport_proto).toString(defaultTransportProto));
|
||||
m_protocolConfig.insert(config_key::port, protocolConfig.value(config_key::port).toString(protocols::xray::defaultPort));
|
||||
m_protocolConfig.insert(config_key::site, protocolConfig.value(config_key::site).toString(protocols::xray::defaultSite));
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,9 +16,11 @@ QHash<int, QByteArray> ProtocolsModel::roleNames() const
|
|||
QHash<int, QByteArray> roles;
|
||||
|
||||
roles[ProtocolNameRole] = "protocolName";
|
||||
roles[ProtocolPageRole] = "protocolPage";
|
||||
roles[ServerProtocolPageRole] = "serverProtocolPage";
|
||||
roles[ClientProtocolPageRole] = "clientProtocolPage";
|
||||
roles[ProtocolIndexRole] = "protocolIndex";
|
||||
roles[RawConfigRole] = "rawConfig";
|
||||
roles[IsClientProtocolExistsRole] = "isClientProtocolExists";
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
|
@ -34,8 +36,10 @@ QVariant ProtocolsModel::data(const QModelIndex &index, int role) const
|
|||
amnezia::Proto proto = ProtocolProps::protoFromString(m_content.keys().at(index.row()));
|
||||
return ProtocolProps::protocolHumanNames().value(proto);
|
||||
}
|
||||
case ProtocolPageRole:
|
||||
return static_cast<int>(protocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row()))));
|
||||
case ServerProtocolPageRole:
|
||||
return static_cast<int>(serverProtocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row()))));
|
||||
case ClientProtocolPageRole:
|
||||
return static_cast<int>(clientProtocolPage(ProtocolProps::protoFromString(m_content.keys().at(index.row()))));
|
||||
case ProtocolIndexRole: return ProtocolProps::protoFromString(m_content.keys().at(index.row()));
|
||||
case RawConfigRole: {
|
||||
auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject();
|
||||
|
|
@ -50,6 +54,15 @@ QVariant ProtocolsModel::data(const QModelIndex &index, int role) const
|
|||
}
|
||||
return rawConfig;
|
||||
}
|
||||
case IsClientProtocolExistsRole: {
|
||||
auto protocolConfig = m_content.value(ContainerProps::containerTypeToString(m_container)).toObject();
|
||||
auto lastConfigJsonDoc =
|
||||
QJsonDocument::fromJson(protocolConfig.value(config_key::last_config).toString().toUtf8());
|
||||
auto lastConfigJson = lastConfigJsonDoc.object();
|
||||
|
||||
auto configString = lastConfigJson.value(config_key::config).toString();
|
||||
return !configString.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
|
|
@ -70,7 +83,7 @@ QJsonObject ProtocolsModel::getConfig()
|
|||
return config;
|
||||
}
|
||||
|
||||
PageLoader::PageEnum ProtocolsModel::protocolPage(Proto protocol) const
|
||||
PageLoader::PageEnum ProtocolsModel::serverProtocolPage(Proto protocol) const
|
||||
{
|
||||
switch (protocol) {
|
||||
case Proto::OpenVpn: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
||||
|
|
@ -86,6 +99,16 @@ PageLoader::PageEnum ProtocolsModel::protocolPage(Proto protocol) const
|
|||
case Proto::TorWebSite: return PageLoader::PageEnum::PageServiceTorWebsiteSettings;
|
||||
case Proto::Dns: return PageLoader::PageEnum::PageServiceDnsSettings;
|
||||
case Proto::Sftp: return PageLoader::PageEnum::PageServiceSftpSettings;
|
||||
case Proto::Socks5Proxy: return PageLoader::PageEnum::PageServiceSocksProxySettings;
|
||||
default: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
||||
}
|
||||
}
|
||||
|
||||
PageLoader::PageEnum ProtocolsModel::clientProtocolPage(Proto protocol) const
|
||||
{
|
||||
switch (protocol) {
|
||||
case Proto::WireGuard: return PageLoader::PageEnum::PageProtocolWireGuardClientSettings;
|
||||
case Proto::Awg: return PageLoader::PageEnum::PageProtocolAwgClientSettings;
|
||||
default: return PageLoader::PageEnum::PageProtocolOpenVpnSettings;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,11 @@ class ProtocolsModel : public QAbstractListModel
|
|||
public:
|
||||
enum Roles {
|
||||
ProtocolNameRole = Qt::UserRole + 1,
|
||||
ProtocolPageRole,
|
||||
ServerProtocolPageRole,
|
||||
ClientProtocolPageRole,
|
||||
ProtocolIndexRole,
|
||||
RawConfigRole
|
||||
RawConfigRole,
|
||||
IsClientProtocolExistsRole
|
||||
};
|
||||
|
||||
ProtocolsModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
||||
|
|
@ -33,7 +35,8 @@ protected:
|
|||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
private:
|
||||
PageLoader::PageEnum protocolPage(Proto protocol) const;
|
||||
PageLoader::PageEnum serverProtocolPage(Proto protocol) const;
|
||||
PageLoader::PageEnum clientProtocolPage(Proto protocol) const;
|
||||
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,31 @@
|
|||
#include "servers_model.h"
|
||||
|
||||
#include "core/api/apiDefs.h"
|
||||
#include "core/controllers/serverController.h"
|
||||
#include "core/networkUtilities.h"
|
||||
|
||||
#ifdef Q_OS_IOS
|
||||
#include <AmneziaVPN-Swift.h>
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace configKey
|
||||
{
|
||||
constexpr char apiConfig[] = "api_config";
|
||||
constexpr char serviceInfo[] = "service_info";
|
||||
constexpr char availableCountries[] = "available_countries";
|
||||
constexpr char serverCountryCode[] = "server_country_code";
|
||||
constexpr char serverCountryName[] = "server_country_name";
|
||||
constexpr char userCountryCode[] = "user_country_code";
|
||||
constexpr char serviceType[] = "service_type";
|
||||
constexpr char serviceProtocol[] = "service_protocol";
|
||||
|
||||
constexpr char publicKeyInfo[] = "public_key";
|
||||
constexpr char expiresAt[] = "expires_at";
|
||||
}
|
||||
}
|
||||
|
||||
ServersModel::ServersModel(std::shared_ptr<Settings> settings, QObject *parent) : m_settings(settings), QAbstractListModel(parent)
|
||||
{
|
||||
m_isAmneziaDnsEnabled = m_settings->useAmneziaDns();
|
||||
|
|
@ -16,6 +39,9 @@ ServersModel::ServersModel(std::shared_ptr<Settings> settings, QObject *parent)
|
|||
emit ServersModel::defaultServerNameChanged();
|
||||
updateDefaultServerContainersModel();
|
||||
});
|
||||
|
||||
connect(this, &ServersModel::processedServerIndexChanged, this, &ServersModel::processedServerChanged);
|
||||
connect(this, &ServersModel::dataChanged, this, &ServersModel::processedServerChanged);
|
||||
}
|
||||
|
||||
int ServersModel::rowCount(const QModelIndex &parent) const
|
||||
|
|
@ -56,6 +82,12 @@ bool ServersModel::setData(const QModelIndex &index, const QVariant &value, int
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ServersModel::setData(const int index, const QVariant &value, int role)
|
||||
{
|
||||
QModelIndex modelIndex = this->index(index);
|
||||
return setData(modelIndex, value, role);
|
||||
}
|
||||
|
||||
QVariant ServersModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= static_cast<int>(m_servers.size())) {
|
||||
|
|
@ -63,6 +95,7 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const
|
|||
}
|
||||
|
||||
const QJsonObject server = m_servers.at(index.row()).toObject();
|
||||
const auto apiConfig = server.value(configKey::apiConfig).toObject();
|
||||
const auto configVersion = server.value(config_key::configVersion).toInt();
|
||||
switch (role) {
|
||||
case NameRole: {
|
||||
|
|
@ -98,8 +131,23 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const
|
|||
case HasInstalledContainers: {
|
||||
return serverHasInstalledContainers(index.row());
|
||||
}
|
||||
case IsServerFromApiRole: {
|
||||
return server.value(config_key::configVersion).toInt();
|
||||
case IsServerFromTelegramApiRole: {
|
||||
return server.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::Telegram;
|
||||
}
|
||||
case IsServerFromGatewayApiRole: {
|
||||
return server.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway;
|
||||
}
|
||||
case ApiConfigRole: {
|
||||
return apiConfig;
|
||||
}
|
||||
case IsCountrySelectionAvailableRole: {
|
||||
return !apiConfig.value(configKey::availableCountries).toArray().isEmpty();
|
||||
}
|
||||
case ApiAvailableCountriesRole: {
|
||||
return apiConfig.value(configKey::availableCountries).toArray();
|
||||
}
|
||||
case ApiServerCountryCodeRole: {
|
||||
return apiConfig.value(configKey::serverCountryCode).toString();
|
||||
}
|
||||
case HasAmneziaDns: {
|
||||
QString primaryDns = server.value(config_key::dns1).toString();
|
||||
|
|
@ -146,10 +194,13 @@ const QString ServersModel::getDefaultServerName()
|
|||
QString ServersModel::getServerDescription(const QJsonObject &server, const int index) const
|
||||
{
|
||||
const auto configVersion = server.value(config_key::configVersion).toInt();
|
||||
const auto apiConfig = server.value(configKey::apiConfig).toObject();
|
||||
|
||||
QString description;
|
||||
|
||||
if (configVersion) {
|
||||
if (configVersion && !apiConfig.value(configKey::serverCountryCode).toString().isEmpty()) {
|
||||
return apiConfig.value(configKey::serverCountryName).toString();
|
||||
} else if (configVersion) {
|
||||
return server.value(config_key::description).toString();
|
||||
} else if (data(index, HasWriteAccessRole).toBool()) {
|
||||
if (m_isAmneziaDnsEnabled && isAmneziaDnsContainerInstalled(index)) {
|
||||
|
|
@ -208,6 +259,12 @@ void ServersModel::setProcessedServerIndex(const int index)
|
|||
{
|
||||
m_processedServerIndex = index;
|
||||
updateContainersModel();
|
||||
if (data(index, IsServerFromGatewayApiRole).toBool()) {
|
||||
if (data(index, IsCountrySelectionAvailableRole).toBool()) {
|
||||
emit updateApiCountryModel();
|
||||
}
|
||||
emit updateApiServicesModel();
|
||||
}
|
||||
emit processedServerIndexChanged(m_processedServerIndex);
|
||||
}
|
||||
|
||||
|
|
@ -233,7 +290,8 @@ bool ServersModel::isDefaultServerCurrentlyProcessed()
|
|||
|
||||
bool ServersModel::isDefaultServerFromApi()
|
||||
{
|
||||
return qvariant_cast<bool>(data(m_defaultServerIndex, IsServerFromApiRole));
|
||||
return data(m_defaultServerIndex, IsServerFromTelegramApiRole).toBool()
|
||||
|| data(m_defaultServerIndex, IsServerFromGatewayApiRole).toBool();
|
||||
}
|
||||
|
||||
bool ServersModel::isProcessedServerHasWriteAccess()
|
||||
|
|
@ -315,7 +373,12 @@ QHash<int, QByteArray> ServersModel::roleNames() const
|
|||
roles[DefaultContainerRole] = "defaultContainer";
|
||||
roles[HasInstalledContainers] = "hasInstalledContainers";
|
||||
|
||||
roles[IsServerFromApiRole] = "isServerFromApi";
|
||||
roles[IsServerFromTelegramApiRole] = "isServerFromTelegramApi";
|
||||
roles[IsServerFromGatewayApiRole] = "isServerFromGatewayApi";
|
||||
roles[ApiConfigRole] = "apiConfig";
|
||||
roles[IsCountrySelectionAvailableRole] = "isCountrySelectionAvailable";
|
||||
roles[ApiAvailableCountriesRole] = "apiAvailableCountries";
|
||||
roles[ApiServerCountryCodeRole] = "apiServerCountryCode";
|
||||
return roles;
|
||||
}
|
||||
|
||||
|
|
@ -399,8 +462,7 @@ void ServersModel::addContainerConfig(const int containerIndex, const QJsonObjec
|
|||
|
||||
auto defaultContainer = server.value(config_key::defaultContainer).toString();
|
||||
if (ContainerProps::containerFromString(defaultContainer) == DockerContainer::None
|
||||
&& ContainerProps::containerService(container) != ServiceType::Other
|
||||
&& ContainerProps::isSupportedByCurrentPlatform(container)) {
|
||||
&& ContainerProps::containerService(container) != ServiceType::Other && ContainerProps::isSupportedByCurrentPlatform(container)) {
|
||||
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
||||
}
|
||||
|
||||
|
|
@ -548,6 +610,8 @@ QStringList ServersModel::getAllInstalledServicesName(const int serverIndex)
|
|||
servicesName.append("SFTP");
|
||||
} else if (container == DockerContainer::TorWebSite) {
|
||||
servicesName.append("TOR");
|
||||
} else if (container == DockerContainer::Socks5Proxy) {
|
||||
servicesName.append("SOCKS5");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -563,7 +627,7 @@ void ServersModel::toggleAmneziaDns(bool enabled)
|
|||
|
||||
bool ServersModel::isServerFromApiAlreadyExists(const quint16 crc)
|
||||
{
|
||||
for (const auto &server : qAsConst(m_servers)) {
|
||||
for (const auto &server : std::as_const(m_servers)) {
|
||||
if (static_cast<quint16>(server.toObject().value(config_key::crc).toInt()) == crc) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -571,6 +635,19 @@ bool ServersModel::isServerFromApiAlreadyExists(const quint16 crc)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ServersModel::isServerFromApiAlreadyExists(const QString &userCountryCode, const QString &serviceType, const QString &serviceProtocol)
|
||||
{
|
||||
for (const auto &server : std::as_const(m_servers)) {
|
||||
const auto apiConfig = server.toObject().value(configKey::apiConfig).toObject();
|
||||
if (apiConfig.value(configKey::userCountryCode).toString() == userCountryCode
|
||||
&& apiConfig.value(configKey::serviceType).toString() == serviceType
|
||||
&& apiConfig.value(configKey::serviceProtocol).toString() == serviceProtocol) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ServersModel::serverHasInstalledContainers(const int serverIndex) const
|
||||
{
|
||||
QJsonObject server = m_servers.at(serverIndex).toObject();
|
||||
|
|
@ -580,6 +657,9 @@ bool ServersModel::serverHasInstalledContainers(const int serverIndex) const
|
|||
if (ContainerProps::containerService(container) == ServiceType::Vpn) {
|
||||
return true;
|
||||
}
|
||||
if (container == DockerContainer::SSXray) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -608,19 +688,109 @@ QVariant ServersModel::getProcessedServerData(const QString roleString)
|
|||
return {};
|
||||
}
|
||||
|
||||
bool ServersModel::setProcessedServerData(const QString &roleString, const QVariant &value)
|
||||
{
|
||||
const auto roles = roleNames();
|
||||
for (auto it = roles.begin(); it != roles.end(); it++) {
|
||||
if (QString(it.value()) == roleString) {
|
||||
return setData(m_processedServerIndex, value, it.key());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ServersModel::isDefaultServerDefaultContainerHasSplitTunneling()
|
||||
{
|
||||
auto server = m_servers.at(m_defaultServerIndex).toObject();
|
||||
auto defaultContainer = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString());
|
||||
auto containerConfig = server.value(config_key::containers).toArray().at(defaultContainer).toObject();
|
||||
auto protocolConfig = containerConfig.value(ContainerProps::containerTypeToString(defaultContainer)).toObject();
|
||||
|
||||
if (defaultContainer == DockerContainer::Awg || defaultContainer == DockerContainer::WireGuard) {
|
||||
return !(protocolConfig.value(config_key::last_config).toString().contains("AllowedIPs = 0.0.0.0/0, ::/0"));
|
||||
} else if (defaultContainer == DockerContainer::Cloak || defaultContainer == DockerContainer::OpenVpn
|
||||
|| defaultContainer == DockerContainer::ShadowSocks) {
|
||||
return !(protocolConfig.value(config_key::last_config).toString().contains("redirect-gateway"));
|
||||
auto containers = server.value(config_key::containers).toArray();
|
||||
for (auto i = 0; i < containers.size(); i++) {
|
||||
auto container = containers.at(i).toObject();
|
||||
if (container.value(config_key::container).toString() != ContainerProps::containerToString(defaultContainer)) {
|
||||
continue;
|
||||
}
|
||||
if (defaultContainer == DockerContainer::Awg || defaultContainer == DockerContainer::WireGuard) {
|
||||
QJsonObject serverProtocolConfig = container.value(ContainerProps::containerTypeToString(defaultContainer)).toObject();
|
||||
QString clientProtocolConfigString = serverProtocolConfig.value(config_key::last_config).toString();
|
||||
QJsonObject clientProtocolConfig = QJsonDocument::fromJson(clientProtocolConfigString.toUtf8()).object();
|
||||
return (clientProtocolConfigString.contains("AllowedIPs") && !clientProtocolConfigString.contains("AllowedIPs = 0.0.0.0/0, ::/0"))
|
||||
|| (!clientProtocolConfig.value(config_key::allowed_ips).toArray().isEmpty()
|
||||
&& !clientProtocolConfig.value(config_key::allowed_ips).toArray().contains("0.0.0.0/0"));
|
||||
} else if (defaultContainer == DockerContainer::Cloak || defaultContainer == DockerContainer::OpenVpn
|
||||
|| defaultContainer == DockerContainer::ShadowSocks) {
|
||||
auto serverProtocolConfig = container.value(ContainerProps::containerTypeToString(DockerContainer::OpenVpn)).toObject();
|
||||
QString clientProtocolConfigString = serverProtocolConfig.value(config_key::last_config).toString();
|
||||
return !clientProtocolConfigString.isEmpty() && !clientProtocolConfigString.contains("redirect-gateway");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ServersModel::isServerFromApi(const int serverIndex)
|
||||
{
|
||||
return data(serverIndex, IsServerFromTelegramApiRole).toBool() || data(serverIndex, IsServerFromGatewayApiRole).toBool();
|
||||
}
|
||||
|
||||
bool ServersModel::isApiKeyExpired(const int serverIndex)
|
||||
{
|
||||
auto serverConfig = m_servers.at(serverIndex).toObject();
|
||||
auto apiConfig = serverConfig.value(configKey::apiConfig).toObject();
|
||||
|
||||
auto publicKeyInfo = apiConfig.value(configKey::publicKeyInfo).toObject();
|
||||
const QString expiresAt = publicKeyInfo.value(configKey::expiresAt).toString();
|
||||
if (expiresAt.isEmpty()) {
|
||||
publicKeyInfo.insert(configKey::expiresAt, QDateTime::currentDateTimeUtc().addDays(1).toString(Qt::ISODate));
|
||||
apiConfig.insert(configKey::publicKeyInfo, publicKeyInfo);
|
||||
serverConfig.insert(configKey::apiConfig, apiConfig);
|
||||
editServer(serverConfig, serverIndex);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
auto expiresAtDateTime = QDateTime::fromString(expiresAt, Qt::ISODate).toUTC();
|
||||
if (expiresAtDateTime < QDateTime::currentDateTimeUtc()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ServersModel::removeApiConfig(const int serverIndex)
|
||||
{
|
||||
auto serverConfig = getServerConfig(serverIndex);
|
||||
|
||||
#ifdef Q_OS_IOS
|
||||
QString vpncName = QString("%1 (%2) %3")
|
||||
.arg(serverConfig[config_key::description].toString())
|
||||
.arg(serverConfig[config_key::hostName].toString())
|
||||
.arg(serverConfig[config_key::vpnproto].toString());
|
||||
|
||||
AmneziaVPN::removeVPNC(vpncName.toStdString());
|
||||
#endif
|
||||
|
||||
serverConfig.remove(config_key::dns1);
|
||||
serverConfig.remove(config_key::dns2);
|
||||
serverConfig.remove(config_key::containers);
|
||||
serverConfig.remove(config_key::hostName);
|
||||
|
||||
auto apiConfig = serverConfig.value(configKey::apiConfig).toObject();
|
||||
apiConfig.remove(configKey::publicKeyInfo);
|
||||
serverConfig.insert(configKey::apiConfig, apiConfig);
|
||||
|
||||
serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None));
|
||||
|
||||
editServer(serverConfig, serverIndex);
|
||||
}
|
||||
|
||||
const QString ServersModel::getDefaultServerImagePathCollapsed()
|
||||
{
|
||||
const auto server = m_servers.at(m_defaultServerIndex).toObject();
|
||||
const auto apiConfig = server.value(configKey::apiConfig).toObject();
|
||||
const auto countryCode = apiConfig.value(configKey::serverCountryCode).toString();
|
||||
|
||||
if (countryCode.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
return QString("qrc:/countriesFlags/images/flagKit/%1.svg").arg(countryCode.toUpper());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
#include "settings.h"
|
||||
#include "core/controllers/serverController.h"
|
||||
#include "settings.h"
|
||||
|
||||
class ServersModel : public QAbstractListModel
|
||||
{
|
||||
|
|
@ -30,7 +30,13 @@ public:
|
|||
DefaultContainerRole,
|
||||
|
||||
HasInstalledContainers,
|
||||
IsServerFromApiRole,
|
||||
|
||||
IsServerFromTelegramApiRole,
|
||||
IsServerFromGatewayApiRole,
|
||||
ApiConfigRole,
|
||||
IsCountrySelectionAvailableRole,
|
||||
ApiAvailableCountriesRole,
|
||||
ApiServerCountryCodeRole,
|
||||
|
||||
HasAmneziaDns
|
||||
};
|
||||
|
|
@ -40,6 +46,7 @@ public:
|
|||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
bool setData(const int index, const QVariant &value, int role = Qt::EditRole);
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QVariant data(const int index, int role = Qt::DisplayRole) const;
|
||||
|
||||
|
|
@ -49,8 +56,10 @@ public:
|
|||
Q_PROPERTY(QString defaultServerName READ getDefaultServerName NOTIFY defaultServerNameChanged)
|
||||
Q_PROPERTY(QString defaultServerDefaultContainerName READ getDefaultServerDefaultContainerName NOTIFY defaultServerDefaultContainerChanged)
|
||||
Q_PROPERTY(QString defaultServerDescriptionCollapsed READ getDefaultServerDescriptionCollapsed NOTIFY defaultServerDefaultContainerChanged)
|
||||
Q_PROPERTY(QString defaultServerImagePathCollapsed READ getDefaultServerImagePathCollapsed NOTIFY defaultServerDefaultContainerChanged)
|
||||
Q_PROPERTY(QString defaultServerDescriptionExpanded READ getDefaultServerDescriptionExpanded NOTIFY defaultServerDefaultContainerChanged)
|
||||
Q_PROPERTY(bool isDefaultServerDefaultContainerHasSplitTunneling READ isDefaultServerDefaultContainerHasSplitTunneling NOTIFY defaultServerDefaultContainerChanged)
|
||||
Q_PROPERTY(bool isDefaultServerDefaultContainerHasSplitTunneling READ isDefaultServerDefaultContainerHasSplitTunneling NOTIFY
|
||||
defaultServerDefaultContainerChanged)
|
||||
Q_PROPERTY(bool isDefaultServerFromApi READ isDefaultServerFromApi NOTIFY defaultServerIndexChanged)
|
||||
|
||||
Q_PROPERTY(int processedIndex READ getProcessedServerIndex WRITE setProcessedServerIndex NOTIFY processedServerIndexChanged)
|
||||
|
|
@ -60,6 +69,7 @@ public slots:
|
|||
const int getDefaultServerIndex();
|
||||
const QString getDefaultServerName();
|
||||
const QString getDefaultServerDescriptionCollapsed();
|
||||
const QString getDefaultServerImagePathCollapsed();
|
||||
const QString getDefaultServerDescriptionExpanded();
|
||||
const QString getDefaultServerDefaultContainerName();
|
||||
bool isDefaultServerCurrentlyProcessed();
|
||||
|
|
@ -101,18 +111,27 @@ public slots:
|
|||
QPair<QString, QString> getDnsPair(const int serverIndex);
|
||||
|
||||
bool isServerFromApiAlreadyExists(const quint16 crc);
|
||||
bool isServerFromApiAlreadyExists(const QString &userCountryCode, const QString &serviceType, const QString &serviceProtocol);
|
||||
|
||||
QVariant getDefaultServerData(const QString roleString);
|
||||
|
||||
QVariant getProcessedServerData(const QString roleString);
|
||||
bool setProcessedServerData(const QString &roleString, const QVariant &value);
|
||||
|
||||
bool isDefaultServerDefaultContainerHasSplitTunneling();
|
||||
|
||||
bool isServerFromApi(const int serverIndex);
|
||||
bool isApiKeyExpired(const int serverIndex);
|
||||
void removeApiConfig(const int serverIndex);
|
||||
|
||||
protected:
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
signals:
|
||||
void processedServerIndexChanged(const int index);
|
||||
// emitted when the processed server index or processed server data is changed
|
||||
void processedServerChanged();
|
||||
|
||||
void defaultServerIndexChanged(const int index);
|
||||
void defaultServerNameChanged();
|
||||
void defaultServerDescriptionChanged();
|
||||
|
|
@ -121,6 +140,9 @@ signals:
|
|||
void defaultServerContainersUpdated(const QJsonArray &containers);
|
||||
void defaultServerDefaultContainerChanged(const int containerIndex);
|
||||
|
||||
void updateApiCountryModel();
|
||||
void updateApiServicesModel();
|
||||
|
||||
private:
|
||||
ServerCredentials serverCredentials(int index) const;
|
||||
|
||||
|
|
|
|||
80
client/ui/models/services/socks5ProxyConfigModel.cpp
Normal file
80
client/ui/models/services/socks5ProxyConfigModel.cpp
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
#include "socks5ProxyConfigModel.h"
|
||||
|
||||
#include "protocols/protocols_defs.h"
|
||||
|
||||
Socks5ProxyConfigModel::Socks5ProxyConfigModel(QObject *parent) : QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
int Socks5ProxyConfigModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool Socks5ProxyConfigModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= ContainerProps::allContainers().size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (role) {
|
||||
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
|
||||
case Roles::UserNameRole: m_protocolConfig.insert(config_key::userName, value.toString()); break;
|
||||
case Roles::PasswordRole: m_protocolConfig.insert(config_key::password, value.toString()); break;
|
||||
}
|
||||
|
||||
emit dataChanged(index, index, QList { role });
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant Socks5ProxyConfigModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() < 0 || index.row() >= rowCount()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (role) {
|
||||
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString();
|
||||
case Roles::UserNameRole:
|
||||
return m_protocolConfig.value(config_key::userName).toString();
|
||||
case Roles::PasswordRole: return m_protocolConfig.value(config_key::password).toString();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void Socks5ProxyConfigModel::updateModel(const QJsonObject &config)
|
||||
{
|
||||
beginResetModel();
|
||||
m_container = ContainerProps::containerFromString(config.value(config_key::container).toString());
|
||||
|
||||
m_fullConfig = config;
|
||||
QJsonObject protocolConfig = config.value(config_key::socks5proxy).toObject();
|
||||
|
||||
m_protocolConfig.insert(config_key::userName,
|
||||
protocolConfig.value(config_key::userName).toString());
|
||||
|
||||
m_protocolConfig.insert(config_key::password, protocolConfig.value(config_key::password).toString());
|
||||
|
||||
m_protocolConfig.insert(config_key::port, protocolConfig.value(config_key::port).toString());
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QJsonObject Socks5ProxyConfigModel::getConfig()
|
||||
{
|
||||
m_fullConfig.insert(config_key::socks5proxy, m_protocolConfig);
|
||||
return m_fullConfig;
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> Socks5ProxyConfigModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
|
||||
roles[PortRole] = "port";
|
||||
roles[UserNameRole] = "username";
|
||||
roles[PasswordRole] = "password";
|
||||
|
||||
return roles;
|
||||
}
|
||||
40
client/ui/models/services/socks5ProxyConfigModel.h
Normal file
40
client/ui/models/services/socks5ProxyConfigModel.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef SOCKS5PROXYCONFIGMODEL_H
|
||||
#define SOCKS5PROXYCONFIGMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "containers/containers_defs.h"
|
||||
|
||||
class Socks5ProxyConfigModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
PortRole = Qt::UserRole + 1,
|
||||
UserNameRole,
|
||||
PasswordRole
|
||||
};
|
||||
|
||||
explicit Socks5ProxyConfigModel(QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
public slots:
|
||||
void updateModel(const QJsonObject &config);
|
||||
QJsonObject getConfig();
|
||||
|
||||
protected:
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
private:
|
||||
DockerContainer m_container;
|
||||
QJsonObject m_protocolConfig;
|
||||
QJsonObject m_fullConfig;
|
||||
};
|
||||
|
||||
#endif // SOCKS5PROXYCONFIGMODEL_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue