Skip to content

Commit 3f639aa

Browse files
committed
Token auth
1 parent 17d37b0 commit 3f639aa

File tree

8 files changed

+142
-80
lines changed

8 files changed

+142
-80
lines changed

src/cmd/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# Currently disabled until we implemented app token support
2-
return()
31
add_executable(cmd
42
cmd.cpp
3+
tokencredentials.cpp
4+
tokencredentials.h
55
)
66
set_target_properties(cmd PROPERTIES OUTPUT_NAME "${APPLICATION_EXECUTABLE}cmd")
77
ecm_mark_nongui_executable(cmd)

src/cmd/cmd.cpp

Lines changed: 28 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
*/
1616

1717
#include "account.h"
18+
#include "cmd/tokencredentials.h"
1819
#include "common/syncjournaldb.h"
1920
#include "common/version.h"
2021
#include "configfile.h" // ONLY ACCESS THE STATIC FUNCTIONS!
21-
#include "httpcredentialstext.h"
2222
#include "libsync/logger.h"
2323
#include "libsync/theme.h"
2424
#include "networkjobs/checkserverjobfactory.h"
@@ -50,10 +50,8 @@ struct CmdOptions
5050
QUrl target_url;
5151
QUrl server_url;
5252

53-
QString remoteFolder;
54-
QString config_directory;
55-
QString user;
56-
QString password;
53+
QByteArray username;
54+
QByteArray token;
5755
QString proxy;
5856
bool silent = false;
5957
bool trustSSL = false;
@@ -76,7 +74,6 @@ struct SyncCTX
7674
CmdOptions options;
7775
bool promptRemoveAllFiles;
7876
AccountPtr account;
79-
QString user;
8077
};
8178

