Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
15d7518
Check if server has valid subcription.
camilasan Jun 3, 2024
e0d7377
Add general config setting for server hasValidSubscription.
camilasan Jun 3, 2024
7fa0378
Add user specific setting for server hasValidScriptionValue.
camilasan Jun 3, 2024
a4c114e
Update server hasValidSubscription if capabilities change for account.
camilasan Jun 3, 2024
ee03282
List enterprise update channel when available.
camilasan Jun 3, 2024
e4b70c4
Extend Capabilities tests.
camilasan Jun 3, 2024
e8b8236
Do not show enterprise channel for branded clients.
camilasan Jun 3, 2024
aa239cd
Add enterprise explanation to message shown when user changes update …
camilasan Jun 3, 2024
4de91cb
NextcloudDev is not a branded client.
camilasan Jun 3, 2024
0274cd9
Only list enterprise for customers not running branded clients.
camilasan Jun 3, 2024
4884fbe
Add desktopEnterpriseChannel to the capabilities check.
camilasan Jul 3, 2024
615805d
Save desktopEnterpriseChannel value in the config file.
camilasan Jul 3, 2024
0663282
Update desktopEnterpriseChannel value when capabilities change.
camilasan Jul 3, 2024
e51324d
Fix the logic to determine update channels available, default value a…
camilasan Jul 3, 2024
52e15ff
Separate the list of valid update channels for enterprise and non-ent…
camilasan Jul 3, 2024
dd5e18e
If the client is branded the default update channel is stable.
camilasan Jul 3, 2024
ee3f2dd
Extend capabilities test to include desktopEnterpriseChannel check.
camilasan Jul 3, 2024
7d27c53
Remove resolved TO DO comment.
camilasan Jul 4, 2024
cdd940f
Remove const from POD in method declaration.
camilasan Jul 4, 2024
bc05dc8
Use NEXTCLOUD_DEV to check if client is branded instead of checking f…
camilasan Jul 4, 2024
9bd4ef1
Translate enterprise channel explanation string.
camilasan Jul 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/gui/accountmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ constexpr auto legacyCfgFileNameC = "owncloud.cfg";
// The maximum versions that this client can read
constexpr auto maxAccountsVersion = 2;
constexpr auto maxAccountVersion = 1;

constexpr auto serverHasValidSubscriptionC = "serverHasValidSubscription";
}


Expand Down Expand Up @@ -321,6 +323,8 @@ void AccountManager::saveAccountHelper(Account *acc, QSettings &settings, bool s
settings.setValue(QLatin1String(serverVersionC), acc->_serverVersion);
settings.setValue(QLatin1String(serverColorC), acc->_serverColor);
settings.setValue(QLatin1String(serverTextColorC), acc->_serverTextColor);
settings.setValue(QLatin1String(serverHasValidSubscriptionC), acc->capabilities().serverHasValidSubscription());

if (!acc->_skipE2eeMetadataChecksumValidation) {
settings.remove(QLatin1String(skipE2eeMetadataChecksumValidationC));
} else {
Expand Down
20 changes: 16 additions & 4 deletions src/gui/generalsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ void GeneralSettings::loadMiscSettings()
_ui->monoIconsCheckBox->setChecked(cfgFile.monoIcons());

#if defined(BUILD_UPDATER)
auto validUpdateChannels = cfgFile.validUpdateChannels();
const auto validUpdateChannels = cfgFile.validUpdateChannels();
_ui->updateChannel->addItems(validUpdateChannels);
const auto currentUpdateChannelIndex = validUpdateChannels.indexOf(cfgFile.currentUpdateChannel());
_ui->updateChannel->setCurrentIndex(currentUpdateChannelIndex != -1? currentUpdateChannelIndex : 0);
Expand Down Expand Up @@ -359,6 +359,10 @@ void GeneralSettings::slotUpdateChannelChanged()
return tr("daily");
}

if (channel == QStringLiteral("enterprise")) {
return tr("enterprise");
}

return QString{};
};

Expand All @@ -370,24 +374,32 @@ void GeneralSettings::slotUpdateChannelChanged()
case 2:
return QStringLiteral("daily");
break;
case 3:
return QStringLiteral("enterprise");
break;
default:
return QStringLiteral("stable");
}
};

ConfigFile configFile;
const auto channel = updateChannelFromLocalized(_ui->updateChannel->currentIndex());
if (channel == ConfigFile().currentUpdateChannel()) {
if (channel == configFile.currentUpdateChannel()) {
return;
}

const auto enterprise = configFile.validUpdateChannels().contains("enterprise") ? tr("- enterprise: contains stable versions for customers.\n",
"description of enterprise update channel for enterprise customers")
: "";
auto msgBox = new QMessageBox(
QMessageBox::Warning,
tr("Changing update channel?"),
tr("The channel determines which upgrades will be offered to install:\n"
"- stable: contains tested versions considered reliable\n"
"- beta: contains versions with new features that may not be tested thoroughly\n"
"- daily: contains versions created daily only for testing and development\n\n"
"Downgrading versions is not possible immediately: changing from beta to stable means waiting for the new stable version."),
"- daily: contains versions created daily only for testing and development\n"
"%1\n"
"Downgrading versions is not possible immediately: changing from beta to stable means waiting for the new stable version.").arg(enterprise),
QMessageBox::NoButton,
this);
const auto acceptButton = msgBox->addButton(tr("Change update channel"), QMessageBox::AcceptRole);
Expand Down
21 changes: 21 additions & 0 deletions src/libsync/account.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,8 @@ void Account::setCapabilities(const QVariantMap &caps)
_capabilities = Capabilities(caps);

