diff --git a/img/auth_icon.svg b/img/auth_icon.svg new file mode 100644 index 0000000..043e69f --- /dev/null +++ b/img/auth_icon.svg @@ -0,0 +1,51 @@ + + diff --git a/img/ic_locked.svg b/img/ic_locked.svg new file mode 100644 index 0000000..dcfe18e --- /dev/null +++ b/img/ic_locked.svg @@ -0,0 +1,51 @@ + +image/svg+xml diff --git a/img/ic_unlocked.svg b/img/ic_unlocked.svg new file mode 100644 index 0000000..3222bde --- /dev/null +++ b/img/ic_unlocked.svg @@ -0,0 +1,54 @@ + +image/svg+xml diff --git a/img_desktop.qrc b/img_desktop.qrc index ced7d5a..a599ccf 100644 --- a/img_desktop.qrc +++ b/img_desktop.qrc @@ -360,5 +360,8 @@ img/icon_config_install.png img/icon_config_network.png img/icon_config_rollback.png + img/auth_icon.svg + img/ic_locked.svg + img/ic_unlocked.svg diff --git a/lang/calaos_de.ts b/lang/calaos_de.ts index bc37ea1..2602b21 100644 --- a/lang/calaos_de.ts +++ b/lang/calaos_de.ts @@ -4,35 +4,35 @@ Application - - + + Network error Netzwerkfehler - + The connection to calaos_server was lost.It will reconnect automatically when calaos_serveris available again. Die Verbindung zu calaos_server wurde unterbrochen. Die Verbindung wird automatisch wiederhergestellt, wenn calaos_server wieder verfügbar ist. - - - + + + Close Schliessen - + No network connection found, this application requires a network connection to work. Keine Netzwerkverbindung gefunden, diese Anwendung benötigt eine Netzwerkverbindung, um zu funktionieren. - + Login failed Fehlgeschlagene Anmeldung - + Connection failed, please check your credentials. Verbindung fehlgeschlagen, bitte überprüfen Sie Ihre Zugangsdaten. @@ -331,37 +331,47 @@ - + %1 day - + %1 days + + + %1 hours + + + %1 hour + + + + Machine name: - + Network: - + CPU Usage: - + Memory Usage: - + Calaos is free software, you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 @@ -392,57 +402,97 @@ ConfigUserInfoView - + + Change your credentials: + + + + + Change username + + + + + Username + + + + + Enter your new username + + + + + Change password + + + + + Password + + + + + Enter your new password + + + + + Actual username: + + + + Here you can configure some personal information like your email address. It is used by Calaos to send you some email. For example, the Note widget can use those addresses to send notes to your mailbox. - + Add email - + Email - + Add a new email address to the list - + User information - + Back to config - + Quit Beenden - + Remove email - + Remove this email '%1' from the list? - + Yes, remove - + No Nein @@ -968,27 +1018,27 @@ The rollback option is also available in the Control Panel (Configuration menu)< LoginView - + Login to your home - + Username - + Password - + Hostname - + Login @@ -1269,23 +1319,17 @@ The rollback option is also available in the Control Panel (Configuration menu)< OSInstaller - - - + Error Fehler - - - + Installation failed. See log... - - - + Close Schliessen @@ -1306,7 +1350,7 @@ The rollback option is also available in the Control Panel (Configuration menu)< PushEventView - + Push Notification @@ -1314,7 +1358,7 @@ The rollback option is also available in the Control Panel (Configuration menu)< QObject - + Internal SD card reader @@ -1402,7 +1446,7 @@ The rollback option is also available in the Control Panel (Configuration menu)< - + Settings @@ -1433,7 +1477,7 @@ The rollback option is also available in the Control Panel (Configuration menu)< UsbDiskModel - + Removable disks @@ -1497,12 +1541,12 @@ The rollback option is also available in the Control Panel (Configuration menu)< cache - + Set cache path to <directory> - + directory @@ -1510,12 +1554,12 @@ The rollback option is also available in the Control Panel (Configuration menu)< config - + Set config path to <directory> - + directory diff --git a/lang/calaos_fr.qm b/lang/calaos_fr.qm index e1d67a3..c2b2a02 100644 Binary files a/lang/calaos_fr.qm and b/lang/calaos_fr.qm differ diff --git a/lang/calaos_fr.ts b/lang/calaos_fr.ts index 7a068a8..41449b4 100644 --- a/lang/calaos_fr.ts +++ b/lang/calaos_fr.ts @@ -4,35 +4,35 @@ Application - - + + Network error Erreur réseau - + The connection to calaos_server was lost.It will reconnect automatically when calaos_serveris available again. La connection avec calaos_server a été perdu. Elle va être retentée lorsque calaos_server sera de nouveau disponible. - - - + + + Close Fermer - + No network connection found, this application requires a network connection to work. Aucune connection réseau trouvée, cette application demande une connection au réseau pour fonctionner. - + Login failed Authentification échoué - + Connection failed, please check your credentials. Connection échouée, veuillez vérifier vos identifiants. @@ -331,37 +331,47 @@ Système démarré depuis: - + %1 day %1 jour - + %1 days %1 jours + + + %1 hours + %1 heures + + %1 hour + %1 heure + + + Machine name: Nom de la machine: - + Network: Réseau: - + CPU Usage: Utilisation CPU: - + Memory Usage: Utilisation mémoire: - + Calaos is free software, you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 Calaos est un logiciel libre, vous pouvez le redistribuer et/ou le modifier en respect des termes de la GNU General Public License version 3 @@ -392,57 +402,97 @@ ConfigUserInfoView - + + Change your credentials: + Modifiez vos informations d'identification : + + + + Change username + Changer de nom d'utilisateur + + + + Username + Nom d'utilisateur + + + + Enter your new username + Entrez votre nouveau nom d'utilisateur + + + + Change password + Modifier le mot de passe + + + + Password + Mot de passe + + + + Enter your new password + Entrez votre nouveau mot de passe + + + + Actual username: + Nom d'utilisateur actuel : + + + Here you can configure some personal information like your email address. It is used by Calaos to send you some email. For example, the Note widget can use those addresses to send notes to your mailbox. Ici, vous pouvez configurer quelques informations personnelles comme votre adresse email. Ca sera utilisé par Calaos pour vous envoyer un mail. Par exemple, le widget Note utilisera ces adresses pour vous envoyer les notes dans votre boite. - + Add email Ajouter un email - + Email Email - + Add a new email address to the list Ajouter uns nouvelle adresse email à la liste - + User information Informations utilisateur - + Back to config Retour à la config - + Quit Quitter - + Remove email Supprimer l'adresse - + Remove this email '%1' from the list? Supprimer l'adresse '%1' de la liste? - + Yes, remove Oui, supprimer - + No Non @@ -996,27 +1046,27 @@ L'option de retour en arrière est également disponible dans le Panneau de LoginView - + Login to your home Se connecter à votre maison - + Username Nom d'utilisateur - + Password Mot de passe - + Hostname Adresse de la machine - + Login Se connecter @@ -1301,23 +1351,17 @@ L'option de retour en arrière est également disponible dans le Panneau de OSInstaller - - - + Error Erreur - - - + Installation failed. See log... L'installation à échoué. Voir le log... - - - + Close Fermer @@ -1338,7 +1382,7 @@ L'option de retour en arrière est également disponible dans le Panneau de PushEventView - + Push Notification Notification Push @@ -1346,7 +1390,7 @@ L'option de retour en arrière est également disponible dans le Panneau de QObject - + Internal SD card reader Lecteur de carte SD interne @@ -1434,7 +1478,7 @@ L'option de retour en arrière est également disponible dans le Panneau de Langue: - + Settings Options @@ -1465,7 +1509,7 @@ L'option de retour en arrière est également disponible dans le Panneau de UsbDiskModel - + Removable disks Disques amovibles @@ -1529,12 +1573,12 @@ L'option de retour en arrière est également disponible dans le Panneau de cache - + Set cache path to <directory> Utiliser <dossier> comme dossier de cache - + directory dossier @@ -1542,12 +1586,12 @@ L'option de retour en arrière est également disponible dans le Panneau de config - + Set config path to <directory> Utiliser <dossier> comme dossier de config - + directory dossier diff --git a/qml/SharedComponents/CalaosItemBase.qml b/qml/SharedComponents/CalaosItemBase.qml index 7bc65cd..66861c5 100644 --- a/qml/SharedComponents/CalaosItemBase.qml +++ b/qml/SharedComponents/CalaosItemBase.qml @@ -5,6 +5,9 @@ MouseArea { id: thisButton property alias text: label.text + property bool disabled: false + + enabled: !disabled signal buttonClicked() @@ -17,7 +20,7 @@ MouseArea { Rectangle { id: rectBorder radius: 8 * calaosApp.density - border.color: "#3AB4D7" + border.color: thisButton.disabled? Theme.colorAlpha(Theme.whiteColor, 0.40) : "#3AB4D7" border.width: 2 * calaosApp.density color: "transparent" @@ -67,7 +70,7 @@ MouseArea { id: label font { family: calaosFont.fontFamilyThin; pointSize: 12 } anchors.centerIn: parent - color: "#3AB4D7" + color: thisButton.disabled? Theme.colorAlpha(Theme.whiteColor, 0.40) : "#3AB4D7" } hoverEnabled: enabled diff --git a/qml/desktop/ConfigUserInfoView.qml b/qml/desktop/ConfigUserInfoView.qml index aba9f01..aa22d6f 100644 --- a/qml/desktop/ConfigUserInfoView.qml +++ b/qml/desktop/ConfigUserInfoView.qml @@ -26,6 +26,15 @@ Item { opacity: 0.6 } + AppListener { + Filter { + type: ActionTypes.changeLogin + onDispatched: (filtertype, message) => { + calaosApp.changeLogin() + } + } + } + ColumnLayout { anchors { @@ -36,6 +45,110 @@ Item { spacing: Units.dp(10) + RowLayout { + Image { + width: Units.dp(32) + height: Units.dp(32) + sourceSize: Qt.size(width, height) + source: calaosApp.getPictureSized("auth_icon") + } + + Text { + Layout.fillWidth: true + font { family: calaosFont.fontFamily; weight: Font.ExtraLight; pixelSize: Units.dp(18) } + color: Theme.whiteColor + text: qsTr("Change your credentials:") + } + + Item { Layout.fillWidth: true; height: 1 } + + ItemButtonAction { + iconSource: calaosApp.settingsLocked? "qrc:/img/ic_locked.svg": "qrc:/img/ic_unlocked.svg" + + onButtonClicked: { + if (calaosApp.settingsLocked) { + AppActions.openKeyboard(qsTr("Locked"), + qsTr("Enter your password to unlock settings"), + "", + TextInput.Password, + false, + function(txt) { + if (!calaosApp.unlockSettings(txt)) { + AppActions.showNotificationMsg(qsTr("Unlock failed"), qsTr("The password you entered is wrong. Please try again."), qsTr("Close")) + } + } + ) + } else { + calaosApp.lockSettings() + } + } + } + } + + RowLayout { + + Item { Layout.fillWidth: true; height: 1 } + + CalaosButton { + text: qsTr("Change username") + onButtonClicked: AppActions.openKeyboard(qsTr("Username"), + qsTr("Enter your new username"), + "", + TextInput.Normal, + false, + function(txt) { + if (!calaosApp.changeUsername(txt)) + AppActions.showNotificationMsg(qsTr("Username change failed"), qsTr("The username was not changed. Please try again."), qsTr("Close")) + }) + hoverEnabled: false + disabled: calaosApp.settingsLocked + } + + CalaosButton { + text: qsTr("Change password") + onButtonClicked: AppActions.openKeyboard(qsTr("Password"), + qsTr("Enter your new password"), + "", + TextInput.PasswordEchoOnEdit, + false, + function(txt) { + if (!calaosApp.changePassword(txt)) + AppActions.showNotificationMsg(qsTr("Password change failed"), qsTr("The password was not changed. Please try again."), qsTr("Close")) + }) + hoverEnabled: false + disabled: calaosApp.settingsLocked + } + } + + RowLayout { + Text { + Layout.fillWidth: true + font { family: calaosFont.fontFamily; weight: Font.ExtraLight; pixelSize: Units.dp(18) } + color: Theme.whiteColor + text: qsTr("Actual username:") + } + + Item { Layout.fillWidth: true; height: 1 } + + Text { + Layout.fillWidth: true + font { family: calaosFont.fontFamily; weight: Font.ExtraLight; pixelSize: Units.dp(18) } + color: Theme.blueColor + text: calaosApp.username + } + } + + Item { Layout.preferredHeight: Units.dp(10); width: 1 } + + Rectangle { + Layout.preferredHeight: 2 + Layout.fillWidth: true + + color: Theme.colorAlpha(Theme.whiteColor, 0.34) + } + + Item { Layout.preferredHeight: Units.dp(10); width: 1 } + Text { font { family: calaosFont.fontFamily; weight: Font.ExtraLight; pixelSize: Units.dp(15) } color: Theme.colorAlpha(Theme.whiteColor, 0.7) @@ -121,6 +234,7 @@ Item { onButtonClicked: AppActions.openKeyboard(qsTr("Email"), qsTr("Add a new email address to the list"), "", + TextInput.Normal, false, ActionTypes.addUserInfoEmail) hoverEnabled: false diff --git a/qml/desktop/DialogKeyboard.qml b/qml/desktop/DialogKeyboard.qml index a8be57f..f6d6c5a 100644 --- a/qml/desktop/DialogKeyboard.qml +++ b/qml/desktop/DialogKeyboard.qml @@ -20,7 +20,7 @@ Dialog { property bool multiline: false property string currentText - function openKeyboard(title, subtitle, initialText, multiline, cb) { + function openKeyboard(title, subtitle, initialText, inputEchoMode, multiline, cb) { lTitle.text = title lSubTitle.text = subtitle dlg.multiline = multiline @@ -38,6 +38,9 @@ Dialog { __callback = null } + textInput.echoMode = inputEchoMode + //textInputMulti.echoMode = inputEchoMode + dlg.show() } diff --git a/qml/desktop/MediaWebView.qml b/qml/desktop/MediaWebView.qml index 2f240de..7320843 100644 --- a/qml/desktop/MediaWebView.qml +++ b/qml/desktop/MediaWebView.qml @@ -165,6 +165,7 @@ Item { onBtClicked: AppActions.openKeyboard(qsTr("URL"), qsTr("Enter the url to navigate to"), "", + TextInput.Normal, false, ActionTypes.webGoToUrl) } diff --git a/qml/desktop/main.qml b/qml/desktop/main.qml index a7ce969..0e673e1 100644 --- a/qml/desktop/main.qml +++ b/qml/desktop/main.qml @@ -343,6 +343,7 @@ Window { dialogKeyboard.openKeyboard(qsTr("Keyboard"), qsTr("Change text for '%1'").arg(io.ioName), io.stateString, + TextInput.Normal, false, function (txt) { io.sendStringValue(txt) @@ -353,15 +354,26 @@ Window { type: ActionTypes.openKeyboard onDispatched: (filtertype, message) => { + //check if message.returnAction is of type function + let retFunc + if (typeof message.returnAction === "function") { + retFunc = message.returnAction + } else { + retFunc = function (txt) { + AppDispatcher.dispatch(message.returnAction, + { text: txt, + returnPayload: message.returnPayload + }) + } + } + dialogKeyboard.openKeyboard(message.title, message.subtitle, message.initialText, + message.inputEchoMode, message.multiline, - function (txt) { - AppDispatcher.dispatch(message.returnAction, - { text: txt, - returnPayload: message.returnPayload }) - }) + retFunc + ) } } diff --git a/qml/quickflux/ActionTypes.qml b/qml/quickflux/ActionTypes.qml index 28a9e66..00d3d5a 100644 --- a/qml/quickflux/ActionTypes.qml +++ b/qml/quickflux/ActionTypes.qml @@ -6,7 +6,7 @@ KeyTable { // KeyTable is an object with properties equal to its key name - // Desktop actions + // Desktop actions property string clickHomeboardItem; property string hideHomeboardMenu; @@ -34,9 +34,9 @@ KeyTable { property string changeNoteText property string addUserInfoEmail property string webGoToUrl - - //Mobile actions - property string openEventLog + + //Mobile actions + property string openEventLog property string openEventPushViewer property string openEventPushViewerUuid diff --git a/qml/quickflux/AppActions.qml b/qml/quickflux/AppActions.qml index 785ab38..1849a86 100644 --- a/qml/quickflux/AppActions.qml +++ b/qml/quickflux/AppActions.qml @@ -41,10 +41,10 @@ QtObject { function openCameraSingleView(model) { AppDispatcher.dispatch(ActionTypes.openCameraSingleView, { camModel: model }); } - - function openEventLog() { - AppDispatcher.dispatch(ActionTypes.openEventLog); - } + + function openEventLog() { + AppDispatcher.dispatch(ActionTypes.openEventLog); + } function openEventPushViewer(text, picurl) { AppDispatcher.dispatch(ActionTypes.openEventPushViewer, @@ -57,11 +57,12 @@ QtObject { { notifUuid: uuid }); } - function openKeyboard(kTitle, kSubtitle, txt, kMultiline, kReturnAction, kReturnPayload) { + function openKeyboard(kTitle, kSubtitle, txt, echoMode, kMultiline, kReturnAction, kReturnPayload) { AppDispatcher.dispatch(ActionTypes.openKeyboard, { title: kTitle, subtitle: kSubtitle, initialText: txt, + inputEchoMode: echoMode, multiline: kMultiline, returnAction: kReturnAction, returnPayload: kReturnPayload }); diff --git a/src/Application.cpp b/src/Application.cpp index 1bb61ef..3649c1c 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -174,6 +174,8 @@ void Application::createQmlApp() update_isSnapshotBoot(false); #endif + update_settingsLocked(true); + update_applicationStatus(Common::NotConnected); calaosConnect = new CalaosConnection(this); @@ -201,6 +203,18 @@ void Application::createQmlApp() }); #endif }); + connect(calaosConnect, &CalaosConnection::changeCredsFailed, this, [=]() + { + HardwareUtils::Instance()->showAlertMessage(tr("Credentials change failed"), + tr("Credentials were not changed. Please try again."), + tr("Close")); + }); + connect(calaosConnect, &CalaosConnection::changeCredsSuccess, this, [=]() + { + HardwareUtils::Instance()->showAlertMessage(tr("Credentials changed"), + tr("Credentials were successfully changed."), + tr("Close")); + }); scenarioModel = new ScenarioModel(&engine, calaosConnect, this); scenarioSortModel = new ScenarioSortModel(&engine, this); @@ -743,3 +757,65 @@ void Application::updateSystemInfo() ); #endif } + +bool Application::unlockSettings(QString pass) +{ + if (pass.isEmpty()) + return false; + + if (pass != get_password()) + return false; + + update_settingsLocked(false); + + //relock after 5 minutes + if (!timerLockSettings) + { + timerLockSettings = new QTimer(this); + connect(timerLockSettings, &QTimer::timeout, this, &Application::lockSettings); + } + timerLockSettings->start(5 * 60 * 1000); + + return true; +} + +void Application::lockSettings() +{ + update_settingsLocked(true); +} + +bool Application::changeUsername(QString user) +{ + if (get_applicationStatus() != Common::LoggedIn) + { + //save user in local config file only + QString u, p; + HardwareUtils::Instance()->loadAuthKeychain(u, p); + HardwareUtils::Instance()->saveAuthKeychain(user, p); + } + else if (user != get_username()) + { + //save user on server + calaosConnect->changeCredentials(user, get_password()); + } + + return true; +} + +bool Application::changePassword(QString pass) +{ + if (get_applicationStatus() != Common::LoggedIn) + { + //save pass in local config file only + QString u, p; + HardwareUtils::Instance()->loadAuthKeychain(u, p); + HardwareUtils::Instance()->saveAuthKeychain(u, pass); + } + else if (pass != get_password()) + { + //save user on server + calaosConnect->changeCredentials(get_username(), pass); + } + + return true; +} diff --git a/src/Application.h b/src/Application.h index 5c1f20f..9096de6 100644 --- a/src/Application.h +++ b/src/Application.h @@ -56,6 +56,8 @@ class Application : public QAPP QML_READONLY_PROPERTY(bool, hasInstall) //If running on live install enable installation mode QML_READONLY_PROPERTY(bool, isSnapshotBoot) //if system has been booted read only from a snapshot + QML_READONLY_PROPERTY(bool, settingsLocked) + QML_READONLY_PROPERTY(QString, appVersion) public: @@ -94,6 +96,12 @@ class Application : public QAPP Q_INVOKABLE void updateNetworkInfo(); Q_INVOKABLE void updateSystemInfo(); + Q_INVOKABLE bool unlockSettings(QString pass); + Q_INVOKABLE void lockSettings(); + + Q_INVOKABLE bool changeUsername(QString user); + Q_INVOKABLE bool changePassword(QString pass); + private slots: void homeLoaded(const QVariantMap &homeData); void loginFailed(); @@ -127,6 +135,8 @@ private slots: bool startedWithOptHandled = false; + QTimer *timerLockSettings = nullptr; + void loadSettings(); void saveSettings(); diff --git a/src/CalaosConnection.cpp b/src/CalaosConnection.cpp index 941d096..afa42e9 100644 --- a/src/CalaosConnection.cpp +++ b/src/CalaosConnection.cpp @@ -635,6 +635,23 @@ void CalaosConnection::getAudioCover(const QString &playerid) reqReplies.append(reqReply); } +bool CalaosConnection::changeCredentials(QString user, QString pass) +{ + //Only supported for websocket + if (!isWebsocket()) return false; + + username_temp = user; + password_temp = pass; + + QJsonObject jroot = { { "action", "change_cred" }, + { "old_user", username }, + { "old_pw", password }, + { "new_user", user }, + { "new_pw", pass }, + }; + sendWebsocket("settings", jroot, "change_creds"); +} + void CalaosConnection::startJsonPolling() { if (constate != ConStateHttp) @@ -862,9 +879,29 @@ void CalaosConnection::onWsTextMessageReceived(const QString &message) { emit logEventLoaded(jroot["data"].toObject().toVariantMap()); } + else if (jroot["msg"] == "settings") + { + if (jdata["action"] == "change_cred") + { + if (jdata["success"] == "true") + { + username = username_temp; + password = password_temp; + emit changeCredsSuccess(); + + //reconnect + logout(); + login(username, password, wshost); + } + else + { + emit changeCredsFailed(); + } + } + } //We get this marker when calling sendCommand(...) it helps disabling the net indicator - if (jroot["msg_id"] == "user_cmd") + if (jroot["msg_id"] == "user_cmd" || jroot["msg_id"] == "change_creds") { HardwareUtils::Instance()->showNetworkActivity(false); } diff --git a/src/CalaosConnection.h b/src/CalaosConnection.h index f537527..53c31a0 100644 --- a/src/CalaosConnection.h +++ b/src/CalaosConnection.h @@ -28,6 +28,8 @@ class CalaosConnection : public QObject QString getNotifPictureUrl(const QString &pic_uid); + bool changeCredentials(QString user, QString pass); + private: QNetworkAccessManager *accessManager; @@ -39,6 +41,9 @@ class CalaosConnection : public QObject QString wshost, httphost; QString uuidPolling; + //used when changing credentials + QString username_temp, password_temp; + int constate = ConStateUnknown; QList reqReplies; @@ -92,6 +97,8 @@ class CalaosConnection : public QObject void eventTouchscreenCamera(QString camid); void logEventLoaded(const QVariantMap &data); void audioCoverDownloaded(const QString &camid, const QByteArray &data); + void changeCredsSuccess(); + void changeCredsFailed(); public slots: void login(QString user, QString pass, QString host); diff --git a/widgets/Note/NoteBack.qml b/widgets/Note/NoteBack.qml index 17100e2..212ce34 100644 --- a/widgets/Note/NoteBack.qml +++ b/widgets/Note/NoteBack.qml @@ -49,6 +49,7 @@ Rectangle { onButtonClicked: AppActions.openKeyboard(qsTr("Note"), qsTr("Write your note to be displayed on the desktop"), noteText, + TextInput.Normal, true, ActionTypes.changeNoteText, { uuid: widgetModel.uuid })