diff --git a/src/gui/sharelinkwidget.cpp b/src/gui/sharelinkwidget.cpp index 29d627daf7..5aeb2e9a13 100644 --- a/src/gui/sharelinkwidget.cpp +++ b/src/gui/sharelinkwidget.cpp @@ -45,7 +45,6 @@ ShareLinkWidget::ShareLinkWidget(AccountPtr account, , _sharePath(sharePath) , _localPath(localPath) , _manager(nullptr) - , _passwordRequired(false) , _expiryRequired(false) , _namesSupported(true) { @@ -136,10 +135,9 @@ ShareLinkWidget::ShareLinkWidget(AccountPtr account, // Parse capabilities - // If password is enforced then don't allow users to disable it - if (_account->capabilities().sharePublicLinkEnforcePassword()) { - _ui->checkBox_password->setEnabled(false); - _passwordRequired = true; + if (!_account->capabilities().sharePublicLinkAllowUpload()) { + _ui->radio_readWrite->setEnabled(false); + _ui->radio_uploadOnly->setEnabled(false); } // If expiredate is enforced do not allow disable and set max days @@ -329,26 +327,49 @@ void ShareLinkWidget::slotShareSelectionChanged() _ui->shareProperties->setEnabled(true); - _ui->checkBox_password->setEnabled(!_passwordRequired); - _ui->checkBox_expire->setEnabled(!_expiryRequired); - _ui->widget_editing->setEnabled(true); - if (!_account->capabilities().sharePublicLinkAllowUpload()) { - _ui->radio_readWrite->setEnabled(false); - _ui->radio_uploadOnly->setEnabled(false); + // Public upload state (files can only be read-only, box is hidden for them) + _ui->widget_editing->setEnabled(!_isFile); + if (!selectionUnchanged) { + if (_isFile) { + _ui->radio_readOnly->setChecked(true); + } else { + if (share && share->getPublicUpload()) { + if (share->getShowFileListing()) { + _ui->radio_readWrite->setChecked(true); + } else { + _ui->radio_uploadOnly->setChecked(true); + } + } else { + _ui->radio_readOnly->setChecked(true); + } + } } + const auto capabilities = _account->capabilities(); + const bool passwordRequired = + (_ui->radio_readOnly->isChecked() && capabilities.sharePublicLinkEnforcePasswordForReadOnly()) + || (_ui->radio_readWrite->isChecked() && capabilities.sharePublicLinkEnforcePasswordForReadWrite()) + || (_ui->radio_uploadOnly->isChecked() && capabilities.sharePublicLinkEnforcePasswordForUploadOnly()); + // Password state _ui->pushButton_setPassword->setVisible(!createNew); _ui->checkBox_password->setText(tr("P&assword protect")); - if (!selectionUnchanged) { + if (createNew) { + if (passwordRequired) { + _ui->checkBox_password->setChecked(true); + _ui->lineEdit_password->setPlaceholderText(tr("Please Set Password")); + _ui->lineEdit_password->setEnabled(true); + } else if (!selectionUnchanged || _ui->lineEdit_password->text().isEmpty()) { + // force to off if no password was entered yet + _ui->checkBox_password->setChecked(false); + _ui->lineEdit_password->setPlaceholderText(QString()); + _ui->lineEdit_password->setEnabled(false); + } + } else if (!selectionUnchanged) { if (share && share->isPasswordSet()) { _ui->checkBox_password->setChecked(true); _ui->lineEdit_password->setPlaceholderText("********"); _ui->lineEdit_password->setEnabled(true); - } else if (createNew && _passwordRequired) { - _ui->checkBox_password->setChecked(true); - _ui->lineEdit_password->setPlaceholderText(tr("Please Set Password")); - _ui->lineEdit_password->setEnabled(true); } else { _ui->checkBox_password->setChecked(false); _ui->lineEdit_password->setPlaceholderText(QString()); @@ -357,37 +378,31 @@ void ShareLinkWidget::slotShareSelectionChanged() _ui->lineEdit_password->setText(QString()); _ui->pushButton_setPassword->setEnabled(false); } + // The following is done to work with old shares when the pw requirement + // is enabled on the server later: users can add pws to old shares. + _ui->checkBox_password->setEnabled(!_ui->checkBox_password->isChecked() || !passwordRequired); // Expiry state _ui->calendar->setMinimumDate(QDate::currentDate().addDays(1)); - if (share && share->getExpireDate().isValid()) { - _ui->checkBox_expire->setChecked(true); - _ui->calendar->setDate(share->getExpireDate()); - _ui->calendar->setEnabled(true); - } else if (createNew) { - const QDate defaultExpire = capabilityDefaultExpireDate(); - if (defaultExpire.isValid()) - _ui->calendar->setDate(defaultExpire); - const bool enabled = _expiryRequired || defaultExpire.isValid(); - _ui->checkBox_expire->setChecked(enabled); - _ui->calendar->setEnabled(enabled); - } else { - _ui->checkBox_expire->setChecked(false); - _ui->calendar->setEnabled(false); - } - - // Public upload state (box is hidden for files) - if (!_isFile) { - if (share && share->getPublicUpload()) { - if (share->getShowFileListing()) { - _ui->radio_readWrite->setChecked(true); - } else { - _ui->radio_uploadOnly->setChecked(true); - } + if (!selectionUnchanged) { + if (share && share->getExpireDate().isValid()) { + _ui->checkBox_expire->setChecked(true); + _ui->calendar->setDate(share->getExpireDate()); + _ui->calendar->setEnabled(true); + } else if (createNew) { + const QDate defaultExpire = capabilityDefaultExpireDate(); + if (defaultExpire.isValid()) + _ui->calendar->setDate(defaultExpire); + const bool enabled = _expiryRequired || defaultExpire.isValid(); + _ui->checkBox_expire->setChecked(enabled); + _ui->calendar->setEnabled(enabled); } else { - _ui->radio_readOnly->setChecked(true); + _ui->checkBox_expire->setChecked(false); + _ui->calendar->setEnabled(false); } } + // Allows checking expiry on old shares created before it was required. + _ui->checkBox_expire->setEnabled(!_ui->checkBox_expire->isChecked() || !_expiryRequired); // Name and create button _ui->create->setVisible(createNew); @@ -656,6 +671,9 @@ void ShareLinkWidget::slotPermissionsClicked() _ui->errorLabel->hide(); current->setPermissions(uiPermissionState()); + } else { + // Password may now be required, update ui. + slotShareSelectionChanged(); } } @@ -691,6 +709,10 @@ void ShareLinkWidget::slotServerError(int code, const QString &message) _pi_password->stopAnimation(); _pi_editing->stopAnimation(); + // Reset UI state + _selectedShareId.clear(); + slotShareSelectionChanged(); + qCWarning(lcSharing) << "Error from server" << code << message; displayError(message); } @@ -699,7 +721,6 @@ void ShareLinkWidget::slotPasswordSetError(int code, const QString &message) { slotServerError(code, message); - _ui->checkBox_password->setEnabled(!_passwordRequired); _ui->lineEdit_password->setEnabled(true); _ui->lineEdit_password->setFocus(); } diff --git a/src/gui/sharelinkwidget.h b/src/gui/sharelinkwidget.h index e2cec5ed4c..05bc0f0924 100644 --- a/src/gui/sharelinkwidget.h +++ b/src/gui/sharelinkwidget.h @@ -127,7 +127,6 @@ private: ShareManager *_manager; bool _isFile; - bool _passwordRequired; bool _expiryRequired; bool _namesSupported; diff --git a/src/gui/socketapi.cpp b/src/gui/socketapi.cpp index 1983bad56e..a61e9a2c16 100644 --- a/src/gui/socketapi.cpp +++ b/src/gui/socketapi.cpp @@ -813,7 +813,7 @@ void SocketApi::sendSharingContextMenuOptions(const FileData &fileData, SocketLi // Is is possible to create a public link without user choices? bool canCreateDefaultPublicLink = publicLinksEnabled - && !capabilities.sharePublicLinkEnforcePassword(); + && !capabilities.sharePublicLinkEnforcePasswordForReadOnly(); if (canCreateDefaultPublicLink) { listener->sendMessage(QLatin1String("MENU_ITEM:COPY_PUBLIC_LINK") + flagString + tr("Copy public link to clipboard")); diff --git a/src/libsync/capabilities.cpp b/src/libsync/capabilities.cpp index 7a68af71c7..1ef575a14b 100644 --- a/src/libsync/capabilities.cpp +++ b/src/libsync/capabilities.cpp @@ -55,9 +55,27 @@ bool Capabilities::sharePublicLinkSupportsUploadOnly() const return _capabilities["files_sharing"].toMap()["public"].toMap()["supports_upload_only"].toBool(); } -bool Capabilities::sharePublicLinkEnforcePassword() const +static bool getEnforcePasswordCapability(const QVariantMap &capabilities, const QByteArray &name) { - return _capabilities["files_sharing"].toMap()["public"].toMap()["password"].toMap()["enforced"].toBool(); + auto value = capabilities["files_sharing"].toMap()["public"].toMap()["password"].toMap()["enforced_for"].toMap()[name]; + if (!value.isValid()) + return capabilities["files_sharing"].toMap()["public"].toMap()["password"].toMap()["enforced"].toBool(); + return value.toBool(); +} + +bool Capabilities::sharePublicLinkEnforcePasswordForReadOnly() const +{ + return getEnforcePasswordCapability(_capabilities, QByteArrayLiteral("read_only")); +} + +bool Capabilities::sharePublicLinkEnforcePasswordForReadWrite() const +{ + return getEnforcePasswordCapability(_capabilities, QByteArrayLiteral("read_write")); +} + +bool Capabilities::sharePublicLinkEnforcePasswordForUploadOnly() const +{ + return getEnforcePasswordCapability(_capabilities, QByteArrayLiteral("upload_only")); } bool Capabilities::sharePublicLinkDefaultExpire() const diff --git a/src/libsync/capabilities.h b/src/libsync/capabilities.h index b49008f523..b25fa438e5 100644 --- a/src/libsync/capabilities.h +++ b/src/libsync/capabilities.h @@ -37,7 +37,16 @@ public: bool sharePublicLink() const; bool sharePublicLinkAllowUpload() const; bool sharePublicLinkSupportsUploadOnly() const; - bool sharePublicLinkEnforcePassword() const; + + /** Whether read-only link shares require a password. + * + * Returns sharePublicLinkEnforcePassword() if the fine-grained + * permission isn't available. + */ + bool sharePublicLinkEnforcePasswordForReadOnly() const; + bool sharePublicLinkEnforcePasswordForReadWrite() const; + bool sharePublicLinkEnforcePasswordForUploadOnly() const; + bool sharePublicLinkDefaultExpire() const; int sharePublicLinkDefaultExpireDateDays() const; bool sharePublicLinkEnforceExpireDate() const;