Utils

The utils package contains additional functionality which is somehow related to what a user of SynqClient typically needs to do and which is not strictly about remote file access or synchronization. In particular, the followiung utilities are included:

NextCloudLoginFlow

When working with NextCloud, a user needs to authenticate, usually providing a username and a password. In this regard, NextCloud behaves like a normal WebDAV server. However, besides using the user’s genuine password, NextCloud also allows to use app specific passwords. This means: The user can - for each app they want to be able to communicate with NextCloud on their behalf - create a specific password. The advantage is, that it is sufficient to revoke this (and only this) password if it is compromised (e.g. if the device on which the app is used has been lost or stolen).

On the other side, while possible, it is cumbersome for a user to manually generate app-specific passwords manually. To aid this, NextCloud implements a Login Flow. This flow allows an app to request the NextCloud server to create a new app-specific password for the user and return the generated password.

class NextCloudLoginFlow : public QObject

Implement the NextCloud login flow.

This class implements the NextCloud login flow. The usage is quite simple:

  • Create an instance of the class.

  • Configure it appropriately.

  • Setup signal/slot connections.

  • And finally: Start the flow.

Here is a minimal example:

auto flow = new SynqClient::NextCloudLoginFlow(this);
flow->setNetworkAccessManager(this->nam);
flow->setUserAgent("My Cool App");
if (flow->startLoginFlow(QUrl("http://nextcloud.example.com"))) {
    connect(flow, &SynqClient::NextCloudLoginFlow::receivedLoginUrl,
            [=](const QUrl &url) {
                // Open the URL in the user configured browser:
                QDesktopServices::openUrl(url);
            });
    connect(flow, &SynqClient::NextCloudLoginFlow::receivedLogin,
            [=](const QString &username, const QString &password, const QUrl &server) {
                this->username = username;
                this->password = password;
                this->server = server;
            });
    connect(flow, &SyncClient::NextCloudLoginFlow::finished,
            flow, &QObject::deleteLater);
}

Note

It is important to connect to the receivedLogin() signal and open the URL - either in the default browser (e.g. on Desktop systems) or in an embedded HTML view (on mobiles). The user needs to login and explicitly grant access to the app.

Note

Make sure you set a proper userAgent(). The user agent string will be shown to the user in the web page where they are asked to grant access.

Note

The flow does not time out. This means if the user either does not grant access or simply never finished the flow, the finished() signal will never be emitted. Hence, either use an additional timer or - better - provide a user interface where the user can manually enter the username and password to be used.

Public Functions

explicit NextCloudLoginFlow(QObject *parent = nullptr)

Constructor.

Creates a new NextCloudLoginFlow object which is owned by the parent object.

~NextCloudLoginFlow() override

Destructor.

bool flowRunning() const

Indicates if the login flow is currently running.

This returns true if this object is currently running a login flow or false otherwise.

QNetworkAccessManager *networkAccessManager() const

The network access manager used by the flow.

void setNetworkAccessManager(QNetworkAccessManager *networkAccessManager)

Set the networkAccessManager to be used by the flow.

This sets the network access manager that shall be used by the login flow.

Note

Setting this while a flow is already running is undefined behaviour.

QString userAgent() const

The user agent used when communicating with the NextCloud server.

This holds the user agent used when communicating with the NextCloud server. The default value is “SynqClient”. Set it to something meaningful (ideally the name of your app) because the user will be displayed this name in the web interface.

void setUserAgent(const QString &userAgent)

Set the userAgent to be used when communicating with the NextCloud server.

Q_INVOKABLE bool startLoginFlow (const QUrl &url)

Start a new login flow against the url.

Calling this will start a new login flow against the NextCloud server listening on the specified URL. This basically sends a request against the specific login flow endpoint of the server and immediately returns.

If sending the request was successful (and also all other prerequisites are fulfilled) this method returns true and the flowRunning() property will change to true.

In case of an error, false is returned. Error causes might be:

  • No network manager is set.

  • The network request could not be created.

  • This object already runs a login flow.

Signals

void finished()

The login flow has finished.

This signal is emitted once to indicate that the login flow has finished. This signal is emitted regardless on whether the flow succeeded or not.

void flowRunningChanged()

The flowRunning property changed.

void receivedLoginUrl(const QUrl &url)

The login url has been received.

This signal is emitted during the flow. It carries the login URL that the user has to visit in a browser. On that page, the user will need to log in and grant access to the app to continue the flow.

Client code should listen to this signal and open a browser so the flow can continue:

connect(flow, &SynqClient::NextCloudLoginFlow::receivedLoginUrl, [=](const QUrl &url) {
    QDesktopServices::openUrl(url);
});
void receivedLogin(const QString &username, const QString &password, const QUrl &server)

The login credentials have been received.

This signal is emitted once to indicate that the user granted access and we received the needed username, app-specific password as well as the server URL to be used to talk to the NextCloud server.

Protected Functions

explicit NextCloudLoginFlow(NextCloudLoginFlowPrivate *d, QObject *parent = nullptr)

Constructor.