Overte C++ Documentation
AccountManager.h
1 //
2 // AccountManager.h
3 // libraries/networking/src
4 //
5 // Created by Stephen Birarda on 2/18/2014.
6 // Copyright 2014 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 #ifndef hifi_AccountManager_h
13 #define hifi_AccountManager_h
14 
15 #include <QtCore/QByteArray>
16 #include <QtCore/QObject>
17 #include <QtCore/QTimer>
18 #include <QtCore/QUrl>
19 #include <QtNetwork/QNetworkReply>
20 #include <QUrlQuery>
21 
22 #include <DependencyManager.h>
23 
24 #include "AccountSettings.h"
25 #include "DataServerAccountInfo.h"
26 #include "NetworkingConstants.h"
27 #include "MetaverseAPI.h"
28 #include "NetworkAccessManager.h"
29 #include <SharedUtil.h>
30 
31 class JSONCallbackParameters {
32 public:
33  JSONCallbackParameters(QObject* callbackReceiver = nullptr,
34  const QString& jsonCallbackMethod = QString(),
35  const QString& errorCallbackMethod = QString(),
36  const QJsonObject& callbackData = QJsonObject());
37 
38  bool isEmpty() const { return !callbackReceiver; }
39 
40  QObject* callbackReceiver;
41  QString jsonCallbackMethod;
42  QString errorCallbackMethod;
43  QJsonObject callbackData;
44 };
45 
46 namespace AccountManagerAuth {
47 enum Type {
48  None,
49  Required,
50  Optional,
51 };
52 }
53 
54 Q_DECLARE_METATYPE(AccountManagerAuth::Type);
55 
56 const QByteArray ACCESS_TOKEN_AUTHORIZATION_HEADER = "Authorization";
57 const auto METAVERSE_SESSION_ID_HEADER = QString("HFM-SessionID").toLocal8Bit();
58 
59 using UserAgentGetter = std::function<QString()>;
60 
61 const auto DEFAULT_USER_AGENT_GETTER = []() -> QString { return NetworkingConstants::OVERTE_USER_AGENT; };
62 
63 class AccountManager : public QObject, public Dependency {
64  Q_OBJECT
65 public:
66  AccountManager(bool accountSettingsEnabled = false, UserAgentGetter userAgentGetter = DEFAULT_USER_AGENT_GETTER);
67 
68  QNetworkRequest createRequest(QString path, AccountManagerAuth::Type authType);
69  Q_INVOKABLE void sendRequest(const QString& path,
70  AccountManagerAuth::Type authType,
71  QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,
72  const JSONCallbackParameters& callbackParams = JSONCallbackParameters(),
73  const QByteArray& dataByteArray = QByteArray(),
74  QHttpMultiPart* dataMultiPart = NULL,
75  const QVariantMap& propertyMap = QVariantMap());
76 
77  void setIsAgent(bool isAgent) { _isAgent = isAgent; }
78 
79  const QUrl& getAuthURL() const { return _authURL; }
80  void setAuthURL(const QUrl& authURL);
81  bool hasAuthEndpoint() { return !_authURL.isEmpty(); }
82  Q_INVOKABLE void updateAuthURLFromMetaverseServerURL();
83 
84  bool isLoggedIn() { return !_authURL.isEmpty() && hasValidAccessToken(); }
85  bool hasValidAccessToken();
86  bool needsToRefreshToken();
87  Q_INVOKABLE bool checkAndSignalForAccessToken();
88  void setAccessTokenForCurrentAuthURL(const QString& accessToken);
89  bool hasKeyPair() const;
90 
91  void requestProfile();
92 
93  DataServerAccountInfo& getAccountInfo() { return _accountInfo; }
94  void setAccountInfo(const DataServerAccountInfo& newAccountInfo);
95 
96  static QJsonObject dataObjectFromResponse(QNetworkReply* requestReply);
97 
98  QUuid getSessionID() const { return _sessionID; }
99  void setSessionID(const QUuid& sessionID);
100 
101  void setTemporaryDomain(const QUuid& domainID, const QString& key);
102  const QString& getTemporaryDomainKey(const QUuid& domainID) { return _accountInfo.getTemporaryDomainKey(domainID); }
103 
104  QUrl getMetaverseServerURL() { return MetaverseAPI::getCurrentMetaverseServerURL(); }
105  QString getMetaverseServerURLPath(bool appendForwardSlash = false) {
106  return MetaverseAPI::getCurrentMetaverseServerURLPath(appendForwardSlash);
107  }
108 
109  void removeAccountFromFile();
110 
111  bool getLimitedCommerce() { return _limitedCommerce; }
112  void setLimitedCommerce(bool isLimited);
113 
114  void setAccessTokens(const QString& response);
115  void setConfigFileURL(const QString& fileURL) { _configFileURL = fileURL; }
116  void saveLoginStatus(bool isLoggedIn);
117 
118  AccountSettings& getAccountSettings() { return _settings; }
119 
120 public slots:
121  void requestAccessToken(const QString& login, const QString& password);
122  void requestAccessTokenWithSteam(QByteArray authSessionTicket);
123  void requestAccessTokenWithOculus(const QString& nonce, const QString& oculusID);
124  void requestAccessTokenWithAuthCode(const QString& authCode,
125  const QString& clientId,
126  const QString& clientSecret,
127  const QString& redirectUri);
128  void refreshAccessToken();
129 
130  void requestAccessTokenFinished();
131  void refreshAccessTokenFinished();
132  void requestProfileFinished();
133  void refreshAccessTokenError(QNetworkReply::NetworkError error);
134  void requestProfileError(QNetworkReply::NetworkError error);
135  void logout();
136  void generateNewUserKeypair() { generateNewKeypair(); }
137  void generateNewDomainKeypair(const QUuid& domainID) { generateNewKeypair(false, domainID); }
138 
139 signals:
140  void authRequired();
141  void authEndpointChanged();
142  void usernameChanged(const QString& username);
143  void profileChanged();
144  void loginComplete(const QUrl& authURL);
145  void loginFailed();
146  void logoutComplete();
147  void newKeypair();
148  void limitedCommerceChanged();
149  void accountSettingsLoaded();
150 
151 private slots:
152  void handleKeypairGenerationError();
153  void processGeneratedKeypair(QByteArray publicKey, QByteArray privateKey);
154  void uploadPublicKey();
155  void publicKeyUploadSucceeded(QNetworkReply* reply);
156  void publicKeyUploadFailed(QNetworkReply* reply);
157  void generateNewKeypair(bool isUserKeypair = true, const QUuid& domainID = QUuid());
158 
159  void requestAccountSettings();
160  void requestAccountSettingsFinished();
161  void requestAccountSettingsError(QNetworkReply::NetworkError error);
162  void postAccountSettings();
163  void postAccountSettingsFinished();
164  void postAccountSettingsError(QNetworkReply::NetworkError error);
165 
166 private:
167  Q_DISABLE_COPY(AccountManager);
168 
169  void persistAccountToFile();
170 
171  void passSuccessToCallback(QNetworkReply* reply);
172  void passErrorToCallback(QNetworkReply* reply);
173 
174  UserAgentGetter _userAgentGetter;
175 
176  QUrl _authURL;
177 
178  DataServerAccountInfo _accountInfo;
179  bool _isWaitingForTokenRefresh { false };
180  bool _isAgent { false };
181 
182  bool _isWaitingForKeypairResponse { false };
183  QByteArray _pendingPrivateKey;
184  QByteArray _pendingPublicKey;
185 
186  QUuid _sessionID { QUuid::createUuid() };
187 
188  bool _limitedCommerce { false };
189  QString _configFileURL;
190 
191  bool _accountSettingsEnabled { false };
192  AccountSettings _settings;
193  quint64 _currentSyncTimestamp { 0 };
194  quint64 _lastSuccessfulSyncTimestamp { 0 };
195  int _numPullRetries { 0 };
196  QTimer* _pullSettingsRetryTimer { nullptr };
197  QTimer* _postSettingsTimer { nullptr };
198 };
199 
200 #endif // hifi_AccountManager_h