Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/public links #4175

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 5 additions & 1 deletion src/gui/accountmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,11 @@ void AccountManager::saveAccountHelper(Account *account, QSettings &settings, bo
{
qCDebug(lcAccountManager) << "Saving settings to" << settings.fileName();
settings.setValue(QLatin1String(versionC), maxAccountVersion);
settings.setValue(QLatin1String(urlC), account->_url.toString());
if (account->isPublicShareLink()) {
settings.setValue(QLatin1String(urlC), account->publicShareLinkUrl().toString());
} else {
settings.setValue(QLatin1String(urlC), account->_url.toString());
}
settings.setValue(QLatin1String(davUserC), account->_davUser);
settings.setValue(QLatin1String(displayNameC), account->davDisplayName());
settings.setValue(QLatin1String(serverVersionC), account->_serverVersion);
Expand Down
7 changes: 7 additions & 0 deletions src/gui/connectionvalidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* for more details.
*/

#include <QJsonDocument>

Check failure on line 15 in src/gui/connectionvalidator.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/connectionvalidator.cpp:15:10 [clang-diagnostic-error]

'QJsonDocument' file not found
#include <QJsonObject>
#include <QJsonArray>
#include <QLoggingCategory>
Expand Down Expand Up @@ -271,6 +271,13 @@
_account->fetchDirectEditors(directEditingURL, directEditingETag);

checkServerTermsOfService();

if (_account->isPublicShareLink()) {
slotUserFetched(nullptr);
return;
}

fetchUser();
}

void ConnectionValidator::fetchUser()
Expand Down
25 changes: 24 additions & 1 deletion src/gui/owncloudsetupwizard.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*

Check notice on line 1 in src/gui/owncloudsetupwizard.cpp

View workflow job for this annotation

GitHub Actions / build

Run clang-format on src/gui/owncloudsetupwizard.cpp

File src/gui/owncloudsetupwizard.cpp does not conform to Custom style guidelines. (lines 354, 355)
* Copyright (C) by Klaas Freitag <[email protected]>
* Copyright (C) by Krzesimir Nowak <[email protected]>
*
Expand All @@ -13,7 +13,7 @@
* for more details.
*/

#include <QAbstractButton>

Check failure on line 16 in src/gui/owncloudsetupwizard.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/owncloudsetupwizard.cpp:16:10 [clang-diagnostic-error]

'QAbstractButton' file not found
#include <QtCore>
#include <QProcess>
#include <QMessageBox>
Expand All @@ -34,6 +34,7 @@
#include "sslerrordialog.h"
#include "wizard/owncloudwizard.h"
#include "wizard/owncloudwizardcommon.h"
#include "account.h"

Check warning on line 37 in src/gui/owncloudsetupwizard.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/owncloudsetupwizard.cpp:37:1 [readability-duplicate-include]

duplicate include

#include "creds/credentialsfactory.h"
#include "creds/abstractcredentials.h"
Expand Down Expand Up @@ -290,7 +291,11 @@
qCInfo(lcWizard) << " was redirected to" << url.toString();
}

slotDetermineAuthType();
if (_ocWizard->account()->isPublicShareLink()) {
_ocWizard->setAuthType(DetermineAuthTypeJob::Basic);
} else {
slotDetermineAuthType();
}
}

void OwncloudSetupWizard::slotNoServerFound(QNetworkReply *reply)
Expand Down Expand Up @@ -341,6 +346,19 @@
_ocWizard->account()->setCredentials(creds);
}

if (_ocWizard->account()->isPublicShareLink()) {
_ocWizard->account()->setDavUser(creds->user());
_ocWizard->account()->setDavDisplayName(creds->user());

_ocWizard->setField(QLatin1String("OCUrl"), url);
_ocWizard->appendToConfigurationLog(tr("Trying to connect to %1 at %2 …")
.arg(Theme::instance()->appNameGUI())
.arg(url));

testOwnCloudConnect();
return;
}

