31 #include <QNetworkRequest> 32 #include <QNetworkReply> 33 #include <QNetworkCookie> 39 #include <QFutureInterface> 46 #include <xmlsettingsdialog/basesettingsmanager.h> 56 QUrl URLFromClientID (
const QString&
id,
const QStringList& scope)
58 auto url = QUrl::fromEncoded (
"https://oauth.vk.com/authorize?redirect_uri=http%3A%2F%2Foauth.vk.com%2Fblank.html&response_type=token&state=");
61 (
"scope", scope.join (
","));
67 const QString&
id,
const QStringList& scope,
72 , AccountHR_ (accName)
73 , AuthNAM_ (new QNetworkAccessManager (this))
77 , IsRequesting_ (false)
79 , URL_ (URLFromClientID (ID_, scope))
80 , IsRequestScheduled_ (false)
81 , ScheduleTimer_ (new QTimer (this))
83 AuthNAM_->setCookieJar (Cookies_);
84 Cookies_->
Load (cookies);
86 ScheduleTimer_->setSingleShot (
true);
87 connect (ScheduleTimer_,
90 SLOT (execScheduledRequest ()));
95 return !Token_.isEmpty () &&
96 (!ValidFor_ || ReceivedAt_.secsTo (QDateTime::currentDateTime ()) < ValidFor_);
101 return !Token_.isEmpty () || !Cookies_->allCookies ().isEmpty ();
106 const auto& newUrl = URLFromClientID (ID_, scope);
112 ReceivedAt_ = QDateTime ();
124 for (
const auto& queue : PrioManagedQueues_)
126 for (
const auto& queue : ManagedQueues_)
133 InvokeQueues (Token_);
142 QFutureInterface<QString> iface;
143 iface.reportStarted ();
147 [
this, iface] ()
mutable { iface.reportFinished (&Token_); },
153 return iface.future ();
160 qWarning () << Q_FUNC_INFO
161 <<
"cannot manage request queue if queue manager wasn't set";
165 ManagedQueues_ << queue;
174 qWarning () << Q_FUNC_INFO
175 <<
"cannot manage request queue if queue manager wasn't set";
179 PrioManagedQueues_ << queue;
186 SilentMode_ = silent;
189 void VkAuthManager::InvokeQueues (
const QString& token)
191 ScheduleTrack (token);
193 for (
auto queue : PrioManagedQueues_)
194 while (!queue->isEmpty ())
196 const auto& pair = queue->takeFirst ();
197 const auto& f = pair.first;
198 Queue_->
Schedule ([f, token] { f (token); },
nullptr, pair.second);
201 for (
auto queue : ManagedQueues_)
202 while (!queue->isEmpty ())
204 const auto& f = queue->takeFirst ();
205 Queue_->
Schedule ([f, token] { f (token); });
209 void VkAuthManager::RequestURL (
const QUrl& url)
211 qDebug () << Q_FUNC_INFO << url;
212 auto reply = AuthNAM_->get (QNetworkRequest (url));
214 SIGNAL (finished ()),
216 SLOT (handleGotForm ()));
219 void VkAuthManager::RequestAuthKey ()
221 if (IsRequestScheduled_ && ScheduleTimer_->isActive ())
222 ScheduleTimer_->stop ();
228 IsRequesting_ =
true;
231 bool VkAuthManager::CheckReply (QUrl location)
233 if (location.path () !=
"/blank.html")
234 return CheckError (location);
236 location = QUrl::fromEncoded (location.toEncoded ().replace (
'#',
'?'));
237 #if QT_VERSION < 0x050000 238 Token_ = location.queryItemValue (
"access_token");
239 ValidFor_ = location.queryItemValue (
"expires_in").toInt ();
241 const QUrlQuery query { location };
242 Token_ = query.queryItemValue (
"access_token");
243 ValidFor_ = query.queryItemValue (
"expires_in").toInt ();
245 ReceivedAt_ = QDateTime::currentDateTime ();
246 qDebug () << Q_FUNC_INFO << Token_ << ValidFor_;
247 IsRequesting_ =
false;
249 InvokeQueues (Token_);
256 bool VkAuthManager::CheckError (
const QUrl& url)
258 if (url.path () !=
"/error")
261 #if QT_VERSION < 0x050000 262 const auto errNum = url.queryItemValue (
"err").toInt ();
264 const auto errNum = QUrlQuery { url }.queryItemValue (
"err").toInt ();
267 IsRequesting_ =
false;
269 qWarning () << Q_FUNC_INFO
281 tr (
"VK.com authentication for %1 failed because of error %2. " 282 "Report upstream please.")
286 Proxy_->GetEntityManager ()->HandleEntity (e);
291 void VkAuthManager::ScheduleTrack (
const QString& key)
296 if (!Proxy_->GetSettingsManager ()->property (
"TrackVK").toBool ())
301 QUrl url {
"https://api.vk.com/method/stats.trackVisitor" };
303 (
"access_token", key);
305 auto reply = AuthNAM_->get (QNetworkRequest { url });
307 SIGNAL (finished ()),
309 SLOT (deleteLater ()));
316 ReceivedAt_ = QDateTime ();
322 class CloseEventFilter :
public QObject
324 const std::function<void ()> Handler_;
326 CloseEventFilter (
const std::function<
void ()>& handler, QObject *handlee)
327 : QObject { handlee }
328 , Handler_ { handler }
330 handlee->installEventFilter (
this);
333 bool eventFilter (QObject*, QEvent *event)
344 auto view =
new QWebView;
345 view->setWindowTitle (tr (
"VK.com authentication for %1")
348 view->resize (800, 600);
349 view->page ()->setNetworkAccessManager (AuthNAM_);
355 SIGNAL (urlChanged (QUrl)),
357 SLOT (handleViewUrlChanged (QUrl)));
359 new CloseEventFilter ([
this] { emit
authCanceled (); }, view);
362 void VkAuthManager::execScheduledRequest ()
364 IsRequestScheduled_ =
false;
369 void VkAuthManager::handleGotForm ()
371 auto reply = qobject_cast<QNetworkReply*> (sender ());
372 reply->deleteLater ();
374 if (reply->error () != QNetworkReply::NoError)
376 qWarning () << Q_FUNC_INFO
378 << reply->errorString ();
380 IsRequesting_ =
false;
382 if (!IsRequestScheduled_)
384 IsRequestScheduled_ =
true;
385 ScheduleTimer_->start (30000);
391 const auto& location = reply->header (QNetworkRequest::LocationHeader).toUrl ();
392 if (location.isEmpty ())
398 if (CheckReply (location))
401 RequestURL (location);
404 void VkAuthManager::handleViewUrlChanged (
const QUrl& url)
406 if (!CheckReply (url))
410 sender ()->deleteLater ();
void UpdateScope(const QStringList &)
void gotAuthKey(const QString &)
Manipulates query part of an QUrl object.
detail::ScopeGuard< F > MakeScopeGuard(const F &f)
Returns an object performing passed function on scope exit.
void Schedule(std::function< void()> functor, QObject *dependent=nullptr, QueuePriority prio=QueuePriority::Normal)
Adds the given functor.
bool HadAuthentication() const
Executes a given functor upon a signal (or a list of signals).
std::shared_ptr< ICoreProxy > ICoreProxy_ptr
ScheduleGuard_t Q_REQUIRED_RESULT ManageQueue(RequestQueue_ptr)
Entity MakeNotification(const QString &header, const QString &text, Priority priority)
An utility function to make a Entity with notification.
A simple scheduling manager for a queue of functors.
bool IsAuthenticated() const
void cookiesChanged(const QByteArray &)
VkAuthManager(const QString &accountName, const QString &clientId, const QStringList &scope, const QByteArray &cookies, ICoreProxy_ptr, QueueManager *=nullptr, QObject *=nullptr)
A customized cookie jar with additional features.
void Load(const QByteArray &data)
QFuture< QString > GetAuthKeyFuture()