1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "AirMapSharedState.h"
#include "AirMapManager.h"
#include "airmap/authenticator.h"
#include "qjsonwebtoken.h"
using namespace airmap;
void
AirMapSharedState::setSettings(const Settings& settings)
{
logout();
_settings = settings;
}
void
AirMapSharedState::doRequestWithLogin(const Callback& callback)
{
if (isLoggedIn()) {
callback(_loginToken);
} else {
login();
_pendingRequests.enqueue(callback);
}
}
//-- TODO:
// For now, only anonymous login collects the (anonymous) pilot ID within login()
// For autheticated logins, we need to collect it here as opposed to spread all over
// the place as it is the case now.
void
AirMapSharedState::login()
{
if (isLoggedIn() || _isLoginInProgress) {
return;
}
_isLoginInProgress = true;
if (_settings.userName == "") { //use anonymous login
qCDebug(AirMapManagerLog) << "Anonymous authentication";
Authenticator::AuthenticateAnonymously::Params params;
params.id = "Anonymous";
_client->authenticator().authenticate_anonymously(params,
[this](const Authenticator::AuthenticateAnonymously::Result& result) {
if (!_isLoginInProgress) { // was logout() called in the meanwhile?
return;
}
if (result) {
qCDebug(AirMapManagerLog) << "Successfully authenticated with AirMap: id="<< result.value().id.c_str();
emit authStatus(AirspaceManager::AuthStatus::Anonymous);
_loginToken = QString::fromStdString(result.value().id);
QJsonWebToken token = QJsonWebToken::fromTokenAndSecret(_loginToken, QString());
QJsonDocument doc = token.getPayloadJDoc();
QJsonObject json = doc.object();
_pilotID = json.value("sub").toString();
qCDebug(AirMapManagerLog) << "Anonymous pilot id:" << _pilotID;
_processPendingRequests();
} else {
_pendingRequests.clear();
emit authStatus(AirspaceManager::AuthStatus::Error);
QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : "");
emit error("Failed to authenticate with AirMap",
QString::fromStdString(result.error().message()), description);
}
});
} else {
Authenticator::AuthenticateWithPassword::Params params;
params.oauth.username = _settings.userName.toStdString();
params.oauth.password = _settings.password.toStdString();
params.oauth.client_id = _settings.clientID.toStdString();
params.oauth.device_id = "QGroundControl";
qCDebug(AirMapManagerLog) << "User authentication" << _settings.userName;
_client->authenticator().authenticate_with_password(params,
[this](const Authenticator::AuthenticateWithPassword::Result& result) {
if (!_isLoginInProgress) { // was logout() called in the meanwhile?
return;
}
if (result) {
qCDebug(AirMapManagerLog) << "Successfully authenticated with AirMap: id="<< result.value().id.c_str()<<", access="
<<result.value().access.c_str();
emit authStatus(AirspaceManager::AuthStatus::Authenticated);
_loginToken = QString::fromStdString(result.value().id);
_processPendingRequests();
} else {
_pendingRequests.clear();
QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : "");
emit authStatus(AirspaceManager::AuthStatus::Error);
emit error("Failed to authenticate with AirMap",
QString::fromStdString(result.error().message()), description);
}
});
}
}
void
AirMapSharedState::_processPendingRequests()
{
while (!_pendingRequests.isEmpty()) {
_pendingRequests.dequeue()(_loginToken);
}
}
void
AirMapSharedState::logout()
{
_isLoginInProgress = false; // cancel if we're currently trying to login
if (!isLoggedIn()) {
return;
}
_pilotID.clear();
_loginToken.clear();
_pendingRequests.clear();
}