8279
/* If the selective sync list is different from before, we need to disable the read from db
@@ -135,8 +132,7 @@ void sync(const SyncCTX &ctx)
135132
}
136133

137134
SyncOptions opt{QSharedPointer<Vfs>(VfsPluginManager::instance().createVfsFromPlugin(Vfs::Off).release())};
138-
auto engine = new SyncEngine(
139-
ctx.account, ctx.options.target_url, ctx.options.source_dir, ctx.options.remoteFolder, db);
135+
auto engine = new SyncEngine(ctx.account, ctx.options.target_url, ctx.options.source_dir, {}, db);
140136
engine->setSyncOptions(opt);
141137
engine->setParent(db);
142138

@@ -192,18 +188,6 @@ void setupCredentials(SyncCTX &ctx)
192188
// 2. From options
193189
// 3. From prompt (if interactive)
194190

195-
const auto &url = ctx.options.target_url;
196-
ctx.user = url.userName();
197-
QString password = url.password();
198-
199-
if (!ctx.options.user.isEmpty()) {
200-
ctx.user = ctx.options.user;
201-
}
202-
203-
if (!ctx.options.password.isEmpty()) {
204-
password = ctx.options.password;
205-
}
206-
207191
if (!ctx.options.proxy.isNull()) {
208192
QString host;
209193
uint32_t port = 0;
@@ -243,7 +227,7 @@ void setupCredentials(SyncCTX &ctx)
243227
f.close();
244228
}
245229

246-
ctx.account->setCredentials(HttpCredentialsText::create(ctx.options.interactive, ctx.user, password));
230+
ctx.account->setCredentials(new TokenCredentials(std::move(ctx.options.username), std::move(ctx.options.token)));
247231
if (ctx.options.trustSSL) {
248232
QObject::connect(ctx.account->accessManager(), &QNetworkAccessManager::sslErrors, qApp,
249233
[](QNetworkReply *reply, const QList<QSslError> &errors) { reply->ignoreSslErrors(errors); });
@@ -277,16 +261,16 @@ CmdOptions parseOptions(const QStringList &app_args)
277261
return option;
278262
};
279263

264+
auto serverOption = addOption({{QStringLiteral("server")}, QStringLiteral("The URL for the server"), QStringLiteral("url")});
265+
auto userOption = addOption({{QStringLiteral("u"), QStringLiteral("user")}, QStringLiteral("Username"), QStringLiteral("name")});
266+
auto tokenOption = addOption({{QStringLiteral("t"), QStringLiteral("token")}, QStringLiteral("Authentication token"), QStringLiteral("token")});
267+
280268
auto silentOption = addOption({ { QStringLiteral("s"), QStringLiteral("silent") }, QStringLiteral("Don't be so verbose.") });
281269
auto httpproxyOption = addOption({ { QStringLiteral("httpproxy") }, QStringLiteral("Specify a http proxy to use."), QStringLiteral("http://server:port") });
282270
auto trustOption = addOption({ { QStringLiteral("trust") }, QStringLiteral("Trust the SSL certification") });
283271
auto excludeOption = addOption({ { QStringLiteral("exclude") }, QStringLiteral("Path to an exclude list [file]"), QStringLiteral("file") });
284272
auto unsyncedfoldersOption = addOption({ { QStringLiteral("unsyncedfolders") }, QStringLiteral("File containing the list of unsynced remote folders (selective sync)"), QStringLiteral("file") });
285273

286-
auto serverOption = addOption({{QStringLiteral("server")}, QStringLiteral("Use [url] as the location of the server."), QStringLiteral("url")});
287-
auto userOption = addOption({ { QStringLiteral("u"), QStringLiteral("user") }, QStringLiteral("Use [name] as the login name"), QStringLiteral("name") });
288-
auto passwordOption = addOption({{QStringLiteral("p"), QStringLiteral("password")}, QStringLiteral("Use [pass] as password"), QStringLiteral("password")});
289-
290274
auto nonInterActiveOption = addOption({ { QStringLiteral("non-interactive") }, QStringLiteral("Do not block execution with interaction") });
291275
auto maxRetriesOption = addOption({ { QStringLiteral("max-sync-retries") }, QStringLiteral("Retries maximum n times (default to 3)"), QStringLiteral("n") });
292276
auto uploadLimitOption = addOption({ { QStringLiteral("uplimit") }, QStringLiteral("Limit the upload speed of files to n KB/s"), QStringLiteral("n") });
@@ -302,8 +286,7 @@ CmdOptions parseOptions(const QStringList &app_args)
302286
parser.addVersionOption();
303287

304288
parser.addPositionalArgument(QStringLiteral("source_dir"), QStringLiteral("The source dir"));
305-
parser.addPositionalArgument(QStringLiteral("server_url"), QStringLiteral("The URL to the server"));
306-
parser.addPositionalArgument(QStringLiteral("remote_folder"), QStringLiteral("A remote folder"));
289+
parser.addPositionalArgument(QStringLiteral("space_url"), QStringLiteral("The URL to the space"));
307290

308291
parser.process(app_args);
309292

@@ -313,11 +296,11 @@ CmdOptions parseOptions(const QStringList &app_args)
313296
parser.showHelp(EXIT_FAILURE);
314297
}
315298

316-
options.source_dir = [arg = args[0]] {
299+
options.source_dir = [&parser, arg = args[0]] {
317300
const QFileInfo fi(arg);
318301
if (!fi.exists()) {
319302
qCritical() << "Source dir" << arg << "does not exist.";
320-
exit(EXIT_FAILURE);
303+
parser.showHelp(EXIT_FAILURE);
321304
}
322305
QString sourceDir = fi.absoluteFilePath();
323306
if (!sourceDir.endsWith(QLatin1Char('/'))) {
@@ -326,9 +309,6 @@ CmdOptions parseOptions(const QStringList &app_args)
326309
return sourceDir;
327310
}();
328311
options.target_url = QUrl::fromUserInput(args[1]);
329-
if (args.size() == 3) {
330-
options.remoteFolder = args[2];
331-
}
332312

333313
if (parser.isSet(httpproxyOption)) {
334314
options.proxy = parser.value(httpproxyOption);
@@ -345,13 +325,20 @@ CmdOptions parseOptions(const QStringList &app_args)
345325
if (parser.isSet(serverOption)) {
346326
options.server_url = QUrl::fromUserInput(parser.value(serverOption));
347327
} else {
348-
options.server_url = options.target_url;
328+
qCritical() << "Server not set";
329+
parser.showHelp(EXIT_FAILURE);
349330
}
350-
if (parser.isSet(userOption)) {
351-
options.user = parser.value(userOption);
331+
if (parser.isSet(tokenOption)) {
332+
options.token = parser.value(tokenOption).toUtf8();
333+
} else {
334+
qCritical() << "Token not set";
335+
parser.showHelp(EXIT_FAILURE);
352336
}
353-
if (parser.isSet(passwordOption)) {
354-
options.password = parser.value(passwordOption);
337+
if (parser.isSet(userOption)) {
338+
options.username = parser.value(userOption).toUtf8();
339+
} else {
340+
qCritical() << "Username not set";
341+
parser.showHelp(EXIT_FAILURE);
355342
}
356343
if (parser.isSet(excludeOption)) {
357344
options.exclude = parser.value(excludeOption);
@@ -417,16 +404,8 @@ int main(int argc, char **argv)
417404
ctx.options.server_url = ctx.options.server_url.adjusted(QUrl::RemoveUserInfo);
418405
ctx.options.target_url = ctx.options.target_url.adjusted(QUrl::RemoveUserInfo);
419406

420-
const QUrl baseUrl = [&ctx] {
421-
auto tmp = ctx.options.server_url;
422-
// Find the url leading to the dav root
423-
QStringList splitted = tmp.path().split(ctx.account->davPath());
424-
tmp.setPath(splitted.value(0));
425-
return tmp;
426-
}();
427-
428407

429-
ctx.account->setUrl(baseUrl);
408+
ctx.account->setUrl(ctx.options.server_url);
430409

431410
auto *checkServerJob = CheckServerJobFactory(ctx.account->accessManager()).startJob(ctx.account->url(), qApp);
432411

@@ -460,24 +439,9 @@ int main(int argc, char **argv)
460439
exit(EXIT_FAILURE);
461440
}
462441

463-
auto userJob = new JsonApiJob(ctx.account, QStringLiteral("ocs/v1.php/cloud/user"), {}, {}, nullptr);
464-
QObject::connect(userJob, &JsonApiJob::finishedSignal, qApp, [userJob, ctx = ctx]() mutable {
465-
const QJsonObject data = userJob->data().value(QStringLiteral("ocs")).toObject().value(QStringLiteral("data")).toObject();
466-
ctx.account->setDavUser(data.value(QStringLiteral("id")).toString());
467-
ctx.account->setDavDisplayName(data.value(QStringLiteral("display-name")).toString());
468-
469-
if (ctx.options.server_url == ctx.options.target_url) {
470-
// guess dav path
471-
if (!ctx.options.target_url.path().contains(ctx.account->davPath())) {
472-
ctx.options.target_url = OCC::Utility::concatUrlPath(ctx.options.target_url, ctx.account->davPath());
473-
}
474-
}
475-
476-
// much lower age than the default since this utility is usually made to be run right after a change in the tests
477-
SyncEngine::minimumFileAgeForUpload = std::chrono::seconds(0);
478-
sync(ctx);
479-
});
480-
userJob->start();
442+
// much lower age than the default since this utility is usually made to be run right after a change in the tests
443+
SyncEngine::minimumFileAgeForUpload = std::chrono::seconds(0);
444+
sync(ctx);
481445
});
482446
capabilitiesJob->start();
483447
} else {

src/cmd/tokencredentials.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright (C) by Hannah von Reth <h.vonreth@opencloud.eu>
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but
10+
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* for more details.
13+
*/
14+
15+
#include "tokencredentials.h"
16+
17+
#include "creds/httpcredentials.h"
18+
#include "libsync/accessmanager.h"
19+
20+
using namespace OCC;
21+
22+
class OCC::TokensAccessManager : public AccessManager
23+
{
24+
Q_OBJECT
25+
public:
26+
TokensAccessManager(QByteArray &&username, QByteArray &&token, QObject *parent)
27+
: AccessManager(parent)
28+
, _token("Basic " + QByteArray(username + ':' + token).toBase64())
29+
{
30+
}
31+
32+
protected:
33+
QNetworkReply *createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData) override
34+
{
35+
QNetworkRequest req(request);
36+
if (!req.attribute(HttpCredentials::DontAddCredentialsAttribute).toBool()) {
37+
req.setRawHeader("Authorization", _token);
38+
}
39+
return AccessManager::createRequest(op, req, outgoingData);
40+
}
41+
42+
private:
43+
QByteArray _token;
44+
};
45+
46+
TokenCredentials::TokenCredentials(QByteArray &&username, QByteArray &&token)
47+
: _accessManager(new TokensAccessManager(std::move(username), std::move(token), this))
48+
{
49+
}
50+
51+
AccessManager *TokenCredentials::createAM() const
52+
{
53+
return _accessManager;
54+
}
55+
56+
bool TokenCredentials::ready() const
57+
{
58+
return true;
59+
}
60+
61+
void TokenCredentials::fetchFromKeychain() { }
62+
63+
void TokenCredentials::restartOauth() { }
64+
65+
void TokenCredentials::persist() { }
66+
67+
void TokenCredentials::invalidateToken() { }
68+
69+
void TokenCredentials::forgetSensitiveData() { }
70+
71+
72+
#include "tokencredentials.moc"

