Line data Source code
1 : #pragma once
2 :
3 : #include <QByteArray>
4 : #include <QObject>
5 : #include <QUrl>
6 :
7 : class QNetworkAccessManager;
8 : class QNetworkReply;
9 : class QTimer;
10 :
11 : // T-158: Nextcloud Login Flow v2 authentication.
12 : // Opens the system browser for the user to log in, then polls
13 : // the Nextcloud server until an app password is granted.
14 : class NextcloudAuth : public QObject {
15 12 : Q_OBJECT
16 :
17 : public:
18 : explicit NextcloudAuth(QObject *parent = nullptr);
19 : ~NextcloudAuth() override;
20 :
21 : // Start the login flow for the given Nextcloud server URL.
22 : void startLogin(const QString &serverUrl);
23 : static bool isServerUrlAllowedForLogin(const QUrl &url);
24 :
25 : // Cancel an ongoing login flow.
26 : void cancel();
27 :
28 : // Test seam (same pattern as CalDavClient): replace the network access
29 : // manager; ownership transfers to this object.
30 : void setNetworkAccessManager(QNetworkAccessManager *nam);
31 :
32 : bool isPolling() const;
33 :
34 : static constexpr qint64 MaxResponseBytes = 64 * 1024;
35 : static constexpr int ReplyDeadlineMs = 15000;
36 :
37 : signals:
38 : void loginSuccess(const QString &server, const QString &loginName,
39 : const QString &appPassword);
40 : void loginFailed(const QString &error);
41 :
42 : private slots:
43 : void onInitReply();
44 : void onReplyReadyRead();
45 : void onReplyDeadline();
46 : void poll();
47 :
48 : private:
49 : enum class ReplyFailure { None, TooLarge, Timeout };
50 :
51 : void beginReply(QNetworkReply *reply);
52 : QByteArray finishReply(QNetworkReply *reply, QString *failureReason);
53 : void abortCurrentReply(ReplyFailure failure);
54 :
55 : QNetworkAccessManager *m_nam = nullptr;
56 : QTimer *m_pollTimer = nullptr;
57 : QTimer *m_replyDeadlineTimer = nullptr;
58 : QNetworkReply *m_currentReply = nullptr;
59 : QByteArray m_replyData;
60 : ReplyFailure m_replyFailure = ReplyFailure::None;
61 :
62 : QString m_pollEndpoint;
63 : QString m_pollToken;
64 : QString m_originalServerUrl; // T-611/SEC-10: For SSRF origin validation
65 : int m_pollCount = 0;
66 : static constexpr int MaxPollAttempts = 60; // 120 seconds at 2s interval
67 : };
|