2 Copyright 2013-2015 Mats Sjöberg
4 This file is part of the Pumpa programme.
6 Pumpa is free software: you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 Pumpa is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Pumpa. If not, see <http://www.gnu.org/licenses/>.
25 #include <QVBoxLayout>
26 #include <QMessageBox>
27 #include <QVariantMap>
28 #include <QApplication>
29 #include <QNetworkReply>
30 #include <QNetworkRequest>
32 #include "pumpa_defines.h"
33 #include "oauthwizard.h"
37 #define EXAMPLE_ACCOUNT_ID "username@example.com"
39 //------------------------------------------------------------------------------
41 OAuthFirstPage::OAuthFirstPage(QWidget
* parent
) :
44 setTitle(tr("Welcome to Pumpa!"));
46 QVBoxLayout
* layout
= new QVBoxLayout(this);
49 new QLabel(tr("<p>In order to use pump.io you need to first register an "
50 "account with a pump.io server. If you haven't done this yet "
51 "you can do it now by trying out one of the existing public "
52 "servers: <br /><a href=\"http://pump.io/tryit.html\">"
53 "http://pump.io/tryit.html</a>.</p>"
54 "<p>When you are done enter your new pump.io account id "
55 "below in the form of <b>username@servername</b>.</p>"),
57 infoLabel
->setOpenExternalLinks(true);
58 infoLabel
->setTextInteractionFlags(Qt::TextSelectableByMouse
|
59 Qt::LinksAccessibleByMouse
);
60 infoLabel
->setWordWrap(true);
61 layout
->addWidget(infoLabel
);
64 m_messageLabel
= new QLabel(this);
65 layout
->addWidget(m_messageLabel
);
67 QLabel
* accountIdLabel
=
68 new QLabel(tr("<b>Your pump.io account id:</b>"), this);
69 QLineEdit
* accountIdEdit
= new QLineEdit(EXAMPLE_ACCOUNT_ID
, this);
70 accountIdLabel
->setBuddy(accountIdEdit
);
71 connect(accountIdEdit
, SIGNAL(textEdited(const QString
&)),
72 this, SIGNAL(completeChanged()));
74 QCheckBox
* sslCheckBox
=
75 new QCheckBox(tr("Use secure connection (recommended)"), this);
76 sslCheckBox
->setChecked(true);
78 layout
->addWidget(accountIdLabel
);
79 layout
->addWidget(accountIdEdit
);
80 layout
->addWidget(sslCheckBox
);
82 registerField("accountId*", accountIdEdit
);
83 registerField("useSsl*", sslCheckBox
);
85 setButtonText(QWizard::CommitButton
, tr("Next"));
90 //------------------------------------------------------------------------------
92 void OAuthFirstPage::setMessage(QString msg
) {
93 m_messageLabel
->setText(msg
);
96 //------------------------------------------------------------------------------
98 bool OAuthFirstPage::splitAccountId(QString
& username
, QString
& server
) const {
99 QString accountId
= field("accountId").toString().trimmed();
101 if (accountId
== EXAMPLE_ACCOUNT_ID
)
104 return splitWebfingerId(accountId
, username
, server
);
107 //------------------------------------------------------------------------------
109 bool OAuthFirstPage::isComplete() const {
110 QString username
, server
;
111 return splitAccountId(username
, server
);
114 //------------------------------------------------------------------------------
116 bool OAuthFirstPage::validatePage() {
117 QString username
, server
;
118 bool ok
= splitAccountId(username
, server
);
123 emit
committed(username
, server
);
127 //------------------------------------------------------------------------------
129 OAuthSecondPage::OAuthSecondPage(QWidget
* parent
) : QWizardPage(parent
) {
130 setTitle(tr("Authorise Pumpa"));
132 QVBoxLayout
* layout
= new QVBoxLayout(this);
135 new QLabel(tr("In order for Pumpa to be able to read and post new messages "
136 "to your pump.io account you need to grant Pumpa access via "
137 "the web page. Pumpa will open the web page for you - just "
138 "follow the instructions and copy & paste the "
139 "<b>verifier</b> text string back into the field below. (The "
140 "token should be automatically pre-filled.)"),
142 infoLabel
->setWordWrap(true);
143 layout
->addWidget(infoLabel
);
145 QLabel
* tokenLabel
= new QLabel(tr("Token:"), this);
146 QLineEdit
* tokenEdit
= new QLineEdit(this);
147 tokenLabel
->setBuddy(tokenEdit
);
148 layout
->addWidget(tokenLabel
);
149 layout
->addWidget(tokenEdit
);
151 QLabel
* verifierLabel
= new QLabel(tr("Verifier:"), this);
152 QLineEdit
* verifierEdit
= new QLineEdit(this);
153 verifierLabel
->setBuddy(verifierEdit
);
154 layout
->addWidget(verifierLabel
);
155 layout
->addWidget(verifierEdit
);
157 registerField("token*", tokenEdit
);
158 registerField("verifier*", verifierEdit
);
163 //------------------------------------------------------------------------------
165 bool OAuthSecondPage::validatePage() {
166 QString token
= field("token").toString();
167 QString verifier
= field("verifier").toString();
169 if (token
.isEmpty() || verifier
.isEmpty())
172 emit
committed(token
, verifier
);
176 //------------------------------------------------------------------------------
178 OAuthWizard::OAuthWizard(QNetworkAccessManager
* nam
, KQOAuthManager
* oam
,
184 setWindowTitle(CLIENT_FANCY_NAME
);
186 m_oar
= new KQOAuthRequest(this);
188 p1
= new OAuthFirstPage(this);
189 p2
= new OAuthSecondPage(this);
191 connect(p1
, SIGNAL(committed(QString
, QString
)),
192 this, SLOT(onFirstPageCommitted(QString
, QString
)));
193 connect(p2
, SIGNAL(committed(QString
, QString
)),
194 this, SLOT(onSecondPageCommitted(QString
, QString
)));
200 //------------------------------------------------------------------------------
202 void OAuthWizard::notifyMessage(QString msg
) {
203 qDebug() << "[OAuthWizard]" << msg
;
206 //------------------------------------------------------------------------------
208 void OAuthWizard::errorMessage(QString msg
) {
209 p1
->setMessage("<b><font color=\"red\">"+msg
+"</font></b>");
210 qDebug() << "[OAuthWizard ERROR]" << msg
;
214 //------------------------------------------------------------------------------
216 void OAuthWizard::onFirstPageCommitted(QString username
, QString server
) {
217 m_username
= username
;
218 m_server
= siteUrlFixer(server
, field("useSsl").toBool());
219 m_clientRegTryCount
= 0;
220 registerOAuthClient();
223 //------------------------------------------------------------------------------
225 void OAuthWizard::registerOAuthClient() {
226 notifyMessage(tr("Registering client ..."));
227 m_clientRegTryCount
++;
229 QUrl
serverUrl(m_server
);
230 serverUrl
.setPath("/api/client/register");
231 qDebug() << serverUrl
;
234 req
.setUrl(serverUrl
);
235 req
.setHeader(QNetworkRequest::ContentTypeHeader
, "application/json");
238 post
["type"] = "client_associate";
239 post
["application_type"] = "native";
240 post
["application_name"] = CLIENT_FANCY_NAME
;
241 post
["logo_uri"] = "http://saz.im/images/pumpa.png";
243 QByteArray postData
= serializeJson(post
);
245 // qDebug() << "data=" << postData;
247 QNetworkReply
*reply
= m_nam
->post(req
, postData
);
249 connect(reply
, SIGNAL(finished()), this, SLOT(onOAuthClientRegDone()));
252 //------------------------------------------------------------------------------
254 void OAuthWizard::onOAuthClientRegDone() {
255 QNetworkReply
*reply
= qobject_cast
<QNetworkReply
*>(sender());
256 if (reply
->error() != QNetworkReply::NoError
) {
257 errorMessage(tr("Network error: ") + reply
->errorString());
261 QByteArray data
= reply
->readAll();
263 QVariantMap json
= parseJson(data
);
264 m_clientId
= json
["client_id"].toString();
265 m_clientSecret
= json
["client_secret"].toString();
267 emit
clientRegistered(m_username
, m_server
, m_clientId
, m_clientSecret
);
269 notifyMessage(QString(tr("Registered client to [%1] successfully.")).
275 //------------------------------------------------------------------------------
277 void OAuthWizard::getOAuthAccess() {
278 notifyMessage(tr("Authorising user ..."));
280 connect(m_oam
, SIGNAL(temporaryTokenReceived(QString
, QString
)),
281 this, SLOT(onTemporaryTokenReceived(QString
, QString
)));
282 connect(m_oam
, SIGNAL(accessTokenReceived(QString
, QString
)),
283 this, SLOT(onAccessTokenReceived(QString
, QString
)));
285 m_oar
->initRequest(KQOAuthRequest::TemporaryCredentials
,
286 QUrl(m_server
+"/oauth/request_token"));
287 m_oar
->setConsumerKey(m_clientId
);
288 m_oar
->setConsumerSecretKey(m_clientSecret
);
290 m_oam
->executeRequest(m_oar
);
293 //------------------------------------------------------------------------------
295 void OAuthWizard::onTemporaryTokenReceived(QString token
,
296 QString
/*tokenSecret*/) {
297 setField("token", token
);
298 QUrl
userAuthURL(m_server
+"/oauth/authorize");
299 if (m_oam
->lastError() == KQOAuthManager::NoError
)
300 m_oam
->getUserAuthorization(userAuthURL
);
302 errorMessage(tr("Network or authentication error!"));
305 //------------------------------------------------------------------------------
307 void OAuthWizard::onSecondPageCommitted(QString token
, QString verifier
) {
308 m_oam
->verifyToken(token
, verifier
);
309 m_oam
->getUserAccessTokens(QUrl(m_server
+"/oauth/access_token"));
312 //------------------------------------------------------------------------------
314 void OAuthWizard::onAccessTokenReceived(QString token
, QString tokenSecret
) {
315 emit
accessTokenReceived(token
, tokenSecret
);