Replace agl-identity-agent by identity
[apps/homescreen.git] / homescreen / src / usermanagement.cpp
1 #include <stdlib.h>
2 #include "usermanagement.h"
3 #include <QDebug>
4 #include <QtCore/QJsonDocument>
5 #include <QByteArray>
6
7 #define APINAME "identity"
8
9 UserManagement::UserManagement(QObject *root) : QObject()
10 {
11     home = root->findChild<QObject *>("Home");
12     QObject::connect(home, SIGNAL(disconnect()),
13                          this, SLOT(slot_disconnect()));
14     logo = root->findChild<QObject *>("Logo_colour");
15     shortcutArea = root->findChild<QObject *>("ShortcutArea");
16     statusArea = root->findChild<QObject *>("StatusArea");
17     this->appModel = home->findChild<ApplicationModel *>("ApplicationModel");
18     sequence = 0;
19     isRed = false;
20     connect(&timerRed, SIGNAL(timeout()), this, SLOT(slot_turnOffRed()));
21     timerRed.setSingleShot(true);
22     timerRed.setInterval(3000);
23 #ifdef REAL_SERVER
24     connectWebsockets();
25 #else
26     pSocket = NULL;
27     connect(&timerTest, SIGNAL(timeout()), this, SLOT(slot_timerTest()));
28     timerTest.setSingleShot(false);
29     timerTest.start(5000);
30     launchServer();
31 #endif
32 }
33 void UserManagement::slot_disconnect()
34 {
35     appModel->changeLanguage("us");
36     appModel->changeOrder(-1);
37     timerRed.stop();
38     slot_turnOffRed();
39     QMetaObject::invokeMethod(home, "languageChanged");
40     QMetaObject::invokeMethod(shortcutArea, "languageChanged", Q_ARG(QVariant, "en"));
41     QMetaObject::invokeMethod(statusArea, "languageChanged", Q_ARG(QVariant, "en"));
42     QMetaObject::invokeMethod(home, "showSign90", Q_ARG(QVariant, false), Q_ARG(QVariant, "en"));
43     QMetaObject::invokeMethod(home, "showVisa", Q_ARG(QVariant, false), Q_ARG(QVariant, ""));
44     QMetaObject::invokeMethod(home, "showLicence", Q_ARG(QVariant, false), Q_ARG(QVariant, ""));
45     QMetaObject::invokeMethod(home, "changeFlag", Q_ARG(QVariant, "./images/us_flag.png"));
46     QMetaObject::invokeMethod(home, "setUser", Q_ARG(QVariant, ""), Q_ARG(QVariant, ""));
47     QVariantList list;
48     list << 2 << QString().setNum(++sequence) << APINAME"/logout" << true;
49     listToJson(list, &data);
50     slot_sendData();
51 }
52
53 void UserManagement::setUser(const User &user)
54 {
55     int hash = qHash(user.name + user.first_name);
56     timerRed.stop();
57     appModel->changeLanguage(user.graphPreferredLanguage);
58     appModel->changeOrder(hash);
59     slot_turnOffRed();
60     QMetaObject::invokeMethod(home, "languageChanged");
61     QMetaObject::invokeMethod(shortcutArea, "languageChanged", Q_ARG(QVariant, user.graphPreferredLanguage));
62     QMetaObject::invokeMethod(statusArea, "languageChanged", Q_ARG(QVariant, user.graphPreferredLanguage));
63     QMetaObject::invokeMethod(home, "showSign90", Q_ARG(QVariant, !user.graphActions.contains("Exceed 90 Kph")), Q_ARG(QVariant, user.graphPreferredLanguage));
64     QStringList t;
65     foreach(const QString &s, user.graphActions) {
66         if(!s.contains("Exceed"))
67             t.append(s);
68     }
69     QString type = user.policy;
70     if(user.graphPreferredLanguage == "fr") {
71         if(type == "Owner")
72             type = "PropriĆ©taire";
73         else if(type == "Driver")
74             type = "Conducteur";
75         else if(type == "Maintainer")
76             type = "Maintenance";
77     }
78     QMetaObject::invokeMethod(home, "setUser", Q_ARG(QVariant, type), Q_ARG(QVariant, QVariant::fromValue(t)));
79     if(user.ccNumberMasked.isEmpty())
80         QMetaObject::invokeMethod(home, "showVisa", Q_ARG(QVariant, false), Q_ARG(QVariant, ""));
81     else
82         QMetaObject::invokeMethod(home, "showVisa", Q_ARG(QVariant, true), Q_ARG(QVariant, user.ccNumberMasked));
83     const QString welcome = QString("%1").arg(user.graphPreferredLanguage == "fr" ? "Bonjour " : "Hello") + " ";
84     QMetaObject::invokeMethod(home, "showHello", Q_ARG(QVariant, welcome + user.first_name));
85     QMetaObject::invokeMethod(home, "changeFlag", Q_ARG(QVariant, user.graphPreferredLanguage == "fr" ? "./images/french_flag.png" : "./images/us_flag.png"));
86     if(user.name.toLower() == "philippea")
87         QMetaObject::invokeMethod(home, "showLicence", Q_ARG(QVariant, true), Q_ARG(QVariant, "./images/DL_Philippe.png"));
88     else if(user.name.toLower() == "alainp")
89         QMetaObject::invokeMethod(home, "showLicence", Q_ARG(QVariant, true), Q_ARG(QVariant, "./images/DL_Alain.png"));
90     else if(user.name.toLower() == "olivierc")
91         QMetaObject::invokeMethod(home, "showLicence", Q_ARG(QVariant, true), Q_ARG(QVariant, "./images/DL_Olivier.png"));
92     else
93         QMetaObject::invokeMethod(home, "showLicence", Q_ARG(QVariant, false), Q_ARG(QVariant, ""));
94
95 }
96 void UserManagement::slot_turnOffRed()
97 {
98     if(!isRed)
99         return;
100     QMetaObject::invokeMethod(logo, "setImage", Q_ARG(QVariant, "./images/Utility_Logo_Colour-01.png"));
101     isRed = false;
102 }
103
104 void UserManagement::connectWebsockets()
105 {
106 #ifdef REAL_SERVER
107     const QUrl url(getenv("IDENTITY_WEBSOCKET") ?: REAL_SERVER);
108 #else
109     const QUrl url(QStringLiteral("ws://localhost:1234"));
110 #endif
111     QSslConfiguration config = QSslConfiguration::defaultConfiguration();
112     config.setProtocol(QSsl::SecureProtocols);
113     webSocket.setSslConfiguration(config);
114     connect(&webSocket, &QWebSocket::connected, this, &UserManagement::onConnected);
115     connect(&webSocket, &QWebSocket::disconnected, this, &UserManagement::onClosed);
116     if(!connect(&webSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onWebSocketError(QAbstractSocket::SocketError)))) {
117         qWarning() << "Failed to connect to QWebSocket::error";
118     }
119     webSocket.open(QUrl(url));
120 }
121 void UserManagement::onWebSocketError(QAbstractSocket::SocketError)
122 {
123     qWarning()<<"Websocket error:" << webSocket.errorString();
124 }
125
126 void UserManagement::onConnected()
127 {
128     connect(&webSocket, &QWebSocket::textMessageReceived,
129             this, &UserManagement::onTextMessageReceived);
130     QVariantList list;
131     QByteArray json;
132     list << 2 << QString().setNum(++sequence) << APINAME"/subscribe" << true;
133     listToJson(list, &json);
134     webSocket.sendTextMessage(QString(json));
135     list .clear();
136     list << 2 << QString().setNum(++sequence) << APINAME"/scan" << true;
137     listToJson(list, &json);
138     webSocket.sendTextMessage(QString(json));
139 }
140 void UserManagement::onTextMessageReceived(QString message)
141 {
142     QVariantList list;
143     const bool ok = jsonToList(message.toUtf8(), &list);
144     if(!ok || list.size() < 3) {
145         qWarning()<<"error 1 decoding json"<<list.size()<<message;
146         return;
147     }
148     QVariantMap map  = list.at(2).toMap();
149     if(list.first().toInt() == 5) {
150         if(!isRed)
151             QMetaObject::invokeMethod(logo, "setImage", Q_ARG(QVariant, "./images/Utility_Logo_Red-01.png"));
152         isRed = true;
153         timerRed.start();
154         map = map["data"].toMap();
155         if(map["eventName"].toString() == "login") {
156             //qWarning()<<"login received in client";
157             list.clear();
158             list << 2 << QString().setNum(++sequence) << APINAME"/get" << true;
159             listToJson(list, &data);
160             QTimer::singleShot(300, this, SLOT(slot_sendData()));
161         }
162         return;
163     }
164     if(list.first().toInt() == 3) {
165         if(!map.contains("response")) {
166             return;
167         }
168         map = map["response"].toMap();
169         User user;
170         user.postal_address = map["postal_address"].toString();
171         QStringList temp  = map["loc"].toString().split(",");
172         if(temp.size() == 2) {
173             user.loc.setX(temp.at(0).toDouble());
174             user.loc.setY(temp.at(1).toDouble());
175         }
176         user.graphActions = map["graphActions"].toString().split(",");
177         user.country = map["country"].toString();
178         user.mail = map["mail"].toString();
179         user.city = map["city"].toString();
180         user.graphEmail = map["graphEmail"].toString();
181         user.graphPreferredLanguage = map["graphPreferredLanguage"].toString();
182         user.ccNumberMasked = map["ccNumberMasked"].toString();
183         user.ccExpYear = map["ccExpYear"].toString();
184         user.ccExpMonth = map["ccExpMonth"].toString();
185         user.description = map["description"].toString();
186         user.groups = map["groups"].toStringList();
187         user.last_name = map["last_name"].toString();
188         user.ccNumber = map["ccNumber"].toString();
189         user.house_identifier = map["house_identifier"].toString();
190         user.phone = map["phone"].toString();
191         user.name = map["name"].toString();
192         user.state = map["state"].toString();
193         user.common_name = map["common_name"].toString();
194         user.fax = map["fax"].toString();
195         user.postal_code = map["postal_code"].toString();
196         user.first_name = map["first_name"].toString();
197         user.keytoken = map["keytoken"].toString();
198         user.policy = map["graphPolicies"].toString();
199         setUser(user);
200     }
201 }
202 void UserManagement::slot_sendData()
203 {
204     webSocket.sendTextMessage(QString(data));
205 }
206
207 void UserManagement::onClosed()
208 {
209     qWarning()<<"webSocket closed";
210 }
211 bool UserManagement::listToJson(const QList<QVariant> &list, QByteArray *json) const
212 {
213     QVariant v(list);
214     *json = QJsonDocument::fromVariant(v).toJson(QJsonDocument::Compact);
215     return true;
216 }
217 bool UserManagement::jsonToList(const QByteArray &buf, QList<QVariant> *list) const
218 {
219     if(!list)
220         return false;
221     QJsonParseError err;
222     QVariant v = QJsonDocument::fromJson(buf, &err).toVariant();
223     if(err.error != 0) {
224         qWarning() << "Error parsing json data" << err.errorString() << buf;
225         *list = QList<QVariant>();
226         return false;
227     }
228     *list = v.toList();
229     return true;
230 }
231 bool UserManagement::mapToJson( const QVariantMap &map, QByteArray *json) const
232 {
233     if(!json)
234         return false;
235     QVariant v(map);
236     *json = QJsonDocument::fromVariant(v).toJson(QJsonDocument::Compact);
237     return true;
238 }
239 bool UserManagement::jsonToMap(const QByteArray &buf, QVariantMap *map) const
240 {
241     if(!map)
242         return false;
243     QJsonParseError err;
244     QVariant v = QJsonDocument::fromJson(buf, &err).toVariant();
245     if(err.error != 0) {
246         qWarning() << "Error parsing json data" << err.errorString() << buf;
247         *map = QVariantMap();
248         return false;
249     }
250     *map = v.toMap();
251     return true;
252 }
253 #ifndef REAL_SERVER
254 void UserManagement::launchServer()
255 {
256       webSocketServer = new QWebSocketServer(QStringLiteral("My Server"),
257                                               QWebSocketServer::NonSecureMode, this);
258       if(webSocketServer->listen(QHostAddress::Any, 1234)) {
259           connect(webSocketServer, &QWebSocketServer::newConnection,
260                   this, &UserManagement::onServerNewConnection);
261           connect(webSocketServer, &QWebSocketServer::closed, this, &UserManagement::onServerClosed);
262           QTimer::singleShot(100, this, SLOT(connectWebsockets()));
263       } else {
264           qWarning()<<"unable to launch webSocket server";
265       }
266 }
267 void UserManagement::onServerNewConnection()
268 {
269     pSocket = webSocketServer->nextPendingConnection();
270     connect(pSocket, &QWebSocket::textMessageReceived, this, &UserManagement::processTextMessage, Qt::UniqueConnection);
271     connect(pSocket, &QWebSocket::binaryMessageReceived, this, &UserManagement::processBinaryMessage, Qt::UniqueConnection);
272     connect(pSocket, &QWebSocket::disconnected, this, &UserManagement::serverSocketDisconnected, Qt::UniqueConnection);
273 }
274 void UserManagement::processTextMessage(QString message)
275 {
276     QString clientDetails_1 = "{\"postal_address\":\"201 Mission Street\",\"loc\":\"37.7914374,-122.3950694\",\"graphActions\":\"Install App,Update Software,Open Trunk,View Online\""
277                               ",\"country\":\"USA\",\"mail\":\"bjensen@example.com\",\"city\":\"San Francisco\",\"graphEmail\":"
278                               "\"bjensen@example.com\",\"graphPreferredLanguage\":\"en\",\"ccNumberMasked\":\"-111\",\"ccExpYear\""
279                               ":\"19\",\"ccExpMonth\":\"01\",\"description\":\"Original description\",\"groups\":[],\"last_name\":\""
280                               "Jensen\",\"ccNumber\":\"111-2343-1121-111\",\"house_identifier\":\"ForgeRock\",\"phone\":\""
281                               "+1 408 555 1862\",\"name\":\"bjensen\",\"state\":\"CA\",\"common_name\":\"Barbara Jensen\",\"fax\":\""
282                               "+1 408 555 1862\",\"postal_code\":\"94105\",\"first_name\":\"Barbara\",\"keytoken\":\"a123456\",\"graphPolicies\":\"Driver\"}";
283     QString clientDetails_2 = "{\"postal_address\":\"201 Mission Street\",\"loc\":\"37.7914374,-122.3950694\""
284                               ",\"country\":\"USA\",\"mail\":\"bjensen@example.com\",\"city\":\"San Francisco\",\"graphEmail\":"
285                               "\"bjensen@example.com\",\"graphPreferredLanguage\":\"fr\",\"ccNumberMasked\":\"-222\",\"ccExpYear\""
286                               ":\"19\",\"ccExpMonth\":\"01\",\"description\":\"Original description\",\"groups\":[],\"last_name\":\""
287                               "Jensen\",\"ccNumber\":\"111-2343-1121-111\",\"house_identifier\":\"ForgeRock\",\"phone\":\""
288                               "+1 408 555 1862\",\"name\":\"bjensen\",\"state\":\"CA\",\"common_name\":\"Barbara Jensen\",\"fax\":\""
289                               "+1 408 555 1862\",\"postal_code\":\"94105\",\"first_name\":\"Philippe\",\"keytoken\":\"a123456\",\"graphPolicies\":\"Maintainer\"}";
290     QString clientDetails = clientDetails_1;
291     if(sequence % 2 == 1)
292         clientDetails = clientDetails_2;
293     QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
294     //qDebug() << "message received in server:" << message;
295     if (!pClient)
296         return;
297     QVariantList list;
298     if(!jsonToList(message.toUtf8(), &list))
299         return;
300     if(list.size() < 2)
301         return;
302     const int messType = list.at(0).toInt();
303     const QString messId = list.at(1).toString();
304     const QString cmd = list.at(2).toString();
305     list.clear();
306     QString reply;
307     switch(messType) {
308     case 2:
309         if(cmd == APINAME"/subscribe") {
310             reply = "[3,\"999maitai999\",{\"jtype\":\"afb-reply\",\"request\":{\"status\":\"success\",\"uuid\":\"1f2f7678-6f2e-4f54-b7b5-d0d4dcbf2e41\"}}]";
311         } else if (cmd == APINAME"/get") {
312             reply = "[3,\"999maitai99\",{\"jtype\":\"afb-reply\",\"request\":{\"status\":\"success\"},\"response\":....}]";
313             reply = reply.replace("....", clientDetails);
314         } else {
315             qWarning()<<"invalid cmd received:"<<cmd;
316             return;
317         }
318         break;
319     default:
320         qWarning()<<"invalid message type"<<messType;
321         return;
322         break;
323     }
324     reply = reply.replace("999maitai999", messId);
325     pClient->sendTextMessage(reply);
326 }
327 void UserManagement::processBinaryMessage(QByteArray message)
328 {
329     QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
330     qDebug() << "Binary Message received ????:" << message;
331     if (pClient) {
332        // pClient->sendBinaryMessage(message);
333     }
334 }
335 void UserManagement::serverSocketDisconnected()
336 {
337     QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
338     qDebug() << "socketDisconnected:" << pClient;
339     if (pClient) {
340         pClient->deleteLater();
341     }
342 }
343 void UserManagement::slot_timerTest()
344 {
345     if(!pSocket)
346         return;
347     if(sequence > 3) {
348         timerTest.stop();
349         return;
350     }
351     pSocket->sendTextMessage("[5,\APINAME"/event\",{\"event\":\APINAME"\/event\",\"data\":{\"eventName\":\"incoming\",\"accountid\":\"D2:D4:71:0D:B5:F1\",\"nickname\":\"D2:D4:71:0D:B5:F1\"},\"jtype\":\"afb-event\"}]");
352     pSocket->sendTextMessage("[5,\APINAME"/event\",{\"event\":\APINAME"\/event\",\"data\":{\"eventName\":\"login\",\"accountid\":\"null\"},\"jtype\":\"afb-event\"}]");
353 }
354 void UserManagement::onServerClosed()
355 {
356     qWarning()<<"websocket server closed";
357 }
358 #endif