const auto fetchUserNameJob = new JsonApiJob(_ocWizard->account()->sharedFromThis(), QStringLiteral("/ocs/v1.php/cloud/user"));
connect(fetchUserNameJob, &JsonApiJob::jsonReceived, this, [this, url](const QJsonDocument &json, int statusCode) {
if (statusCode != 100) {
Expand Down Expand Up @@ -731,6 +749,11 @@
auto manager = AccountManager::instance();

auto newState = manager->addAccount(newAccount);

if (newAccount->isPublicShareLink()) {
qCInfo(lcWizard()) << "seeting up public share link account";
}

manager->saveAccount(newAccount.data());
return newState;
}
Expand Down
5 changes: 4 additions & 1 deletion src/gui/tray/UserLine.qml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ AbstractButton {
}

MenuItem {
visible: model.canLogout
height: visible ? implicitHeight : 0
mgallien marked this conversation as resolved.
Show resolved Hide resolved
width: parent.width
text: model.isConnected ? qsTr("Log out") : qsTr("Log in")
font.pixelSize: Style.topLinePixelSize
hoverEnabled: true
Expand All @@ -175,7 +178,7 @@ AbstractButton {

MenuItem {
id: removeAccountButton
text: qsTr("Remove account")
text: model.removeAccountText
font.pixelSize: Style.topLinePixelSize
hoverEnabled: true
onClicked: {
Expand Down
103 changes: 71 additions & 32 deletions src/gui/tray/usermodel.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "notificationhandler.h"

Check notice on line 1 in src/gui/tray/usermodel.cpp

View workflow job for this annotation

GitHub Actions / build

Run clang-format on src/gui/tray/usermodel.cpp

File src/gui/tray/usermodel.cpp does not conform to Custom style guidelines. (lines 1018, 1533)
#include "usermodel.h"
#include "common/filesystembase.h"

Expand Down Expand Up @@ -884,7 +884,17 @@
return _trayFolderInfos;
}

bool User::canLogout() const

Check warning on line 887 in src/gui/tray/usermodel.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/tray/usermodel.cpp:887:12 [modernize-use-trailing-return-type]

use a trailing return type for this function
{
return !isPublicShareLink();
}

bool User::isPublicShareLink() const

Check warning on line 892 in src/gui/tray/usermodel.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/tray/usermodel.cpp:892:12 [modernize-use-trailing-return-type]

use a trailing return type for this function
{
return _account->account()->isPublicShareLink();
}

void User::slotItemCompleted(const QString &folder, const SyncFileItemPtr &item)

Check warning on line 897 in src/gui/tray/usermodel.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/tray/usermodel.cpp:897:12 [readability-convert-member-functions-to-static]

method 'slotItemCompleted' can be made static

Check warning on line 897 in src/gui/tray/usermodel.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/tray/usermodel.cpp:897:30 [bugprone-easily-swappable-parameters]

2 adjacent parameters of 'slotItemCompleted' of similar type ('const int &') are easily swapped by mistake
{
auto folderInstance = FolderMan::instance()->folder(folder);

Expand Down Expand Up @@ -988,17 +998,27 @@

QString User::name() const
{
if (isPublicShareLink()) {
return tr("Public Share Link");
}

return _account->account()->prettyName();
}

QString User::server(bool shortened) const
{
QString serverUrl = _account->account()->url().toString();
auto serverUrl = _account->account()->url();

if (isPublicShareLink()) {
serverUrl.setUserName({});
}
QString stringServerUrl = serverUrl.toString();

Check warning on line 1015 in src/gui/tray/usermodel.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/tray/usermodel.cpp:1015:13 [cppcoreguidelines-init-variables]

variable 'stringServerUrl' is not initialized
if (shortened) {
serverUrl.replace(QLatin1String("https://"), QLatin1String(""));
serverUrl.replace(QLatin1String("http://"), QLatin1String(""));
stringServerUrl.replace(QLatin1String("https://"), QLatin1String(""));
stringServerUrl.replace(QLatin1String("http://"), QLatin1String(""));

}
return serverUrl;
return stringServerUrl;
}

UserStatus::OnlineStatus User::status() const
Expand Down Expand Up @@ -1509,34 +1529,51 @@

QVariant UserModel::data(const QModelIndex &index, int role) const
{
if (index.row() < 0 || index.row() >= _users.count()) {
return QVariant();
}

if (role == NameRole) {
return _users[index.row()]->name();
} else if (role == ServerRole) {
return _users[index.row()]->server();
} else if (role == ServerHasUserStatusRole) {
return _users[index.row()]->serverHasUserStatus();
} else if (role == StatusIconRole) {
return _users[index.row()]->statusIcon();
} else if (role == StatusEmojiRole) {
return _users[index.row()]->statusEmoji();
} else if (role == StatusMessageRole) {
return _users[index.row()]->statusMessage();
} else if (role == DesktopNotificationsAllowedRole) {
return _users[index.row()]->isDesktopNotificationsAllowed();
} else if (role == AvatarRole) {
return _users[index.row()]->avatarUrl();
} else if (role == IsCurrentUserRole) {
return _users[index.row()]->isCurrentUser();
} else if (role == IsConnectedRole) {
return _users[index.row()]->isConnected();
} else if (role == IdRole) {
return index.row();
}
return QVariant();
auto result = QVariant{};
switch (role)
{
case NameRole:

Check warning on line 1535 in src/gui/tray/usermodel.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/tray/usermodel.cpp:1535:5 [bugprone-branch-clone]

switch has 13 consecutive identical branches
result = _users[index.row()]->name();
break;
case ServerRole:
result = _users[index.row()]->server();
break;
case ServerHasUserStatusRole:
result = _users[index.row()]->serverHasUserStatus();
break;
case StatusIconRole:
result = _users[index.row()]->statusIcon();
break;
case StatusEmojiRole:
result = _users[index.row()]->statusEmoji();
break;
case StatusMessageRole:
result = _users[index.row()]->statusMessage();
break;
case DesktopNotificationsAllowedRole:
result = _users[index.row()]->isDesktopNotificationsAllowed();
break;
case AvatarRole:
result = _users[index.row()]->avatarUrl();
break;
case IsCurrentUserRole:
result = _users[index.row()]->isCurrentUser();
break;
case IsConnectedRole:
result = _users[index.row()]->isConnected();
break;
case IdRole:
result = index.row();
break;
case CanLogoutRole:
result = _users[index.row()]->canLogout();
break;
case RemoveAccountTextRole:
result = _users[index.row()]->isPublicShareLink() ? tr("Leave share") : tr("Remove account");
break;
}

return result;
}

QHash<int, QByteArray> UserModel::roleNames() const
Expand All @@ -1545,6 +1582,8 @@
roles[NameRole] = "name";
roles[ServerRole] = "server";
roles[ServerHasUserStatusRole] = "serverHasUserStatus";
roles[CanLogoutRole] = "canLogout";
roles[RemoveAccountTextRole] = "removeAccountText";
roles[StatusIconRole] = "statusIcon";
roles[StatusEmojiRole] = "statusEmoji";
roles[StatusMessageRole] = "statusMessage";
Expand Down
7 changes: 6 additions & 1 deletion src/gui/tray/usermodel.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef USERMODEL_H
#define USERMODEL_H

#include <QAbstractListModel>

Check failure on line 4 in src/gui/tray/usermodel.h

View workflow job for this annotation

GitHub Actions / build

src/gui/tray/usermodel.h:4:10 [clang-diagnostic-error]

'QAbstractListModel' file not found
#include <QImage>
#include <QDateTime>
#include <QStringList>
Expand Down Expand Up @@ -63,6 +63,7 @@
Q_PROPERTY(bool isConnected READ isConnected NOTIFY accountStateChanged)
Q_PROPERTY(UnifiedSearchResultsListModel* unifiedSearchResultsListModel READ getUnifiedSearchResultsListModel CONSTANT)
Q_PROPERTY(QVariantList groupFolders READ groupFolders NOTIFY groupFoldersChanged)
Q_PROPERTY(bool canLogout READ canLogout CONSTANT)

public:
User(AccountStatePtr &account, const bool &isCurrent = false, QObject *parent = nullptr);
Expand Down Expand Up @@ -104,6 +105,8 @@
[[nodiscard]] QString statusEmoji() const;
void processCompletedSyncItem(const Folder *folder, const SyncFileItemPtr &item);
[[nodiscard]] const QVariantList &groupFolders() const;
[[nodiscard]] bool canLogout() const;
[[nodiscard]] bool isPublicShareLink() const;

signals:
void nameChanged();
Expand Down Expand Up @@ -236,14 +239,16 @@
NameRole = Qt::UserRole + 1,
ServerRole,
ServerHasUserStatusRole,
CanLogoutRole,
RemoveAccountTextRole,
StatusIconRole,
StatusEmojiRole,
StatusMessageRole,
DesktopNotificationsAllowedRole,
AvatarRole,
IsCurrentUserRole,
IsConnectedRole,
IdRole
IdRole,
};

[[nodiscard]] AccountAppList appList() const;
Expand Down
4 changes: 2 additions & 2 deletions src/gui/userinfo.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*

Check notice on line 1 in src/gui/userinfo.cpp

View workflow job for this annotation

GitHub Actions / build

Run clang-format on src/gui/userinfo.cpp

File src/gui/userinfo.cpp does not conform to Custom style guidelines. (lines 143)
* Copyright (C) by Daniel Molkentin <[email protected]>
* Copyright (C) by Michael Schuster <[email protected]>
*
Expand Down Expand Up @@ -76,7 +76,7 @@

bool UserInfo::canGetInfo() const
{
if (!_accountState || !_active) {
if (!_accountState || !_active || !_accountState->account() || _accountState->account()->isPublicShareLink()) {
return false;
}
AccountPtr account = _accountState->account();
Expand Down Expand Up @@ -140,8 +140,8 @@
_jobRestartTimer.start(defaultIntervalT);
_lastInfoReceived = QDateTime::currentDateTime();

if(_fetchAvatarImage) {
if(_fetchAvatarImage && !account->isPublicShareLink()) {
auto *job = new AvatarJob(account, account->davUser(), 128, this);

Check warning on line 144 in src/gui/userinfo.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/userinfo.cpp:144:15 [cppcoreguidelines-init-variables]

variable 'job' is not initialized
job->setTimeout(20 * 1000);
QObject::connect(job, &AvatarJob::avatarPixmap, this, &UserInfo::slotAvatarImage);
job->start();
Expand Down
5 changes: 5 additions & 0 deletions src/gui/wizard/owncloudadvancedsetuppage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* for more details.
*/

#include <QDir>

Check failure on line 16 in src/gui/wizard/owncloudadvancedsetuppage.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/wizard/owncloudadvancedsetuppage.cpp:16:10 [clang-diagnostic-error]

'QDir' file not found
#include <QFileDialog>
#include <QUrl>
#include <QTimer>
Expand Down Expand Up @@ -226,6 +226,11 @@
if (Theme::isHidpi()) {
avatarSize *= 2;
}

if (account->isPublicShareLink()) {
return;
}

const auto avatarJob = new AvatarJob(account, account->davUser(), avatarSize, this);
avatarJob->setTimeout(20 * 1000);
QObject::connect(avatarJob, &AvatarJob::avatarPixmap, this, [this](const QImage &avatarImage) {
Expand Down
14 changes: 9 additions & 5 deletions src/gui/wizard/owncloudhttpcredspage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* for more details.
*/

#include "QProgressIndicator.h"

Check failure on line 16 in src/gui/wizard/owncloudhttpcredspage.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/wizard/owncloudhttpcredspage.cpp:16:10 [clang-diagnostic-error]

'QProgressIndicator.h' file not found

#include "creds/httpcredentialsgui.h"
#include "theme.h"
Expand Down Expand Up @@ -104,11 +104,15 @@
const QString user = url.userName();
const QString password = url.password();

_ui.leUsername->setText(user);
_ui.lePassword->setText(password);

if (!user.isEmpty()) {
_ui.leUsername->setText(user);
}
if (!password.isEmpty()) {
_ui.lePassword->setText(password);
_ui.errorLabel->setVisible(false);
startSpinner();

emit completeChanged();
emit connectToOCUrl(field("OCUrl").toString().simplified());
}
}
_ui.tokenLabel->setText(HttpCredentialsGui::requestAppPasswordText(ocWizard->account().data()));
Expand All @@ -124,7 +128,7 @@

bool OwncloudHttpCredsPage::validatePage()
{
if (_ui.leUsername->text().isEmpty() || _ui.lePassword->text().isEmpty()) {
if (_ui.leUsername->text().isEmpty()) {
return false;
}

Expand Down
24 changes: 22 additions & 2 deletions src/libsync/account.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,11 @@ QString Account::davPath() const

QString Account::davPathRoot() const
{
return davPathBase() + QLatin1Char('/') + davUser();
if (_isPublicLink) {
return QStringLiteral("/public.php/webdav");
} else {
return davPathBase() + QLatin1Char('/') + davUser();
}
}

void Account::setSharedThis(AccountPtr sharedThis)
Expand Down Expand Up @@ -526,10 +530,26 @@ void Account::setSslErrorHandler(AbstractSslErrorHandler *handler)

void Account::setUrl(const QUrl &url)
{
_url = url;
const QRegularExpression discoverPublicLinks(R"((http.://[^/]*).*/s/([^/]*))");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be nice to have plain http:// links work too (e.g. for local dev)

Suggested change
const QRegularExpression discoverPublicLinks(R"((http.://[^/]*).*/s/([^/]*))");
const QRegularExpression discoverPublicLinks(R"((https?://[^/]*).*/s/([^/]*))");

Copy link
Member

@camilasan camilasan Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps we could allow http only when NEXTCLOUD_DEV is set.

const auto isPublicLink = discoverPublicLinks.match(url.toString());
if (isPublicLink.hasMatch()) {
_url = QUrl::fromUserInput(isPublicLink.captured(1));
_url.setUserName(isPublicLink.captured(2));
setDavUser(isPublicLink.captured(2));
_isPublicLink = true;
_publicShareLinkUrl = url;
} else {
_url = url;
}

_userVisibleUrl = url;
}

QUrl Account::publicShareLinkUrl() const
{
return _publicShareLinkUrl;
}

void Account::setUserVisibleHost(const QString &host)
{
_userVisibleUrl.setHost(host);
Expand Down
8 changes: 8 additions & 0 deletions src/libsync/account.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ class OWNCLOUDSYNC_EXPORT Account : public QObject
/** Server url of the account */
void setUrl(const QUrl &url);
[[nodiscard]] QUrl url() const { return _url; }
[[nodiscard]] QUrl publicShareLinkUrl() const;

[[nodiscard]] bool isPublicShareLink() const
{
return _isPublicLink;
}

/// Adjusts _userVisibleUrl once the host to use is discovered.
void setUserVisibleHost(const QString &host);
Expand Down Expand Up @@ -501,6 +507,8 @@ private slots:
#endif
QMap<QString, QVariant> _settingsMap;
QUrl _url;
QUrl _publicShareLinkUrl;
bool _isPublicLink = false;

/** If url to use for any user-visible urls.
*
Expand Down
Loading
Loading