src/cmd/tokencredentials.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (C) by Hannah von Reth <h.vonreth@opencloud.eu>
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful, but
10+
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* for more details.
13+
*/
14+
15+
#pragma once
16+
17+
#include "libsync/creds/abstractcredentials.h"
18+
19+
namespace OCC {
20+
class TokensAccessManager;
21+
22+
class TokenCredentials : public AbstractCredentials
23+
{
24+
private:
25+
Q_OBJECT
26+
public:
27+
TokenCredentials(QByteArray &&username, QByteArray &&token);
28+
29+
AccessManager *createAM() const override;
30+
bool ready() const override;
31+
void fetchFromKeychain() override;
32+
void restartOauth() override;
33+
void persist() override;
34+
void invalidateToken() override;
35+
void forgetSensitiveData() override;
36+
37+
private:
38+
TokensAccessManager *_accessManager;
39+
};
40+
}

src/libsync/creds/abstractcredentials.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ class OPENCLOUD_SYNC_EXPORT AbstractCredentials : public QObject
4444
*/
4545
virtual void setAccount(Account *account);
4646

47-
virtual QString authType() const = 0;
4847
virtual AccessManager *createAM() const = 0;
4948

5049
/** Whether there are credentials that can be used for a connection attempt. */

src/libsync/creds/httpcredentials.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,6 @@ HttpCredentials::HttpCredentials(const QString &accessToken)
8080
{
8181
}
8282

