Merge pull request #3186 from nextcloud/feature/share-obey-enforced-password-for-share-by-mail

Obey enforced password for share by email.
This commit is contained in:
allexzander 2021-04-29 11:21:24 +03:00 коммит произвёл GitHub
Родитель a4bad72c57 e72013fed1
Коммит 14843b7a62
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 515 добавлений и 90 удалений

Просмотреть файл

@ -142,7 +142,8 @@ void OcsShareJob::createLinkShare(const QString &path,
void OcsShareJob::createShare(const QString &path,
const Share::ShareType shareType,
const QString &shareWith,
const Share::Permissions permissions)
const Share::Permissions permissions,
const QString &password)
{
Q_UNUSED(permissions)
setVerb("POST");
@ -151,6 +152,10 @@ void OcsShareJob::createShare(const QString &path,
addParam(QString::fromLatin1("shareType"), QString::number(shareType));
addParam(QString::fromLatin1("shareWith"), shareWith);
if (!password.isEmpty()) {
addParam(QString::fromLatin1("password"), password);
}
start();
}

Просмотреть файл

@ -113,11 +113,13 @@ public:
* @param shareType The type of share (user/group/link/federated)
* @param shareWith The uid/gid/federated id to share with
* @param permissions The permissions the share will have
* @param password The password to protect the share with
*/
void createShare(const QString &path,
const Share::ShareType shareType,
const QString &shareWith = "",
const Share::Permissions permissions = SharePermissionRead);
const Share::Permissions permissions = SharePermissionRead,
const QString &password = "");
/**
* Returns information on the items shared with the current user.

Просмотреть файл

@ -56,6 +56,7 @@ Share::Share(AccountPtr account,
const QString &ownerDisplayName,
const QString &path,
const ShareType shareType,
bool isPasswordSet,
const Permissions permissions,
const QSharedPointer<Sharee> shareWith)
: _account(account)
@ -64,6 +65,7 @@ Share::Share(AccountPtr account,
, _ownerDisplayName(ownerDisplayName)
, _path(path)
, _shareType(shareType)
, _isPasswordSet(isPasswordSet)
, _permissions(permissions)
, _shareWith(shareWith)
{
@ -104,6 +106,19 @@ QSharedPointer<Sharee> Share::getShareWith() const
return _shareWith;
}
void Share::setPassword(const QString &password)
{
auto * const job = new OcsShareJob(_account);
connect(job, &OcsShareJob::shareJobFinished, this, &Share::slotPasswordSet);
connect(job, &OcsJob::ocsError, this, &Share::slotSetPasswordError);
job->setPassword(getId(), password);
}
bool Share::isPasswordSet() const
{
return _isPasswordSet;
}
void Share::setPermissions(Permissions permissions)
{
auto *job = new OcsShareJob(_account);
@ -142,6 +157,17 @@ void Share::slotOcsError(int statusCode, const QString &message)
emit serverError(statusCode, message);
}
void Share::slotPasswordSet(const QJsonDocument &, const QVariant &value)
{
_isPasswordSet = !value.toString().isEmpty();
emit passwordSet();
}
void Share::slotSetPasswordError(int statusCode, const QString &message)
{
emit passwordSetError(statusCode, message);
}
QUrl LinkShare::getLink() const
{
return _url;
@ -159,11 +185,6 @@ QDate LinkShare::getExpireDate() const
return _expireDate;
}
bool LinkShare::isPasswordSet() const
{
return _passwordSet;
}
LinkShare::LinkShare(AccountPtr account,
const QString &id,
const QString &uidowner,
@ -172,13 +193,12 @@ LinkShare::LinkShare(AccountPtr account,
const QString &name,
const QString &token,
Permissions permissions,
bool passwordSet,
bool isPasswordSet,
const QUrl &url,
const QDate &expireDate)
: Share(account, id, uidowner, ownerDisplayName, path, Share::TypeLink, permissions)
: Share(account, id, uidowner, ownerDisplayName, path, Share::TypeLink, isPasswordSet, permissions)
, _name(name)
, _token(token)
, _passwordSet(passwordSet)
, _expireDate(expireDate)
, _url(url)
{
@ -231,20 +251,6 @@ QString LinkShare::getToken() const
return _token;
}
void LinkShare::setPassword(const QString &password)
{
auto *job = new OcsShareJob(_account);
connect(job, &OcsShareJob::shareJobFinished, this, &LinkShare::slotPasswordSet);
connect(job, &OcsJob::ocsError, this, &LinkShare::slotSetPasswordError);
job->setPassword(getId(), password);
}
void LinkShare::slotPasswordSet(const QJsonDocument &, const QVariant &value)
{
_passwordSet = value.toString() != "";
emit passwordSet();
}
void LinkShare::setExpireDate(const QDate &date)
{
auto *job = new OcsShareJob(_account);
@ -269,11 +275,6 @@ void LinkShare::slotExpireDateSet(const QJsonDocument &reply, const QVariant &va
emit expireDateSet();
}
void LinkShare::slotSetPasswordError(int statusCode, const QString &message)
{
emit passwordSetError(statusCode, message);
}
void LinkShare::slotNameSet(const QJsonDocument &, const QVariant &value)
{
_name = value.toString();
@ -286,15 +287,16 @@ UserGroupShare::UserGroupShare(AccountPtr account,
const QString &ownerDisplayName,
const QString &path,
const ShareType shareType,
bool isPasswordSet,
const Permissions permissions,
const QSharedPointer<Sharee> shareWith,
const QDate &expireDate,
const QString &note)
: Share(account, id, owner, ownerDisplayName, path, shareType, permissions, shareWith)
, _expireDate(expireDate)
: Share(account, id, owner, ownerDisplayName, path, shareType, isPasswordSet, permissions, shareWith)
, _note(note)
, _expireDate(expireDate)
{
Q_ASSERT(shareType == TypeUser || shareType == TypeGroup);
Q_ASSERT(shareType == TypeUser || shareType == TypeGroup || shareType == TypeEmail);
Q_ASSERT(shareWith);
}
@ -389,7 +391,8 @@ void ShareManager::slotLinkShareCreated(const QJsonDocument &reply)
void ShareManager::createShare(const QString &path,
const Share::ShareType shareType,
const QString shareWith,
const Share::Permissions desiredPermissions)
const Share::Permissions desiredPermissions,
const QString &password)
{
auto job = new OcsShareJob(_account);
connect(job, &OcsJob::ocsError, this, &ShareManager::slotOcsError);
@ -416,7 +419,7 @@ void ShareManager::createShare(const QString &path,
auto *job = new OcsShareJob(_account);
connect(job, &OcsShareJob::shareJobFinished, this, &ShareManager::slotShareCreated);
connect(job, &OcsJob::ocsError, this, &ShareManager::slotOcsError);
job->createShare(path, shareType, shareWith, validPermissions);
job->createShare(path, shareType, shareWith, validPermissions, password);
});
job->getSharedWithMe();
}
@ -458,7 +461,7 @@ void ShareManager::slotSharesFetched(const QJsonDocument &reply)
if (shareType == Share::TypeLink) {
newShare = parseLinkShare(data);
} else if (shareType == Share::TypeGroup || shareType == Share::TypeUser) {
} else if (shareType == Share::TypeGroup || shareType == Share::TypeUser || shareType == Share::TypeEmail) {
newShare = parseUserGroupShare(data);
} else {
newShare = parseShare(data);
@ -493,6 +496,7 @@ QSharedPointer<UserGroupShare> ShareManager::parseUserGroupShare(const QJsonObje
data.value("displayname_owner").toVariant().toString(),
data.value("path").toString(),
static_cast<Share::ShareType>(data.value("share_type").toInt()),
!data.value("password").toString().isEmpty(),
static_cast<Share::Permissions>(data.value("permissions").toInt()),
sharee,
expireDate,
@ -546,6 +550,7 @@ QSharedPointer<Share> ShareManager::parseShare(const QJsonObject &data)
data.value("displayname_owner").toVariant().toString(),
data.value("path").toString(),
(Share::ShareType)data.value("share_type").toInt(),
!data.value("password").toString().isEmpty(),
(Share::Permissions)data.value("permissions").toInt(),
sharee));
}

Просмотреть файл

@ -61,6 +61,7 @@ public:
const QString &ownerDisplayName,
const QString &path,
const ShareType shareType,
bool isPasswordSet = false,
const Permissions permissions = SharePermissionDefault,
const QSharedPointer<Sharee> shareWith = QSharedPointer<Sharee>(nullptr));
@ -109,7 +110,17 @@ public:
*/
void setPermissions(Permissions permissions);
/**
/*
* Set the password for remote share
*
* On success the passwordSet signal is emitted
* In case of a server error the passwordSetError signal is emitted.
*/
void setPassword(const QString &password);
bool isPasswordSet() const;
/*
* Deletes a share
*
* On success the shareDeleted signal is emitted
@ -121,6 +132,8 @@ signals:
void permissionsSet();
void shareDeleted();
void serverError(int code, const QString &message);
void passwordSet();
void passwordSetError(int statusCode, const QString &message);
protected:
AccountPtr _account;
@ -129,11 +142,14 @@ protected:
QString _ownerDisplayName;
QString _path;
ShareType _shareType;
bool _isPasswordSet;
Permissions _permissions;
QSharedPointer<Sharee> _shareWith;
protected slots:
void slotOcsError(int statusCode, const QString &message);
void slotPasswordSet(const QJsonDocument &, const QVariant &value);
void slotSetPasswordError(int statusCode, const QString &message);
private slots:
void slotDeleted();
@ -157,7 +173,7 @@ public:
const QString &name,
const QString &token,
const Permissions permissions,
bool passwordSet,
bool isPasswordSet,
const QUrl &url,
const QDate &expireDate);
@ -210,19 +226,6 @@ public:
*/
QString getToken() const;
/*
* Set the password
*
* On success the passwordSet signal is emitted
* In case of a server error the serverError signal is emitted.
*/
void setPassword(const QString &password);
/*
* Is the password set?
*/
bool isPasswordSet() const;
/*
* Get the expiration date
*/
@ -238,22 +241,17 @@ public:
signals:
void expireDateSet();
void passwordSet();
void noteSet();
void passwordSetError(int statusCode, const QString &message);
void nameSet();
private slots:
void slotPasswordSet(const QJsonDocument &, const QVariant &value);
void slotNoteSet(const QJsonDocument &, const QVariant &value);
void slotExpireDateSet(const QJsonDocument &reply, const QVariant &value);
void slotSetPasswordError(int statusCode, const QString &message);
void slotNameSet(const QJsonDocument &, const QVariant &value);
private:
QString _name;
QString _token;
bool _passwordSet;
QString _note;
QDate _expireDate;
QUrl _url;
@ -269,6 +267,7 @@ public:
const QString &ownerDisplayName,
const QString &path,
const ShareType shareType,
bool isPasswordSet,
const Permissions permissions,
const QSharedPointer<Sharee> shareWith,
const QDate &expireDate,
@ -335,7 +334,8 @@ public:
void createShare(const QString &path,
const Share::ShareType shareType,
const QString shareWith,
const Share::Permissions permissions);
const Share::Permissions permissions,
const QString &password = "");
/**
* Fetch all the shares for path

Просмотреть файл

@ -40,6 +40,7 @@
#include <QMenu>
#include <QAction>
#include <QDesktopServices>
#include <QInputDialog>
#include <QMessageBox>
#include <QCryptographicHash>
#include <QColor>
@ -48,6 +49,10 @@
#include <cstring>
namespace {
const char *passwordIsSetPlaceholder = "●●●●●●●●";
}
namespace OCC {
ShareUserGroupWidget::ShareUserGroupWidget(AccountPtr account,
@ -97,7 +102,7 @@ ShareUserGroupWidget::ShareUserGroupWidget(AccountPtr account,
_manager = new ShareManager(_account, this);
connect(_manager, &ShareManager::sharesFetched, this, &ShareUserGroupWidget::slotSharesFetched);
connect(_manager, &ShareManager::shareCreated, this, &ShareUserGroupWidget::getShares);
connect(_manager, &ShareManager::shareCreated, this, &ShareUserGroupWidget::slotShareCreated);
connect(_manager, &ShareManager::serverError, this, &ShareUserGroupWidget::displayError);
connect(_ui->shareeLineEdit, &QLineEdit::returnPressed, this, &ShareUserGroupWidget::slotLineEditReturn);
connect(_ui->confirmShare, &QAbstractButton::clicked, this, &ShareUserGroupWidget::slotLineEditReturn);
@ -202,6 +207,16 @@ void ShareUserGroupWidget::getShares()
_manager->fetchShares(_sharePath);
}
void ShareUserGroupWidget::slotShareCreated(const QSharedPointer<Share> &share)
{
if (share && _account->capabilities().shareEmailPasswordEnabled() && !_account->capabilities().shareEmailPasswordEnforced()) {
// remember this share Id so we can set it's password Line Edit to focus later
_lastCreatedShareId = share->getId();
}
// fetch all shares including the one we've just created
getShares();
}
void ShareUserGroupWidget::slotSharesFetched(const QList<QSharedPointer<Share>> &shares)
{
QScrollArea *scrollArea = _parentScrollArea;
@ -213,6 +228,8 @@ void ShareUserGroupWidget::slotSharesFetched(const QList<QSharedPointer<Share>>
int height = 0;
QList<QString> linkOwners({});
ShareUserLine *justCreatedShareThatNeedsPassword = nullptr;
foreach (const auto &share, shares) {
// We don't handle link shares, only TypeUser or TypeGroup
if (share->getShareType() == Share::TypeLink) {
@ -230,9 +247,9 @@ void ShareUserGroupWidget::slotSharesFetched(const QList<QSharedPointer<Share>>
}
Q_ASSERT(share->getShareType() == Share::TypeUser || share->getShareType() == Share::TypeGroup);
Q_ASSERT(share->getShareType() == Share::TypeUser || share->getShareType() == Share::TypeGroup || share->getShareType() == Share::TypeEmail);
auto userGroupShare = qSharedPointerDynamicCast<UserGroupShare>(share);
auto *s = new ShareUserLine(userGroupShare, _maxSharingPermissions, _isFile, _parentScrollArea);
auto *s = new ShareUserLine(_account, userGroupShare, _maxSharingPermissions, _isFile, _parentScrollArea);
connect(s, &ShareUserLine::resizeRequested, this, &ShareUserGroupWidget::slotAdjustScrollWidgetSize);
connect(s, &ShareUserLine::visualDeletionDone, this, &ShareUserGroupWidget::getShares);
s->setBackgroundRole(layout->count() % 2 == 0 ? QPalette::Base : QPalette::AlternateBase);
@ -242,6 +259,13 @@ void ShareUserGroupWidget::slotSharesFetched(const QList<QSharedPointer<Share>>
layout->addWidget(s);
if (!_lastCreatedShareId.isEmpty() && share->getId() == _lastCreatedShareId) {
_lastCreatedShareId = QString();
if (_account->capabilities().shareEmailPasswordEnabled() && !_account->capabilities().shareEmailPasswordEnforced()) {
justCreatedShareThatNeedsPassword = s;
}
}
x++;
if (x <= 3) {
height = newViewPort->sizeHint().height();
@ -266,6 +290,11 @@ void ShareUserGroupWidget::slotSharesFetched(const QList<QSharedPointer<Share>>
_disableCompleterActivated = false;
activateShareeLineEdit();
if (justCreatedShareThatNeedsPassword) {
// always set focus to a password Line Edit when the new email share is created on a server with optional passwords enabled for email shares
justCreatedShareThatNeedsPassword->focusPasswordLineEdit();
}
}
void ShareUserGroupWidget::slotAdjustScrollWidgetSize()
@ -338,6 +367,9 @@ void ShareUserGroupWidget::slotCompleterActivated(const QModelIndex &index)
* https://github.com/owncloud/core/issues/22122#issuecomment-185637344
* https://github.com/owncloud/client/issues/4996
*/
_lastCreatedShareId = QString();
if (sharee->type() == Sharee::Federated
&& _account->serverVersionInt() < Account::makeServerVersion(9, 1, 0)) {
int permissions = SharePermissionRead | SharePermissionUpdate;
@ -347,16 +379,36 @@ void ShareUserGroupWidget::slotCompleterActivated(const QModelIndex &index)
_manager->createShare(_sharePath, Share::ShareType(sharee->type()),
sharee->shareWith(), SharePermission(permissions));
} else {
QString password;
if (sharee->type() == Sharee::Email && _account->capabilities().shareEmailPasswordEnforced()) {
_ui->shareeLineEdit->clear();
// always show a dialog for password-enforced email shares
bool ok = false;
do {
password = QInputDialog::getText(
this,
tr("Password for share required"),
tr("Please enter a password for your email share:"),
QLineEdit::Password,
QString(),
&ok);
} while (password.isEmpty() && ok);
if (!ok) {
return;
}
}
// Default permissions on creation
int permissions = SharePermissionCreate | SharePermissionUpdate
| SharePermissionDelete | SharePermissionShare;
_manager->createShare(_sharePath, Share::ShareType(sharee->type()),
sharee->shareWith(), SharePermission(permissions));
sharee->shareWith(), SharePermission(permissions), password);
}
_ui->shareeLineEdit->setEnabled(false);
_ui->shareeLineEdit->setText(QString());
_ui->shareeLineEdit->clear();
}
void ShareUserGroupWidget::slotCompleterHighlighted(const QModelIndex &index)
@ -424,12 +476,14 @@ void ShareUserGroupWidget::activateShareeLineEdit()
_ui->shareeLineEdit->setFocus();
}
ShareUserLine::ShareUserLine(QSharedPointer<UserGroupShare> share,
SharePermissions maxSharingPermissions,
bool isFile,
QWidget *parent)
ShareUserLine::ShareUserLine(AccountPtr account,
QSharedPointer<UserGroupShare> share,
SharePermissions maxSharingPermissions,
bool isFile,
QWidget *parent)
: QWidget(parent)
, _ui(new Ui::ShareUserLine)
, _account(account)
, _share(share)
, _isFile(isFile)
{
@ -454,6 +508,9 @@ ShareUserLine::ShareUserLine(QSharedPointer<UserGroupShare> share,
connect(_share.data(), &UserGroupShare::noteSetError, this, &ShareUserLine::disableProgessIndicatorAnimation);
connect(_share.data(), &UserGroupShare::expireDateSet, this, &ShareUserLine::disableProgessIndicatorAnimation);
connect(_ui->confirmPassword, &QToolButton::clicked, this, &ShareUserLine::slotConfirmPasswordClicked);
connect(_ui->lineEdit_password, &QLineEdit::returnPressed, this, &ShareUserLine::slotLineEditPasswordReturnPressed);
// create menu with checkable permissions
auto *menu = new QMenu(this);
_permissionReshare= new QAction(tr("Can reshare"), this);
@ -463,25 +520,35 @@ ShareUserLine::ShareUserLine(QSharedPointer<UserGroupShare> share,
connect(_permissionReshare, &QAction::triggered, this, &ShareUserLine::slotPermissionsChanged);
showNoteOptions(false);
_noteLinkAction = new QAction(tr("Note to recipient"));
_noteLinkAction->setCheckable(true);
menu->addAction(_noteLinkAction);
connect(_noteLinkAction, &QAction::triggered, this, &ShareUserLine::toggleNoteOptions);
if (!_share->getNote().isEmpty()) {
_noteLinkAction->setChecked(true);
showNoteOptions(true);
// email shares do not support notes and expiration dates
const bool isNoteAndExpirationDateSupported = _share->getShareType() != Share::ShareType::TypeEmail;
if (isNoteAndExpirationDateSupported) {
_noteLinkAction = new QAction(tr("Note to recipient"));
_noteLinkAction->setCheckable(true);
menu->addAction(_noteLinkAction);
connect(_noteLinkAction, &QAction::triggered, this, &ShareUserLine::toggleNoteOptions);
if (!_share->getNote().isEmpty()) {
_noteLinkAction->setChecked(true);
showNoteOptions(true);
}
}
showExpireDateOptions(false);
_expirationDateLinkAction = new QAction(tr("Set expiration date"));
_expirationDateLinkAction->setCheckable(true);
menu->addAction(_expirationDateLinkAction);
connect(_expirationDateLinkAction, &QAction::triggered, this, &ShareUserLine::toggleExpireDateOptions);
const auto expireDate = _share->getExpireDate().isValid() ? share.data()->getExpireDate() : QDate();
if (!expireDate.isNull()) {
_ui->calendar->setDate(expireDate);
_expirationDateLinkAction->setChecked(true);
showExpireDateOptions(true);
if (isNoteAndExpirationDateSupported) {
// email shares do not support expiration dates
_expirationDateLinkAction = new QAction(tr("Set expiration date"));
_expirationDateLinkAction->setCheckable(true);
menu->addAction(_expirationDateLinkAction);
connect(_expirationDateLinkAction, &QAction::triggered, this, &ShareUserLine::toggleExpireDateOptions);
const auto expireDate = _share->getExpireDate().isValid() ? share.data()->getExpireDate() : QDate();
if (!expireDate.isNull()) {
_ui->calendar->setDate(expireDate);
_expirationDateLinkAction->setChecked(true);
showExpireDateOptions(true);
}
}
menu->addSeparator();
@ -516,9 +583,32 @@ ShareUserLine::ShareUserLine(QSharedPointer<UserGroupShare> share,
connect(_permissionDelete, &QAction::triggered, this, &ShareUserLine::slotPermissionsChanged);
}
// Adds action to display password widget (check box)
if (_share->getShareType() == Share::TypeEmail && (_share->isPasswordSet() || _account->capabilities().shareEmailPasswordEnabled())) {
_passwordProtectLinkAction = new QAction(tr("Password protect"), this);
_passwordProtectLinkAction->setCheckable(true);
_passwordProtectLinkAction->setChecked(_share->isPasswordSet());
// checkbox can be checked/unchedkec if the password is not yet set or if it's not enforced
_passwordProtectLinkAction->setEnabled(!_share->isPasswordSet() || !_account->capabilities().shareEmailPasswordEnforced());
menu->addAction(_passwordProtectLinkAction);
connect(_passwordProtectLinkAction, &QAction::triggered, this, &ShareUserLine::slotPasswordCheckboxChanged);
refreshPasswordLineEditPlaceholder();
connect(_share.data(), &Share::passwordSet, this, &ShareUserLine::slotPasswordSet);
connect(_share.data(), &Share::passwordSetError, this, &ShareUserLine::slotPasswordSetError);
}
refreshPasswordOptions();
_ui->errorLabel->hide();
_ui->permissionToolButton->setMenu(menu);
_ui->permissionToolButton->setPopupMode(QToolButton::InstantPopup);
_ui->passwordProgressIndicator->setVisible(false);
// Set the permissions checkboxes
displayPermissions();
@ -675,6 +765,29 @@ void ShareUserLine::slotPermissionsChanged()
_share->setPermissions(permissions);
}
void ShareUserLine::slotPasswordCheckboxChanged()
{
if (!_passwordProtectLinkAction->isChecked()) {
_ui->errorLabel->hide();
_ui->errorLabel->clear();
if (!_share->isPasswordSet()) {
_ui->lineEdit_password->clear();
refreshPasswordOptions();
} else {
// do not call refreshPasswordOptions here, as it will be called after the network request is complete
togglePasswordSetProgressAnimation(true);
_share->setPassword(QString());
}
} else {
refreshPasswordOptions();
if (_ui->lineEdit_password->isVisible() && _ui->lineEdit_password->isEnabled()) {
focusPasswordLineEdit();
}
}
}
void ShareUserLine::slotDeleteAnimationFinished()
{
emit resizeRequested();
@ -687,6 +800,63 @@ void ShareUserLine::slotDeleteAnimationFinished()
connect(this, SIGNAL(destroyed(QObject *)), parentWidget(), SLOT(repaint()));
}
void ShareUserLine::refreshPasswordOptions()
{
const bool isPasswordEnabled = _share->getShareType() == Share::TypeEmail && _passwordProtectLinkAction->isChecked();
_ui->passwordLabel->setVisible(isPasswordEnabled);
_ui->lineEdit_password->setEnabled(isPasswordEnabled);
_ui->lineEdit_password->setVisible(isPasswordEnabled);
_ui->confirmPassword->setVisible(isPasswordEnabled);
emit resizeRequested();
}
void ShareUserLine::refreshPasswordLineEditPlaceholder()
{
if (_share->isPasswordSet()) {
_ui->lineEdit_password->setPlaceholderText(QString::fromUtf8(passwordIsSetPlaceholder));
} else {
_ui->lineEdit_password->setPlaceholderText("");
}
}
void ShareUserLine::slotPasswordSet()
{
togglePasswordSetProgressAnimation(false);
_ui->lineEdit_password->setEnabled(true);
_ui->confirmPassword->setEnabled(true);
_ui->lineEdit_password->setText("");
_passwordProtectLinkAction->setEnabled(!_share->isPasswordSet() || !_account->capabilities().shareEmailPasswordEnforced());
refreshPasswordLineEditPlaceholder();
refreshPasswordOptions();
}
void ShareUserLine::slotPasswordSetError(int statusCode, const QString &message)
{
qCWarning(lcSharing) << "Error from server" << statusCode << message;
togglePasswordSetProgressAnimation(false);
_ui->lineEdit_password->setEnabled(true);
_ui->confirmPassword->setEnabled(true);
refreshPasswordLineEditPlaceholder();
refreshPasswordOptions();
focusPasswordLineEdit();
_ui->errorLabel->show();
_ui->errorLabel->setText(message);
emit resizeRequested();
}
void ShareUserLine::slotShareDeleted()
{
auto *animation = new QPropertyAnimation(this, "maximumHeight", this);
@ -743,6 +913,11 @@ void ShareUserLine::slotStyleChanged()
customizeStyle();
}
void ShareUserLine::focusPasswordLineEdit()
{
_ui->lineEdit_password->setFocus();
}
void ShareUserLine::customizeStyle()
{
_ui->permissionToolButton->setIcon(Theme::createColorAwareIcon(":/client/theme/more.svg"));
@ -753,6 +928,9 @@ void ShareUserLine::customizeStyle()
_ui->noteConfirmButton->setIcon(Theme::createColorAwareIcon(":/client/theme/confirm.svg"));
_ui->confirmExpirationDate->setIcon(Theme::createColorAwareIcon(":/client/theme/confirm.svg"));
_ui->progressIndicator->setColor(QGuiApplication::palette().color(QPalette::WindowText));
// make sure to force BackgroundRole to QPalette::WindowText for a lable, because it's parent always has a different role set that applies to children unless customized
_ui->errorLabel->setBackgroundRole(QPalette::WindowText);
}
void ShareUserLine::showNoteOptions(bool show)
@ -834,8 +1012,48 @@ void ShareUserLine::enableProgessIndicatorAnimation(bool enable)
}
}
void ShareUserLine::togglePasswordSetProgressAnimation(bool show)
{
// button and progress indicator are interchanged depending on if the network request is in progress or not
_ui->confirmPassword->setVisible(!show && _passwordProtectLinkAction->isChecked());
_ui->passwordProgressIndicator->setVisible(show);
if (show) {
if (!_ui->passwordProgressIndicator->isAnimated()) {
_ui->passwordProgressIndicator->startAnimation();
}
} else {
_ui->passwordProgressIndicator->stopAnimation();
}
}
void ShareUserLine::disableProgessIndicatorAnimation()
{
enableProgessIndicatorAnimation(false);
}
void ShareUserLine::setPasswordConfirmed()
{
if (_ui->lineEdit_password->text().isEmpty()) {
return;
}
_ui->lineEdit_password->setEnabled(false);
_ui->confirmPassword->setEnabled(false);
_ui->errorLabel->hide();
_ui->errorLabel->clear();
togglePasswordSetProgressAnimation(true);
_share->setPassword(_ui->lineEdit_password->text());
}
void ShareUserLine::slotLineEditPasswordReturnPressed()
{
setPasswordConfirmed();
}
void ShareUserLine::slotConfirmPasswordClicked()
{
setPasswordConfirmed();
}
}

Просмотреть файл

@ -67,6 +67,7 @@ signals:
public slots:
void getShares();
void slotShareCreated(const QSharedPointer<Share> &share);
void slotStyleChanged();
private slots:
@ -110,6 +111,8 @@ private:
ShareManager *_manager;
QProgressIndicator _pi_sharee;
QString _lastCreatedShareId;
};
/**
@ -120,7 +123,8 @@ class ShareUserLine : public QWidget
Q_OBJECT
public:
explicit ShareUserLine(QSharedPointer<UserGroupShare> share,
explicit ShareUserLine(AccountPtr account,
QSharedPointer<UserGroupShare> Share,
SharePermissions maxSharingPermissions,
bool isFile,
QWidget *parent = nullptr);
@ -135,17 +139,33 @@ signals:
public slots:
void slotStyleChanged();
void focusPasswordLineEdit();
private slots:
void on_deleteShareButton_clicked();
void slotPermissionsChanged();
void slotEditPermissionsChanged();
void slotPasswordCheckboxChanged();
void slotDeleteAnimationFinished();
void refreshPasswordOptions();
void refreshPasswordLineEditPlaceholder();
void slotPasswordSet();
void slotPasswordSetError(int statusCode, const QString &message);
void slotShareDeleted();
void slotPermissionsSet();
void slotAvatarLoaded(QImage avatar);
void setPasswordConfirmed();
void slotLineEditPasswordReturnPressed();
void slotConfirmPasswordClicked();
private:
void displayPermissions();
void loadAvatar();
@ -160,10 +180,13 @@ private:
void showExpireDateOptions(bool show);
void setExpireDate();
void togglePasswordSetProgressAnimation(bool show);
void enableProgessIndicatorAnimation(bool enable);
void disableProgessIndicatorAnimation();
Ui::ShareUserLine *_ui;
AccountPtr _account;
QSharedPointer<UserGroupShare> _share;
bool _isFile;
@ -175,6 +198,7 @@ private:
QAction *_permissionDelete;
QAction *_noteLinkAction;
QAction *_expirationDateLinkAction;
QAction *_passwordProtectLinkAction;
};
}

Просмотреть файл

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>980</width>
<height>210</height>
<height>239</height>
</rect>
</property>
<property name="sizePolicy">
@ -116,11 +116,23 @@
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="noteLabel">
<property name="minimumSize">
<size>
<width>78</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Note:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
@ -134,7 +146,7 @@
<property name="minimumSize">
<size>
<width>0</width>
<height>60</height>
<height>0</height>
</size>
</property>
<property name="sizeAdjustPolicy">
@ -158,8 +170,83 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="passwordElementsLayout">
<property name="leftMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="passwordLabel">
<property name="minimumSize">
<size>
<width>78</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Password:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="indent">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_password">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="confirmPassword">
<property name="minimumSize">
<size>
<width>28</width>
<height>28</height>
</size>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../theme.qrc">
<normaloff>:/client/theme/confirm.svg</normaloff>:/client/theme/confirm.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QProgressIndicator" name="passwordProgressIndicator" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>28</width>
<height>28</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="expirationLabel">
<property name="minimumSize">
@ -172,7 +259,7 @@
<string>Expires:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
@ -202,20 +289,92 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="errorLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>123</red>
<green>121</green>
<blue>134</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="text">
<string notr="true">Placeholder for Error text</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>OCC::ElidedLabel</class>
<extends>QLabel</extends>
<header>elidedlabel.h</header>
</customwidget>
<customwidget>
<class>QProgressIndicator</class>
<extends>QWidget</extends>
<header>QProgressIndicator.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>OCC::ElidedLabel</class>
<extends>QLabel</extends>
<header>elidedlabel.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../theme.qrc"/>

Просмотреть файл

@ -40,6 +40,16 @@ bool Capabilities::shareAPI() const
}
}
bool Capabilities::shareEmailPasswordEnabled() const
{
return _capabilities["files_sharing"].toMap()["sharebymail"].toMap()["password"].toMap()["enabled"].toBool();
}
bool Capabilities::shareEmailPasswordEnforced() const
{
return _capabilities["files_sharing"].toMap()["sharebymail"].toMap()["password"].toMap()["enforced"].toBool();
}
bool Capabilities::sharePublicLink() const
{
if (_capabilities["files_sharing"].toMap().contains("public")) {

Просмотреть файл

@ -46,6 +46,8 @@ public:
Capabilities(const QVariantMap &capabilities);
bool shareAPI() const;
bool shareEmailPasswordEnabled() const;
bool shareEmailPasswordEnforced() const;
bool sharePublicLink() const;
bool sharePublicLinkAllowUpload() const;
bool sharePublicLinkSupportsUploadOnly() const;