diff options
Diffstat (limited to 'src/nxmaccessmanager.h')
| -rw-r--r-- | src/nxmaccessmanager.h | 221 |
1 files changed, 195 insertions, 26 deletions
diff --git a/src/nxmaccessmanager.h b/src/nxmaccessmanager.h index 1bdeae40..6a45d880 100644 --- a/src/nxmaccessmanager.h +++ b/src/nxmaccessmanager.h @@ -25,9 +25,182 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QTimer> #include <QNetworkReply> #include <QProgressDialog> +#include <QElapsedTimer> +#include <QDialogButtonBox> +#include <QWebSocket> #include <set> namespace MOBase { class IPluginGame; } +namespace Ui { class ValidationProgressDialog; } +class NXMAccessManager; + +class NexusSSOLogin +{ +public: + enum States + { + ConnectingToSSO, + WaitingForToken, + WaitingForBrowser, + Finished, + Timeout, + ClosedByRemote, + Cancelled, + Error + }; + + std::function<void (QString)> keyChanged; + std::function<void (States, QString)> stateChanged; + + static QString stateToString(States s, const QString& e); + + NexusSSOLogin(); + + void start(); + void cancel(); + + bool isActive() const; + +private: + QWebSocket m_socket; + QString m_guid; + bool m_keyReceived; + bool m_active; + QTimer m_timeout; + + void setState(States s, const QString& error={}); + + void close(); + void abort(); + + void onConnected(); + void onMessage(const QString& s); + void onDisconnected(); + void onError(QAbstractSocket::SocketError e); + void onSslErrors(const QList<QSslError>& errors); + void onTimeout(); +}; + + +class ValidationAttempt +{ +public: + enum Result + { + None, + Success, + SoftError, + HardError, + Cancelled + }; + + std::function<void (APIUserAccount)> success; + std::function<void ()> failure; + + ValidationAttempt(std::chrono::seconds timeout); + ValidationAttempt(const ValidationAttempt&) = delete; + ValidationAttempt& operator=(const ValidationAttempt&) = delete; + + void start(NXMAccessManager& m, const QString& key); + void cancel(); + + bool done() const; + Result result() const; + const QString& message() const; + std::chrono::seconds timeout() const; + QElapsedTimer elapsed() const; + +private: + QNetworkReply* m_reply; + Result m_result; + QString m_message; + QTimer m_timeout; + QElapsedTimer m_elapsed; + + bool sendRequest(NXMAccessManager& m, const QString& key); + + void onFinished(); + void onSslErrors(const QList<QSslError>& errors); + void onTimeout(); + + void setFailure(Result r, const QString& error); + void setSuccess(const APIUserAccount& user); + + void cleanup(); +}; + + +class NexusKeyValidator +{ +public: + enum Behaviour + { + OneShot = 0, + Retry + }; + + using FinishedCallback = void ( + ValidationAttempt::Result, const QString&, + std::optional<APIUserAccount>); + + std::function<FinishedCallback> finished; + std::function<void (const ValidationAttempt&)> attemptFinished; + + NexusKeyValidator(NXMAccessManager& am); + ~NexusKeyValidator(); + + void start(const QString& key, Behaviour b); + void cancel(); + + bool isActive() const; + const ValidationAttempt* lastAttempt() const; + const ValidationAttempt* currentAttempt() const; + +private: + NXMAccessManager& m_manager; + QString m_key; + std::vector<std::unique_ptr<ValidationAttempt>> m_attempts; + + void createAttempts(const std::vector<std::chrono::seconds>& timeouts); + + bool nextTry(); + void onAttemptSuccess(const ValidationAttempt& a, const APIUserAccount& u); + void onAttemptFailure(const ValidationAttempt& a); + + void setFinished( + ValidationAttempt::Result r, const QString& message, + std::optional<APIUserAccount> user); +}; + + +class ValidationProgressDialog : public QDialog +{ + Q_OBJECT; + +public: + ValidationProgressDialog(NexusKeyValidator& v); + + void setParentWidget(QWidget* w); + + void start(); + void stop(); + +protected: + void showEvent(QShowEvent* e) override; + void closeEvent(QCloseEvent* e) override; + +private: + std::unique_ptr<Ui::ValidationProgressDialog> ui; + NexusKeyValidator& m_validator; + QTimer* m_updateTimer; + bool m_first; + + void onHide(); + void onCancel(); + void onTimer(); + void updateProgress(); +}; + /** * @brief access manager extended to handle nxm links @@ -36,10 +209,9 @@ class NXMAccessManager : public QNetworkAccessManager { Q_OBJECT public: + NXMAccessManager(QObject *parent, const QString &moVersion); - explicit NXMAccessManager(QObject *parent, const QString &moVersion); - - ~NXMAccessManager(); + void setTopLevelWidget(QWidget* w); bool validated() const; @@ -53,12 +225,10 @@ public: void clearCookies(); QString userAgent(const QString &subModule = QString()) const; + const QString& MOVersion() const; - QString apiKey() const; void clearApiKey(); - void startValidationCheck(); - void refuseValidation(); signals: @@ -76,17 +246,9 @@ signals: * @param necessary true if a login was necessary and succeeded, false if the user is still logged in **/ void validateSuccessful(bool necessary); - void validateFailed(const QString &message); - void credentialsReceived(const APIUserAccount& user); -private slots: - - void validateFinished(); - void validateError(QNetworkReply::NetworkError errorCode); - void validateTimeout(); - protected: virtual QNetworkReply *createRequest( @@ -94,22 +256,29 @@ protected: QIODevice *device); private: - QTimer m_ValidateTimeout; - QNetworkReply *m_ValidateReply; - QProgressDialog *m_ProgressDialog { nullptr }; + enum States + { + NotChecked, + Valid, + Invalid + }; + QWidget* m_TopLevel; + mutable std::unique_ptr<ValidationProgressDialog> m_ProgressDialog; QString m_MOVersion; + NexusKeyValidator m_validator; + States m_validationState; + + void startValidationCheck(const QString& key); + + void onValidatorFinished( + ValidationAttempt::Result r, const QString& message, + std::optional<APIUserAccount>); - QString m_ApiKey; + void onValidatorAttemptFinished(const ValidationAttempt& a); - enum { - VALIDATE_NOT_CHECKED, - VALIDATE_CHECKING, - VALIDATE_NOT_VALID, - VALIDATE_ATTEMPT_FAILED, - VALIDATE_REFUSED, - VALIDATE_VALID - } m_ValidateState = VALIDATE_NOT_CHECKED; + void startProgress(); + void stopProgress(); }; #endif // NXMACCESSMANAGER_H |