updateServerColors();
updateServerSubcription();
updateDesktopEnterpriseChannel();

emit capabilitiesChanged();

Expand Down Expand Up @@ -1068,4 +1070,23 @@ void Account::setAskUserForMnemonic(const bool ask)
emit askUserForMnemonicChanged();
}

void Account::updateServerSubcription()
{
ConfigFile currentConfig;
if (const auto serverHasValidSubscription = _capabilities.serverHasValidSubscription();
serverHasValidSubscription != currentConfig.serverHasValidSubscription()) {
currentConfig.setServerHasValidSubscription(serverHasValidSubscription);
}
}

void Account::updateDesktopEnterpriseChannel()
{
ConfigFile currentConfig;
if (const auto desktopEnterpriseChannel = _capabilities.desktopEnterpriseChannel();
desktopEnterpriseChannel != currentConfig.desktopEnterpriseChannel()) {
currentConfig.setDesktopEnterpriseChannel(desktopEnterpriseChannel);
}
}


} // namespace OCC
3 changes: 3 additions & 0 deletions src/libsync/account.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,9 @@ class OWNCLOUDSYNC_EXPORT Account : public QObject

[[nodiscard]] bool askUserForMnemonic() const;

void updateServerSubcription();
void updateDesktopEnterpriseChannel();

public slots:
/// Used when forgetting credentials
void clearQNAMCache();
Expand Down
11 changes: 11 additions & 0 deletions src/libsync/capabilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*/

#include "capabilities.h"
#include "configfile.h"

#include <QVariantMap>
#include <QLoggingCategory>
Expand Down Expand Up @@ -388,6 +389,16 @@ bool Capabilities::groupFoldersAvailable() const
return _capabilities[QStringLiteral("groupfolders")].toMap().value(QStringLiteral("hasGroupFolders"), false).toBool();
}

bool Capabilities::serverHasValidSubscription() const
{
return _capabilities[QStringLiteral("support")].toMap().value(QStringLiteral("hasValidSubscription"), false).toBool();
}

QString Capabilities::desktopEnterpriseChannel() const
{
return _capabilities[QStringLiteral("support")].toMap().value(QStringLiteral("desktopEnterpriseChannel"), ConfigFile().defaultUpdateChannel()).toString();
}

QStringList Capabilities::blacklistedFiles() const
{
return _capabilities["files"].toMap()["blacklisted_files"].toStringList();
Expand Down
3 changes: 3 additions & 0 deletions src/libsync/capabilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ class OWNCLOUDSYNC_EXPORT Capabilities

[[nodiscard]] bool groupFoldersAvailable() const;

[[nodiscard]] bool serverHasValidSubscription() const;
[[nodiscard]] QString desktopEnterpriseChannel() const;

// Direct Editing
void addDirectEditor(DirectEditor* directEditor);
DirectEditor* getDirectEditorForMimetype(const QMimeType &mimeType);
Expand Down
60 changes: 55 additions & 5 deletions src/libsync/configfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,13 @@ static constexpr char forceLoginV2C[] = "forceLoginV2";
static constexpr char certPath[] = "http_certificatePath";
static constexpr char certPasswd[] = "http_certificatePasswd";

static const QStringList validUpdateChannelsList { QStringLiteral("stable"), QStringLiteral("beta"), QStringLiteral("daily") };
static constexpr char defaultUpdateChannelName[] = "stable";
static constexpr char serverHasValidSubscriptionC[] = "serverHasValidSubscription";
static constexpr char desktopEnterpriseChannelName[] = "desktopEnterpriseChannel";

static const QStringList defaultUpdateChannelsList { QStringLiteral("stable"), QStringLiteral("beta"), QStringLiteral("daily") };
static const QString defaultUpdateChannelName = "stable";
static const QStringList enterpriseUpdateChannelsList { QStringLiteral("stable"), QStringLiteral("enterprise") };
static const QString defaultEnterpriseChannel = "enterprise";
}

