mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-17 08:16:06 +03:00
* refactor: remove serverConfig struct * refactor: add warnings for api v1 configs * refactor: moved the server type definition to a separate namespace * refactor: simplified gateway stacks * fix: fixed server description * fix: fixed postAsync reply usage * fix: fixed validateConfig call * fix: fixed server name in notifications * fix: fixed initPrepareConfigHandler for lagacy configs
373 lines
11 KiB
C++
373 lines
11 KiB
C++
#include "secureServersRepository.h"
|
|
|
|
#include <QJsonArray>
|
|
#include <QJsonDocument>
|
|
#include <QJsonValue>
|
|
#include <QUuid>
|
|
|
|
#include "core/utils/serverConfigUtils.h"
|
|
#include "core/utils/constants/apiKeys.h"
|
|
#include "core/utils/constants/configKeys.h"
|
|
|
|
using namespace amnezia;
|
|
|
|
namespace {
|
|
|
|
QString readStorageServerId(const QJsonObject &json)
|
|
{
|
|
return json.value(QString(configKey::storageServerId)).toString().trimmed();
|
|
}
|
|
|
|
QJsonObject withoutStorageServerId(const QJsonObject &json)
|
|
{
|
|
QJsonObject o = json;
|
|
o.remove(QString(configKey::storageServerId));
|
|
return o;
|
|
}
|
|
|
|
QJsonObject embedStorageServerId(const QString &serverId, const QJsonObject &payloadSansId)
|
|
{
|
|
QJsonObject o = payloadSansId;
|
|
o.insert(QString(configKey::storageServerId), serverId);
|
|
return o;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
SecureServersRepository::SecureServersRepository(SecureQSettings *settings, QObject *parent)
|
|
: QObject(parent), m_settings(settings)
|
|
{
|
|
loadFromStorage();
|
|
persistDefaultServerFields();
|
|
}
|
|
|
|
QVariant SecureServersRepository::value(const QString &key, const QVariant &defaultValue) const
|
|
{
|
|
return m_settings->value(key, defaultValue);
|
|
}
|
|
|
|
void SecureServersRepository::setValue(const QString &key, const QVariant &value)
|
|
{
|
|
m_settings->setValue(key, value);
|
|
}
|
|
|
|
void SecureServersRepository::clearServerStateMaps()
|
|
{
|
|
m_serverJsonById.clear();
|
|
m_orderedServerIds.clear();
|
|
}
|
|
|
|
QString SecureServersRepository::normalizedOrGeneratedServerId(const QString &candidateId) const
|
|
{
|
|
const QString trimmed = candidateId.trimmed();
|
|
if (!trimmed.isEmpty() && !m_serverJsonById.contains(trimmed)) {
|
|
return trimmed;
|
|
}
|
|
return QUuid::createUuid().toString(QUuid::WithoutBraces);
|
|
}
|
|
|
|
void SecureServersRepository::updateDefaultServerFromStorage()
|
|
{
|
|
const QString storedDefaultId = value(QStringLiteral("Servers/defaultServerId"), QString()).toString();
|
|
if (!storedDefaultId.isEmpty() && m_serverJsonById.contains(storedDefaultId)) {
|
|
m_defaultServerId = storedDefaultId;
|
|
return;
|
|
}
|
|
|
|
const int storedDefaultIndex = value("Servers/defaultServerIndex", 0).toInt();
|
|
if (storedDefaultIndex >= 0 && storedDefaultIndex < m_orderedServerIds.size()) {
|
|
m_defaultServerId = m_orderedServerIds.at(storedDefaultIndex);
|
|
return;
|
|
}
|
|
|
|
if (!m_orderedServerIds.isEmpty()) {
|
|
m_defaultServerId = m_orderedServerIds.first();
|
|
return;
|
|
}
|
|
|
|
m_defaultServerId.clear();
|
|
}
|
|
|
|
void SecureServersRepository::persistDefaultServerFields()
|
|
{
|
|
if (m_orderedServerIds.isEmpty()) {
|
|
m_defaultServerId.clear();
|
|
} else if (!m_orderedServerIds.contains(m_defaultServerId)) {
|
|
m_defaultServerId = m_orderedServerIds.first();
|
|
}
|
|
|
|
setValue("Servers/defaultServerId", m_defaultServerId);
|
|
}
|
|
|
|
void SecureServersRepository::loadFromStorage()
|
|
{
|
|
clearServerStateMaps();
|
|
|
|
const QJsonArray serversArray =
|
|
QJsonDocument::fromJson(value(QStringLiteral("Servers/serversList"), QByteArray()).toByteArray())
|
|
.array();
|
|
|
|
for (int i = 0; i < serversArray.size(); ++i) {
|
|
const QJsonObject json = serversArray.at(i).toObject();
|
|
const QString candidateId = readStorageServerId(json);
|
|
const QString serverId = normalizedOrGeneratedServerId(candidateId);
|
|
const QJsonObject strippedJson = withoutStorageServerId(json);
|
|
const serverConfigUtils::ConfigType kind = serverConfigUtils::configTypeFromJson(strippedJson);
|
|
|
|
if (m_serverJsonById.contains(serverId) || kind == serverConfigUtils::ConfigType::Invalid) {
|
|
continue;
|
|
}
|
|
m_serverJsonById.insert(serverId, embedStorageServerId(serverId, strippedJson));
|
|
m_orderedServerIds.append(serverId);
|
|
}
|
|
|
|
updateDefaultServerFromStorage();
|
|
}
|
|
|
|
void SecureServersRepository::syncToStorage()
|
|
{
|
|
QJsonArray serversArray;
|
|
|
|
for (const QString &serverId : m_orderedServerIds) {
|
|
if (!m_serverJsonById.contains(serverId)) {
|
|
continue;
|
|
}
|
|
serversArray.append(m_serverJsonById.value(serverId));
|
|
}
|
|
|
|
setValue("Servers/serversList", QJsonDocument(serversArray).toJson());
|
|
persistDefaultServerFields();
|
|
}
|
|
|
|
void SecureServersRepository::invalidateCache()
|
|
{
|
|
loadFromStorage();
|
|
}
|
|
|
|
void SecureServersRepository::clearServers()
|
|
{
|
|
clearServerStateMaps();
|
|
|
|
m_defaultServerId.clear();
|
|
|
|
syncToStorage();
|
|
}
|
|
|
|
QString SecureServersRepository::addServer(const QString &serverId, const QJsonObject &serverJson, serverConfigUtils::ConfigType kind)
|
|
{
|
|
const QString id = normalizedOrGeneratedServerId(serverId);
|
|
if (m_serverJsonById.contains(id) || kind == serverConfigUtils::ConfigType::Invalid) {
|
|
return id;
|
|
}
|
|
const QJsonObject strippedJson = withoutStorageServerId(serverJson);
|
|
if (serverConfigUtils::configTypeFromJson(strippedJson) != kind) {
|
|
return id;
|
|
}
|
|
m_serverJsonById.insert(id, embedStorageServerId(id, strippedJson));
|
|
|
|
m_orderedServerIds.append(id);
|
|
|
|
if (m_defaultServerId.isEmpty()) {
|
|
m_defaultServerId = id;
|
|
}
|
|
|
|
syncToStorage();
|
|
emit serverAdded(id);
|
|
return id;
|
|
}
|
|
|
|
void SecureServersRepository::editServer(const QString &serverId, const QJsonObject &serverJson, serverConfigUtils::ConfigType kind)
|
|
{
|
|
if (indexOfServerId(serverId) < 0 || kind == serverConfigUtils::ConfigType::Invalid) {
|
|
return;
|
|
}
|
|
if (!m_serverJsonById.contains(serverId)) {
|
|
return;
|
|
}
|
|
|
|
const QJsonObject oldJson = m_serverJsonById.value(serverId);
|
|
const serverConfigUtils::ConfigType oldKind = serverConfigUtils::configTypeFromJson(withoutStorageServerId(oldJson));
|
|
|
|
m_serverJsonById.remove(serverId);
|
|
|
|
const QJsonObject strippedNew = withoutStorageServerId(serverJson);
|
|
if (serverConfigUtils::configTypeFromJson(strippedNew) != kind) {
|
|
const QJsonObject strippedOld = withoutStorageServerId(oldJson);
|
|
if (oldKind != serverConfigUtils::ConfigType::Invalid && serverConfigUtils::configTypeFromJson(strippedOld) == oldKind) {
|
|
m_serverJsonById.insert(serverId, embedStorageServerId(serverId, strippedOld));
|
|
}
|
|
return;
|
|
}
|
|
m_serverJsonById.insert(serverId, embedStorageServerId(serverId, strippedNew));
|
|
|
|
syncToStorage();
|
|
emit serverEdited(serverId);
|
|
}
|
|
|
|
void SecureServersRepository::removeServer(const QString &serverId)
|
|
{
|
|
const int removedIndex = indexOfServerId(serverId);
|
|
if (removedIndex < 0) {
|
|
return;
|
|
}
|
|
if (!m_serverJsonById.contains(serverId)) {
|
|
return;
|
|
}
|
|
|
|
const QString previousDefaultId = m_defaultServerId;
|
|
const int previousDefaultIndex = defaultServerIndex();
|
|
|
|
m_serverJsonById.remove(serverId);
|
|
m_orderedServerIds.removeAt(removedIndex);
|
|
|
|
if (m_orderedServerIds.isEmpty()) {
|
|
m_defaultServerId.clear();
|
|
} else if (m_defaultServerId == serverId) {
|
|
const int fallbackIndex = qMin(removedIndex, m_orderedServerIds.size() - 1);
|
|
m_defaultServerId = m_orderedServerIds.at(fallbackIndex);
|
|
} else if (!m_orderedServerIds.contains(m_defaultServerId)) {
|
|
m_defaultServerId = m_orderedServerIds.first();
|
|
}
|
|
|
|
const int newDefaultIndex = defaultServerIndex();
|
|
if (previousDefaultId != m_defaultServerId || previousDefaultIndex != newDefaultIndex) {
|
|
emit defaultServerChanged(m_defaultServerId);
|
|
}
|
|
|
|
syncToStorage();
|
|
emit serverRemoved(serverId, removedIndex);
|
|
}
|
|
|
|
serverConfigUtils::ConfigType SecureServersRepository::serverKind(const QString &serverId) const
|
|
{
|
|
const auto it = m_serverJsonById.constFind(serverId);
|
|
if (it == m_serverJsonById.constEnd()) {
|
|
return serverConfigUtils::ConfigType::Invalid;
|
|
}
|
|
return serverConfigUtils::configTypeFromJson(withoutStorageServerId(it.value()));
|
|
}
|
|
|
|
std::optional<SelfHostedAdminServerConfig> SecureServersRepository::selfHostedAdminConfig(const QString &serverId) const
|
|
{
|
|
const auto it = m_serverJsonById.constFind(serverId);
|
|
if (it == m_serverJsonById.constEnd()) {
|
|
return std::nullopt;
|
|
}
|
|
const QJsonObject strippedJson = withoutStorageServerId(it.value());
|
|
if (serverConfigUtils::configTypeFromJson(strippedJson) != serverConfigUtils::ConfigType::SelfHostedAdmin) {
|
|
return std::nullopt;
|
|
}
|
|
return SelfHostedAdminServerConfig::fromJson(strippedJson);
|
|
}
|
|
|
|
std::optional<SelfHostedUserServerConfig> SecureServersRepository::selfHostedUserConfig(const QString &serverId) const
|
|
{
|
|
const auto it = m_serverJsonById.constFind(serverId);
|
|
if (it == m_serverJsonById.constEnd()) {
|
|
return std::nullopt;
|
|
}
|
|
const QJsonObject strippedJson = withoutStorageServerId(it.value());
|
|
if (serverConfigUtils::configTypeFromJson(strippedJson) != serverConfigUtils::ConfigType::SelfHostedUser) {
|
|
return std::nullopt;
|
|
}
|
|
return SelfHostedUserServerConfig::fromJson(strippedJson);
|
|
}
|
|
|
|
std::optional<NativeServerConfig> SecureServersRepository::nativeConfig(const QString &serverId) const
|
|
{
|
|
const auto it = m_serverJsonById.constFind(serverId);
|
|
if (it == m_serverJsonById.constEnd()) {
|
|
return std::nullopt;
|
|
}
|
|
const QJsonObject strippedJson = withoutStorageServerId(it.value());
|
|
if (serverConfigUtils::configTypeFromJson(strippedJson) != serverConfigUtils::ConfigType::Native) {
|
|
return std::nullopt;
|
|
}
|
|
return NativeServerConfig::fromJson(strippedJson);
|
|
}
|
|
|
|
std::optional<ApiV2ServerConfig> SecureServersRepository::apiV2Config(const QString &serverId) const
|
|
{
|
|
const auto it = m_serverJsonById.constFind(serverId);
|
|
if (it == m_serverJsonById.constEnd()) {
|
|
return std::nullopt;
|
|
}
|
|
const QJsonObject strippedJson = withoutStorageServerId(it.value());
|
|
if (!serverConfigUtils::isApiV2Subscription(serverConfigUtils::configTypeFromJson(strippedJson))) {
|
|
return std::nullopt;
|
|
}
|
|
return ApiV2ServerConfig::fromJson(strippedJson);
|
|
}
|
|
|
|
std::optional<LegacyApiServerConfig> SecureServersRepository::legacyApiConfig(const QString &serverId) const
|
|
{
|
|
const auto it = m_serverJsonById.constFind(serverId);
|
|
if (it == m_serverJsonById.constEnd()) {
|
|
return std::nullopt;
|
|
}
|
|
const QJsonObject strippedJson = withoutStorageServerId(it.value());
|
|
if (!serverConfigUtils::isLegacyApiSubscription(serverConfigUtils::configTypeFromJson(strippedJson))) {
|
|
return std::nullopt;
|
|
}
|
|
return LegacyApiServerConfig::fromJson(strippedJson);
|
|
}
|
|
|
|
int SecureServersRepository::serversCount() const
|
|
{
|
|
return m_orderedServerIds.size();
|
|
}
|
|
|
|
QString SecureServersRepository::serverIdAt(int index) const
|
|
{
|
|
if (index < 0 || index >= m_orderedServerIds.size()) {
|
|
return QString();
|
|
}
|
|
return m_orderedServerIds.at(index);
|
|
}
|
|
|
|
QVector<QString> SecureServersRepository::orderedServerIds() const
|
|
{
|
|
return m_orderedServerIds;
|
|
}
|
|
|
|
int SecureServersRepository::indexOfServerId(const QString &serverId) const
|
|
{
|
|
return m_orderedServerIds.indexOf(serverId);
|
|
}
|
|
|
|
int SecureServersRepository::defaultServerIndex() const
|
|
{
|
|
if (m_orderedServerIds.isEmpty()) {
|
|
return 0;
|
|
}
|
|
const int idx = m_orderedServerIds.indexOf(m_defaultServerId);
|
|
return idx >= 0 ? idx : 0;
|
|
}
|
|
|
|
QString SecureServersRepository::defaultServerId() const
|
|
{
|
|
return m_defaultServerId;
|
|
}
|
|
|
|
void SecureServersRepository::setDefaultServer(const QString &serverId)
|
|
{
|
|
if (m_orderedServerIds.isEmpty()) {
|
|
return;
|
|
}
|
|
if (!m_serverJsonById.contains(serverId)) {
|
|
return;
|
|
}
|
|
|
|
if (indexOfServerId(serverId) < 0) {
|
|
return;
|
|
}
|
|
|
|
if (m_defaultServerId == serverId) {
|
|
return;
|
|
}
|
|
|
|
m_defaultServerId = serverId;
|
|
persistDefaultServerFields();
|
|
emit defaultServerChanged(m_defaultServerId);
|
|
}
|