83-
QString HttpCredentials::authType() const
84-
{
85-
return QStringLiteral("http");
86-
}
87-
88-
void HttpCredentials::setAccount(Account *account)
89-
{
90-
AbstractCredentials::setAccount(account);
91-
}
92-
9383
AccessManager *HttpCredentials::createAM() const
9484
{
9585
AccessManager *am = new HttpCredentialsAccessManager(this);

src/libsync/creds/httpcredentials.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ class OPENCLOUD_SYNC_EXPORT HttpCredentials : public AbstractCredentials
5353

5454
explicit HttpCredentials(const QString &accessToken);
5555

56-
QString authType() const override;
5756
AccessManager *createAM() const override;
5857
bool ready() const override;
5958
void fetchFromKeychain() override;
@@ -67,7 +66,6 @@ class OPENCLOUD_SYNC_EXPORT HttpCredentials : public AbstractCredentials
6766
*/
6867
bool refreshAccessToken();
6968

70-
void setAccount(Account *account) override;
7169

7270
protected:
7371
HttpCredentials() = default;

test/testutils/syncenginetestutils.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,6 @@ class FakeCredentials : public OCC::AbstractCredentials
508508
{
509509
}
510510

511-
QString authType() const override { return QStringLiteral("test"); }
512511
OCC::AccessManager *createAM() const override { return _am; }
513512
bool ready() const override { return true; }
514513
void fetchFromKeychain() override { }

0 commit comments

Comments
 (0)