namespace OCC {
Expand Down Expand Up @@ -689,17 +694,37 @@ int ConfigFile::updateSegment() const

QStringList ConfigFile::validUpdateChannels() const
{
return validUpdateChannelsList;
const auto isBranded = Theme::instance()->isBranded();

if (isBranded) {
return { defaultUpdateChannelName };
}

if (serverHasValidSubscription()) {
return enterpriseUpdateChannelsList;
}

return defaultUpdateChannelsList;
}

QString ConfigFile::defaultUpdateChannel() const
{
const auto isBranded = Theme::instance()->isBranded();
if (serverHasValidSubscription() && !isBranded) {
if (const auto serverChannel = desktopEnterpriseChannel();
validUpdateChannels().contains(serverChannel)) {
qCWarning(lcConfigFile()) << "Enforcing update channel" << serverChannel << "because that is the desktop enterprise channel returned by the server.";
return serverChannel;
}
}

if (const auto currentVersionSuffix = Theme::instance()->versionSuffix();
validUpdateChannels().contains(currentVersionSuffix)) {
validUpdateChannels().contains(currentVersionSuffix) && !isBranded) {
qCWarning(lcConfigFile()) << "Enforcing update channel" << currentVersionSuffix << "because of the version suffix of the current client.";
return currentVersionSuffix;
}

qCWarning(lcConfigFile()) << "Enforcing default update channel" << defaultUpdateChannelName;
return defaultUpdateChannelName;
}

Expand All @@ -721,7 +746,7 @@ void ConfigFile::setUpdateChannel(const QString &channel)
if (!validUpdateChannels().contains(channel)) {
qCWarning(lcConfigFile()) << "Received invalid update channel:"
<< channel
<< "can only accept 'stable', 'beta' or 'daily'. Ignoring.";
<< "can only accept" << validUpdateChannels() << ". Ignoring.";
return;
}

Expand Down Expand Up @@ -1176,6 +1201,31 @@ void ConfigFile::setLaunchOnSystemStartup(const bool autostart)
settings.setValue(QLatin1String(launchOnSystemStartupC), autostart);
}

bool ConfigFile::serverHasValidSubscription() const
{
QSettings settings(configFile(), QSettings::IniFormat);
return settings.value(QLatin1String(serverHasValidSubscriptionC), false).toBool();
}

void ConfigFile::setServerHasValidSubscription(const bool valid)
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setValue(QLatin1String(serverHasValidSubscriptionC), valid);
}

QString ConfigFile::desktopEnterpriseChannel() const
{
QSettings settings(configFile(), QSettings::IniFormat);
return settings.value(QLatin1String(desktopEnterpriseChannelName), defaultUpdateChannel()).toString();
}

void ConfigFile::setDesktopEnterpriseChannel(const QString &channel)
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setValue(QLatin1String(desktopEnterpriseChannelName), channel);
}


Q_GLOBAL_STATIC(QString, g_configFileName)

std::unique_ptr<QSettings> ConfigFile::settingsWithGroup(const QString &group, QObject *parent)
Expand Down
6 changes: 6 additions & 0 deletions src/libsync/configfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,12 @@ class OWNCLOUDSYNC_EXPORT ConfigFile
[[nodiscard]] bool launchOnSystemStartup() const;
void setLaunchOnSystemStartup(const bool autostart);

[[nodiscard]] bool serverHasValidSubscription() const;
void setServerHasValidSubscription(bool valid);

[[nodiscard]] QString desktopEnterpriseChannel() const;
void setDesktopEnterpriseChannel(const QString &channel);

/** Returns a new settings pre-set in a specific group. The Settings will be created
with the given parent. If no parent is specified, the caller must destroy the settings */
static std::unique_ptr<QSettings> settingsWithGroup(const QString &group, QObject *parent = nullptr);
Expand Down
2 changes: 1 addition & 1 deletion src/libsync/theme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ QString Theme::statusHeaderText(SyncResult::Status status) const

bool Theme::isBranded() const
{
return appNameGUI() != QStringLiteral("Nextcloud");
return (appNameGUI() != QStringLiteral("Nextcloud") && NEXTCLOUD_DEV == 0);
}

QString Theme::appNameGUI() const
Expand Down
29 changes: 29 additions & 0 deletions test/testcapabilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,35 @@ private slots:

QCOMPARE(filesLockAvailable, true);
}

void testSupport_hasValidSubscription_returnTrue()
{
QVariantMap supportMap;
supportMap["hasValidSubscription"] = "true";

QVariantMap capabilitiesMap;
capabilitiesMap["support"] = supportMap;

const auto &capabilities = OCC::Capabilities(capabilitiesMap);
const auto serverHasValidSubscription = capabilities.serverHasValidSubscription();

QCOMPARE(serverHasValidSubscription, true);
}

void testSupport_desktopEnterpriseChannel_returnString()
{
QVariantMap supportMap;
const auto defaultChannel = "stable";
supportMap["desktopEnterpriseChannel"] = defaultChannel;

QVariantMap capabilitiesMap;
capabilitiesMap["support"] = supportMap;

const auto &capabilities = OCC::Capabilities(capabilitiesMap);
const auto enterpriseChannel = capabilities.desktopEnterpriseChannel();

QCOMPARE(enterpriseChannel, defaultChannel);
}
};

QTEST_GUILESS_MAIN(TestCapabilities)
Expand Down