Skip to content

Commit

Permalink
Link sharing ui improvements
Browse files Browse the repository at this point in the history
- Respect fine-grained "password required" capability #7247
- Allow password/expiration to be added to shares that were created
  without these at a time when the server allowed that #7313
  • Loading branch information
ckamm committed Jul 17, 2019
1 parent aafa903 commit 6140797
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 45 deletions.
105 changes: 63 additions & 42 deletions src/gui/sharelinkwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ ShareLinkWidget::ShareLinkWidget(AccountPtr account,
, _sharePath(sharePath)
, _localPath(localPath)
, _manager(nullptr)
, _passwordRequired(false)
, _expiryRequired(false)
, _namesSupported(true)
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -329,25 +327,48 @@ 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 (share && share->isPasswordSet()) {
if (createNew) {
if (passwordRequired) {
_ui->checkBox_password->setChecked(true);
_ui->lineEdit_password->setPlaceholderText("********");
_ui->lineEdit_password->setPlaceholderText(tr("Please Set Password"));
_ui->lineEdit_password->setEnabled(true);
} else if (createNew && _passwordRequired) {
} 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(tr("Please Set Password"));
_ui->lineEdit_password->setPlaceholderText("********");
_ui->lineEdit_password->setEnabled(true);
} else {
_ui->checkBox_password->setChecked(false);
Expand All @@ -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);
Expand Down Expand Up @@ -656,6 +671,9 @@ void ShareLinkWidget::slotPermissionsClicked()
_ui->errorLabel->hide();

current->setPermissions(uiPermissionState());
} else {
// Password may now be required, update ui.
slotShareSelectionChanged();
}
}

Expand Down Expand Up @@ -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);
}
Expand All @@ -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();
}
Expand Down
1 change: 0 additions & 1 deletion src/gui/sharelinkwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ private slots:
ShareManager *_manager;

bool _isFile;
bool _passwordRequired;
bool _expiryRequired;
bool _namesSupported;

Expand Down
2 changes: 1 addition & 1 deletion src/gui/socketapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand Down
24 changes: 24 additions & 0 deletions src/libsync/capabilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,30 @@ bool Capabilities::sharePublicLinkEnforcePassword() const
return _capabilities["files_sharing"].toMap()["public"].toMap()["password"].toMap()["enforced"].toBool();
}

bool Capabilities::sharePublicLinkEnforcePasswordForReadOnly() const
{
auto value = _capabilities["files_sharing"].toMap()["public"].toMap()["password"].toMap()["enforced_for"].toMap()["read_only"];
if (!value.isValid())
return sharePublicLinkEnforcePassword();
return value.toBool();
}

bool Capabilities::sharePublicLinkEnforcePasswordForReadWrite() const
{
auto value = _capabilities["files_sharing"].toMap()["public"].toMap()["password"].toMap()["enforced_for"].toMap()["read_write"];
if (!value.isValid())
return sharePublicLinkEnforcePassword();
return value.toBool();
}

bool Capabilities::sharePublicLinkEnforcePasswordForUploadOnly() const
{
auto value = _capabilities["files_sharing"].toMap()["public"].toMap()["password"].toMap()["enforced_for"].toMap()["upload_only"];
if (!value.isValid())
return sharePublicLinkEnforcePassword();
return value.toBool();
}

bool Capabilities::sharePublicLinkDefaultExpire() const
{
return _capabilities["files_sharing"].toMap()["public"].toMap()["expire_date"].toMap()["enabled"].toBool();
Expand Down
22 changes: 21 additions & 1 deletion src/libsync/capabilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,16 @@ class OWNCLOUDSYNC_EXPORT Capabilities
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;
Expand Down Expand Up @@ -135,6 +144,17 @@ class OWNCLOUDSYNC_EXPORT Capabilities
bool versioningEnabled() const;

private:
/** Whether a password is required for link shares.
*
* Note that since server 10.0.8 there are more fine-grained
* permissions for each permission style of link share: see
* sharePublicLinkEnforcePasswordForReadOnly() etc.
*
* The newer server also exposes the broad setting and currently
* seems to or-combine the individual flags. We shouldn't rely on that.
*/
bool sharePublicLinkEnforcePassword() const;

QVariantMap _capabilities;
};
}
Expand Down

0 comments on commit 6140797

Please sign in to comment.