From a68ae311bf08d8305b07cc9a9bde756fddca12b0085fc3d6b1055e6db4430d96 Mon Sep 17 00:00:00 2001 From: Daniel Stoppek Date: Tue, 25 Feb 2025 16:21:09 +0100 Subject: [PATCH 1/7] Test --- Gui/AddNewObject.qml | 5 +---- lib/DB/EmployeeModel.py | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Gui/AddNewObject.qml b/Gui/AddNewObject.qml index 7ad44bc..f19120a 100644 --- a/Gui/AddNewObject.qml +++ b/Gui/AddNewObject.qml @@ -23,8 +23,6 @@ GridLayout editable: true Layout.fillWidth: true Layout.columnSpan: 3 - onEditTextChanged: checkFields() - onCurrentTextChanged: checkFields() } //// New grid row @@ -234,8 +232,7 @@ GridLayout function checkObjectField() { - return ((business.editText.trim() || business.currentText.trim()) && - street.text.trim() && houseno.text.trim() && + return (street.text.trim() && houseno.text.trim() && (postcode.editText.trim() || postcode.currentText.trim()) && (city.editText.trim() || city.currentText.trim()) && cleansing.text.trim()) diff --git a/lib/DB/EmployeeModel.py b/lib/DB/EmployeeModel.py index 0897061..821218c 100644 --- a/lib/DB/EmployeeModel.py +++ b/lib/DB/EmployeeModel.py @@ -21,6 +21,7 @@ class EmployeeModel(QAbstractTableModel): self.__employee_dao.newEmployeeAdded.connect(self.__refreshView) self.__conf = ConfigLoader().getConfig() self.__key = self.__conf['pyqcrm']['ENCRYPTION_KEY'] + print(self.__key) self.__getData() @Slot(dict, bool) From f0cde5ec2064f6024f12157071c2cce43b16dbab0dc082f17d5019c8eb3c8114 Mon Sep 17 00:00:00 2001 From: Daniel Stoppek Date: Wed, 26 Feb 2025 15:09:28 +0100 Subject: [PATCH 2/7] Fehler --- Gui/BackupSettings.qml | 103 +++++++++++++++++++++++ Gui/CompanyConf.qml | 17 ++++ Gui/{firststart.qml => Firststart.qml} | 17 ++++ Gui/ObjectAddOnContactPerson.qml | 26 ++++++ Gui/PyqcrmConf.qml | 108 +++++++++++++++++++++++++ Gui/TopBar.qml | 11 ++- Gui/UsersPage.qml | 1 + Gui/main.qml | 4 +- enc_key_backup.txt | 1 + lib/Vermasseln.py | 4 +- pyqcrm.qrc | 24 ------ qml.qrc | 46 ----------- 12 files changed, 287 insertions(+), 75 deletions(-) create mode 100644 Gui/BackupSettings.qml create mode 100644 Gui/CompanyConf.qml rename Gui/{firststart.qml => Firststart.qml} (88%) create mode 100644 Gui/PyqcrmConf.qml create mode 100644 enc_key_backup.txt delete mode 100644 pyqcrm.qrc delete mode 100644 qml.qrc diff --git a/Gui/BackupSettings.qml b/Gui/BackupSettings.qml new file mode 100644 index 0000000..4a31706 --- /dev/null +++ b/Gui/BackupSettings.qml @@ -0,0 +1,103 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Dialogs + +GridLayout +{ + anchors.fill: parent + anchors.topMargin: 150 + columns: 2 + Label + { + Layout.columnSpan: 2 + Layout.alignment: Qt.AlignHCenter + text: qsTr("Sicherung") + font.pixelSize: 35 + + } + + Label + { + text: qsTr("Konfiguration") + Layout.alignment: Qt.AlignRight + + } + Button + { + id: saveConfig + text: qsTr("Jetzt sichern!") + onClicked: settingsFileDialog.open() + } + Label + { + text: qsTr("Verschlüsselung") + Layout.alignment: Qt.AlignRight + } + Button + { + id: saveEncryption + text: qsTr("Jetzt sichern!") + onClicked: Firsts.open() + } + Item + { + id: spacer + Layout.fillHeight: true + } + Dialog + { + anchors.centerIn: parent + id: dialog + title: "Title" + standardButtons: Dialog.Apply | Dialog.Cancel + + onApplied: + { + + if (configPwd.text === repeatConfigPwd.text) + { console.log("true") + saveConfigFile.open() + } + else + { + configPwd.text = "" + configPwd.placeholderText = qsTr("Passwort stimmt nicht überein") + configPwd.placeholderTextColor = "red" + repeatConfigPwd.placeholderText = qsTr("") + repeatConfigPwd.text = "" + console.log("false") + } + } + onRejected: console.log("Cancel clicked") + GridLayout + { + columns: 2 + Label + { + text: qsTr("Passwort eingeben") + } + TextField + { + id: configPwd + placeholderText: qsTr("Sicherungspasswort festlegen") + } + Label + { + text: qsTr("Passwort wiederholen") + } + TextField + { + id: repeatConfigPwd + placeholderText: qsTr("Sicherungspasswort wiederholen") + } + + } + } + FileDialog + { + id: saveConfigFile + fileMode: FileDialog.SaveFile + + } +} diff --git a/Gui/CompanyConf.qml b/Gui/CompanyConf.qml new file mode 100644 index 0000000..52aa97e --- /dev/null +++ b/Gui/CompanyConf.qml @@ -0,0 +1,17 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls + +Item +{ + property string name: "company" + anchors.fill: parent + + Label + { + text: qsTr("Das Unternehmen") + anchors.centerIn: parent + font.pixelSize: 57 + font.bold: true + } +} diff --git a/Gui/firststart.qml b/Gui/Firststart.qml similarity index 88% rename from Gui/firststart.qml rename to Gui/Firststart.qml index 38544a8..7c2a134 100644 --- a/Gui/firststart.qml +++ b/Gui/Firststart.qml @@ -11,7 +11,10 @@ Item { property string recpass: "" property bool adminAvailable: true + property alias recoverEnc: recoveryPaswordDialog + property alias first: firstStartItem + id: firstStartItem anchors.fill: parent StackView { @@ -87,6 +90,7 @@ Item Dialog { + id: recoveryPaswordDialog modal: true title: qsTr("Wiederherstellung") @@ -115,6 +119,19 @@ Item implicitWidth: 300 placeholderText: qsTr("Hier Wiederherstellungspasswort eingeben") } + Label + { + text: qsTr("Wiederherstellungspasswort eingeben: ") + } + + TextField + { + id: repeatRecoveryPaswordInput + text: "" + echoMode: TextInput.Password + implicitWidth: 300 + placeholderText: qsTr("Hier Wiederherstellungspasswort eingeben") + } } } } diff --git a/Gui/ObjectAddOnContactPerson.qml b/Gui/ObjectAddOnContactPerson.qml index 7d99aae..0d93195 100644 --- a/Gui/ObjectAddOnContactPerson.qml +++ b/Gui/ObjectAddOnContactPerson.qml @@ -231,6 +231,25 @@ GridLayout } } + Component + { + id: highlight + Rectangle + { + width: 230; height: 15 + color: "lightsteelblue"; radius: 5 + y: contactView.currentItem.y + Behavior on y + { + SpringAnimation + { + spring: 3 + damping: 0.2 + } + } + } + } + Rectangle { id: mainRect @@ -242,6 +261,7 @@ GridLayout ListView { id: contactView + implicitHeight: parent.height implicitWidth: parent.width model: contactModel @@ -249,10 +269,13 @@ GridLayout highlight: Rectangle { color: "grey"} highlightFollowsCurrentItem: false + onActiveFocusChanged: if(!focus) currentIndex = -1 delegate: Item + { width: contactView.width + height: 15 MouseArea { @@ -264,6 +287,7 @@ GridLayout } } + Row { //spacing: 9 @@ -297,6 +321,8 @@ GridLayout } } } + + } } } diff --git a/Gui/PyqcrmConf.qml b/Gui/PyqcrmConf.qml new file mode 100644 index 0000000..76a5d84 --- /dev/null +++ b/Gui/PyqcrmConf.qml @@ -0,0 +1,108 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Item +{ + anchors.fill: parent + TabBar + { + id: bar + width: parent.width + TabButton + { + text: qsTr("Benutzer") + } + TabButton + { + text: qsTr("Datenbank") + } + TabButton + { + text: qsTr("Das Unternehmen") + } + TabButton + { + text: qsTr("Sicherung") + } + } + + StackLayout + { + id: confContainer + anchors.fill: parent + currentIndex: bar.currentIndex + Item + { + id: userTab + UsersPage + { + id: usersPage + anchors.fill: parent + } + } + Item + { + id: dbTab + DbConfiguration + { + id: dbConf + anchors.fill: parent + } + } + Item + { + id: companyTab + CompanyConf + { + id: companyConf + anchors.fill: parent + } + } + Item + { + id: backup + BackupSettings + { + id: backupSettings + anchors.fill: parent + } + } + } + + RowLayout + { + width: parent.width + anchors.bottom: parent.bottom + Item + { + Layout.fillWidth: true + } + + Button + { + text: qsTr("Ablehnen") + onClicked: appLoader.source = "Dashboard.qml" + } + + Button + { + text: qsTr("Speichern") + onClicked: + { + switch (confContainer.currentIndex) + { + case 1: + console.log("Need to update DB paramenters") + break + + case 2: + console.log("Need to update company's info.") + break + default: + console.log("Need to handle users") + } + } + } + } +} diff --git a/Gui/TopBar.qml b/Gui/TopBar.qml index 758dfb0..16bf968 100644 --- a/Gui/TopBar.qml +++ b/Gui/TopBar.qml @@ -178,8 +178,15 @@ RowLayout id: mainMenu MenuItem { - text: qsTr("Benutzer-Verwaltung") - onTriggered: appLoader.source = "UsersPage.qml" + //text: qsTr("Benutzer-Verwaltung") + //onTriggered: appLoader.source = "UsersPage.qml" + text: qsTr("Einstellungen") + onTriggered: + { + // TODO: Check if logged-in user is admin first!! + + appLoader.source = "PyqcrmConf.qml" + } } MenuSeparator {} MenuItem { text: qsTr("Als PDF exportieren") } diff --git a/Gui/UsersPage.qml b/Gui/UsersPage.qml index 31d8c59..e9a9ec2 100644 --- a/Gui/UsersPage.qml +++ b/Gui/UsersPage.qml @@ -4,6 +4,7 @@ import QtQuick.Controls Item { + property string name: "users" anchors.fill: parent Label diff --git a/Gui/main.qml b/Gui/main.qml index 2e85370..2d65ba1 100644 --- a/Gui/main.qml +++ b/Gui/main.qml @@ -12,6 +12,7 @@ ApplicationWindow visible: true title: "PYQCRM" property string confile: "" + property alias settingsFileDialog: settingsFiledialog TopBar { @@ -80,12 +81,13 @@ ApplicationWindow anchors.centerIn: parent standardButtons: Dialog.Yes | Dialog.No onAccepted: settingsFiledialog.open() - onRejected: appLoader.source= "firststart.qml" + onRejected: appLoader.source= "Firststart.qml" title: qsTr("Einstellungen importieren") } FileDialog { + id: settingsFiledialog title: qsTr("PYQCRM Einstellungen") currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0] diff --git a/enc_key_backup.txt b/enc_key_backup.txt new file mode 100644 index 0000000..a4915d4 --- /dev/null +++ b/enc_key_backup.txt @@ -0,0 +1 @@ +Lj30yFOP7hJmY5Cub1Go8fJz0UE+Zyo9cEqNxfY23Sc= diff --git a/lib/Vermasseln.py b/lib/Vermasseln.py index 7857100..72e3190 100644 --- a/lib/Vermasseln.py +++ b/lib/Vermasseln.py @@ -20,7 +20,7 @@ class Vermasseln: return storable_data - def entschluesseln(self, data, local= True): + def entschluesseln(self, data, local = True): try: data_list = data.split(".") encoded_data = [b64decode(x) for x in data_list] @@ -37,7 +37,7 @@ class Vermasseln: return decrypted_data - def __vermasslungsKobold(self, local= True): + def __vermasslungsKobold(self, local = True): key = platform.processor().encode("utf-8") if local else b"(==daniishtverhaftetwegensexy#)" key = key[0:31] hash_key = SHA256.new(key) diff --git a/pyqcrm.qrc b/pyqcrm.qrc deleted file mode 100644 index 6fd41f3..0000000 --- a/pyqcrm.qrc +++ /dev/null @@ -1,24 +0,0 @@ - - - qtquickcontrols2.conf - images/add.svg - images/addbusiness.svg - images/addperson.svg - images/filter.svg - images/menu.svg - images/search.svg - sounds/error.ogg - sounds/fail2c.ogg - sounds/puzzerr.ogg - sounds/sysnotify.ogg - sounds/wrong.ogg - fonts/Damarwulan.ttf - fonts/HelloStranger.otf - fonts/HussarPrintA.otf - fonts/LittleBirdsRegular.ttf - fonts/ReginaldScript.ttf - images/account.svg - README - LICENSE - - diff --git a/qml.qrc b/qml.qrc deleted file mode 100644 index 1e6ca28..0000000 --- a/qml.qrc +++ /dev/null @@ -1,46 +0,0 @@ - - - Gui/TopBar.qml - Gui/AdminUserConfig.qml - Gui/EncryptionKey.qml - Gui/DbConfiguration.qml - Gui/LoginScreen.qml - Gui/AddContact.qml - Gui/AddCustomer.qml - Gui/CustomerTable.qml - Gui/Dashboard.qml - Gui/EmployeeTable.qml - Gui/firststart.qml - Gui/main.qml - Gui/SearchBar.qml - js/qmldict.js - Gui/CustomerView.qml - Gui/NoDbConnection.qml - Gui/Notifications.qml - Gui/ObjectTable.qml - Gui/AddObject.qml - Gui/ObjectView.qml - Gui/ObjectAddOns.qml - Gui/ObjectAddOnContactPerson.qml - Gui/ObjectAddOnEmployee.qml - Gui/AddObjectEmployee.qml - Gui/AddApplicant.qml - Gui/ApplicantPersonalData.qml - Gui/ApplicantBankData.qml - Gui/ApplicantNationalInsurance.qml - Gui/ApplicantVarious.qml - Gui/CustomersTable.qml - Gui/CustomerDetails.qml - Gui/ObjectsTable.qml - Gui/EmployeesTable.qml - Gui/EmployeeDetails.qml - Gui/ObjectDetails.qml - Gui/AddNewObject.qml - Gui/PrinterDialog.qml - Gui/CustomerContactDetails.qml - Gui/NoCustomerContact.qml - Gui/CustomerDetailsView.qml - Gui/ReadMe.qml - Gui/UsersPage.qml - - From 2a09fed57ac72552d4442485b48f4568f79c57bd09f63f260cfabaac6d492308 Mon Sep 17 00:00:00 2001 From: Daniel Stoppek Date: Wed, 26 Feb 2025 15:15:39 +0100 Subject: [PATCH 3/7] Test --- Gui/BackupSettings.qml | 103 +++++++++++++++++++++++ Gui/CompanyConf.qml | 17 ++++ Gui/{firststart.qml => Firststart.qml} | 17 ++++ Gui/ObjectAddOnContactPerson.qml | 26 ++++++ Gui/PyqcrmConf.qml | 112 +++++++++++++++++++++++++ Gui/TopBar.qml | 11 ++- Gui/UsersPage.qml | 1 + Gui/main.qml | 4 +- enc_key_backup.txt | 1 + lib/Vermasseln.py | 4 +- pyqcrm.qrc | 24 ------ qml.qrc | 2 + 12 files changed, 293 insertions(+), 29 deletions(-) create mode 100644 Gui/BackupSettings.qml create mode 100644 Gui/CompanyConf.qml rename Gui/{firststart.qml => Firststart.qml} (88%) create mode 100644 Gui/PyqcrmConf.qml create mode 100644 enc_key_backup.txt delete mode 100644 pyqcrm.qrc diff --git a/Gui/BackupSettings.qml b/Gui/BackupSettings.qml new file mode 100644 index 0000000..4a31706 --- /dev/null +++ b/Gui/BackupSettings.qml @@ -0,0 +1,103 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Dialogs + +GridLayout +{ + anchors.fill: parent + anchors.topMargin: 150 + columns: 2 + Label + { + Layout.columnSpan: 2 + Layout.alignment: Qt.AlignHCenter + text: qsTr("Sicherung") + font.pixelSize: 35 + + } + + Label + { + text: qsTr("Konfiguration") + Layout.alignment: Qt.AlignRight + + } + Button + { + id: saveConfig + text: qsTr("Jetzt sichern!") + onClicked: settingsFileDialog.open() + } + Label + { + text: qsTr("Verschlüsselung") + Layout.alignment: Qt.AlignRight + } + Button + { + id: saveEncryption + text: qsTr("Jetzt sichern!") + onClicked: Firsts.open() + } + Item + { + id: spacer + Layout.fillHeight: true + } + Dialog + { + anchors.centerIn: parent + id: dialog + title: "Title" + standardButtons: Dialog.Apply | Dialog.Cancel + + onApplied: + { + + if (configPwd.text === repeatConfigPwd.text) + { console.log("true") + saveConfigFile.open() + } + else + { + configPwd.text = "" + configPwd.placeholderText = qsTr("Passwort stimmt nicht überein") + configPwd.placeholderTextColor = "red" + repeatConfigPwd.placeholderText = qsTr("") + repeatConfigPwd.text = "" + console.log("false") + } + } + onRejected: console.log("Cancel clicked") + GridLayout + { + columns: 2 + Label + { + text: qsTr("Passwort eingeben") + } + TextField + { + id: configPwd + placeholderText: qsTr("Sicherungspasswort festlegen") + } + Label + { + text: qsTr("Passwort wiederholen") + } + TextField + { + id: repeatConfigPwd + placeholderText: qsTr("Sicherungspasswort wiederholen") + } + + } + } + FileDialog + { + id: saveConfigFile + fileMode: FileDialog.SaveFile + + } +} diff --git a/Gui/CompanyConf.qml b/Gui/CompanyConf.qml new file mode 100644 index 0000000..52aa97e --- /dev/null +++ b/Gui/CompanyConf.qml @@ -0,0 +1,17 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls + +Item +{ + property string name: "company" + anchors.fill: parent + + Label + { + text: qsTr("Das Unternehmen") + anchors.centerIn: parent + font.pixelSize: 57 + font.bold: true + } +} diff --git a/Gui/firststart.qml b/Gui/Firststart.qml similarity index 88% rename from Gui/firststart.qml rename to Gui/Firststart.qml index 38544a8..7c2a134 100644 --- a/Gui/firststart.qml +++ b/Gui/Firststart.qml @@ -11,7 +11,10 @@ Item { property string recpass: "" property bool adminAvailable: true + property alias recoverEnc: recoveryPaswordDialog + property alias first: firstStartItem + id: firstStartItem anchors.fill: parent StackView { @@ -87,6 +90,7 @@ Item Dialog { + id: recoveryPaswordDialog modal: true title: qsTr("Wiederherstellung") @@ -115,6 +119,19 @@ Item implicitWidth: 300 placeholderText: qsTr("Hier Wiederherstellungspasswort eingeben") } + Label + { + text: qsTr("Wiederherstellungspasswort eingeben: ") + } + + TextField + { + id: repeatRecoveryPaswordInput + text: "" + echoMode: TextInput.Password + implicitWidth: 300 + placeholderText: qsTr("Hier Wiederherstellungspasswort eingeben") + } } } } diff --git a/Gui/ObjectAddOnContactPerson.qml b/Gui/ObjectAddOnContactPerson.qml index 7d99aae..0d93195 100644 --- a/Gui/ObjectAddOnContactPerson.qml +++ b/Gui/ObjectAddOnContactPerson.qml @@ -231,6 +231,25 @@ GridLayout } } + Component + { + id: highlight + Rectangle + { + width: 230; height: 15 + color: "lightsteelblue"; radius: 5 + y: contactView.currentItem.y + Behavior on y + { + SpringAnimation + { + spring: 3 + damping: 0.2 + } + } + } + } + Rectangle { id: mainRect @@ -242,6 +261,7 @@ GridLayout ListView { id: contactView + implicitHeight: parent.height implicitWidth: parent.width model: contactModel @@ -249,10 +269,13 @@ GridLayout highlight: Rectangle { color: "grey"} highlightFollowsCurrentItem: false + onActiveFocusChanged: if(!focus) currentIndex = -1 delegate: Item + { width: contactView.width + height: 15 MouseArea { @@ -264,6 +287,7 @@ GridLayout } } + Row { //spacing: 9 @@ -297,6 +321,8 @@ GridLayout } } } + + } } } diff --git a/Gui/PyqcrmConf.qml b/Gui/PyqcrmConf.qml new file mode 100644 index 0000000..b37913c --- /dev/null +++ b/Gui/PyqcrmConf.qml @@ -0,0 +1,112 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Item +{ + anchors.fill: parent + TabBar + { + id: bar + width: parent.width + TabButton + { + text: qsTr("Benutzer") + } + TabButton + { + text: qsTr("Datenbank") + } + TabButton + { + text: qsTr("Das Unternehmen") + } + + TabButton + { + text: qsTr("Sicherung") + } + + } + + StackLayout + { + id: confContainer + anchors.fill: parent + currentIndex: bar.currentIndex + Item + { + id: userTab + UsersPage + { + id: usersPage + anchors.fill: parent + } + } + Item + { + id: dbTab + DbConfiguration + { + id: dbConf + anchors.fill: parent + } + } + Item + { + id: companyTab + CompanyConf + { + id: companyConf + anchors.fill: parent + } + } + + Item + { + id: backup + BackupSettings + { + id: backupSettings + anchors.fill: parent + } + } + + } + + RowLayout + { + width: parent.width + anchors.bottom: parent.bottom + Item + { + Layout.fillWidth: true + } + + Button + { + text: qsTr("Ablehnen") + onClicked: appLoader.source = "Dashboard.qml" + } + + Button + { + text: qsTr("Speichern") + onClicked: + { + switch (confContainer.currentIndex) + { + case 1: + console.log("Need to update DB paramenters") + break + + case 2: + console.log("Need to update company's info.") + break + default: + console.log("Need to handle users") + } + } + } + } +} diff --git a/Gui/TopBar.qml b/Gui/TopBar.qml index 758dfb0..16bf968 100644 --- a/Gui/TopBar.qml +++ b/Gui/TopBar.qml @@ -178,8 +178,15 @@ RowLayout id: mainMenu MenuItem { - text: qsTr("Benutzer-Verwaltung") - onTriggered: appLoader.source = "UsersPage.qml" + //text: qsTr("Benutzer-Verwaltung") + //onTriggered: appLoader.source = "UsersPage.qml" + text: qsTr("Einstellungen") + onTriggered: + { + // TODO: Check if logged-in user is admin first!! + + appLoader.source = "PyqcrmConf.qml" + } } MenuSeparator {} MenuItem { text: qsTr("Als PDF exportieren") } diff --git a/Gui/UsersPage.qml b/Gui/UsersPage.qml index 31d8c59..e9a9ec2 100644 --- a/Gui/UsersPage.qml +++ b/Gui/UsersPage.qml @@ -4,6 +4,7 @@ import QtQuick.Controls Item { + property string name: "users" anchors.fill: parent Label diff --git a/Gui/main.qml b/Gui/main.qml index 2e85370..2d65ba1 100644 --- a/Gui/main.qml +++ b/Gui/main.qml @@ -12,6 +12,7 @@ ApplicationWindow visible: true title: "PYQCRM" property string confile: "" + property alias settingsFileDialog: settingsFiledialog TopBar { @@ -80,12 +81,13 @@ ApplicationWindow anchors.centerIn: parent standardButtons: Dialog.Yes | Dialog.No onAccepted: settingsFiledialog.open() - onRejected: appLoader.source= "firststart.qml" + onRejected: appLoader.source= "Firststart.qml" title: qsTr("Einstellungen importieren") } FileDialog { + id: settingsFiledialog title: qsTr("PYQCRM Einstellungen") currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0] diff --git a/enc_key_backup.txt b/enc_key_backup.txt new file mode 100644 index 0000000..a4915d4 --- /dev/null +++ b/enc_key_backup.txt @@ -0,0 +1 @@ +Lj30yFOP7hJmY5Cub1Go8fJz0UE+Zyo9cEqNxfY23Sc= diff --git a/lib/Vermasseln.py b/lib/Vermasseln.py index 7857100..72e3190 100644 --- a/lib/Vermasseln.py +++ b/lib/Vermasseln.py @@ -20,7 +20,7 @@ class Vermasseln: return storable_data - def entschluesseln(self, data, local= True): + def entschluesseln(self, data, local = True): try: data_list = data.split(".") encoded_data = [b64decode(x) for x in data_list] @@ -37,7 +37,7 @@ class Vermasseln: return decrypted_data - def __vermasslungsKobold(self, local= True): + def __vermasslungsKobold(self, local = True): key = platform.processor().encode("utf-8") if local else b"(==daniishtverhaftetwegensexy#)" key = key[0:31] hash_key = SHA256.new(key) diff --git a/pyqcrm.qrc b/pyqcrm.qrc deleted file mode 100644 index 6fd41f3..0000000 --- a/pyqcrm.qrc +++ /dev/null @@ -1,24 +0,0 @@ - - - qtquickcontrols2.conf - images/add.svg - images/addbusiness.svg - images/addperson.svg - images/filter.svg - images/menu.svg - images/search.svg - sounds/error.ogg - sounds/fail2c.ogg - sounds/puzzerr.ogg - sounds/sysnotify.ogg - sounds/wrong.ogg - fonts/Damarwulan.ttf - fonts/HelloStranger.otf - fonts/HussarPrintA.otf - fonts/LittleBirdsRegular.ttf - fonts/ReginaldScript.ttf - images/account.svg - README - LICENSE - - diff --git a/qml.qrc b/qml.qrc index 1e6ca28..7996b66 100644 --- a/qml.qrc +++ b/qml.qrc @@ -42,5 +42,7 @@ Gui/CustomerDetailsView.qml Gui/ReadMe.qml Gui/UsersPage.qml + Gui/PyqcrmConf.qml + Gui/CompanyConf.qml From 82b3c2d403d63331facafda8e0d36e25d977af6a874d7dece10977205ee923e1 Mon Sep 17 00:00:00 2001 From: Daniel Stoppek Date: Wed, 26 Feb 2025 15:24:24 +0100 Subject: [PATCH 4/7] test --- pyqcrm.qrc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 pyqcrm.qrc diff --git a/pyqcrm.qrc b/pyqcrm.qrc new file mode 100644 index 0000000..6fd41f3 --- /dev/null +++ b/pyqcrm.qrc @@ -0,0 +1,24 @@ + + + qtquickcontrols2.conf + images/add.svg + images/addbusiness.svg + images/addperson.svg + images/filter.svg + images/menu.svg + images/search.svg + sounds/error.ogg + sounds/fail2c.ogg + sounds/puzzerr.ogg + sounds/sysnotify.ogg + sounds/wrong.ogg + fonts/Damarwulan.ttf + fonts/HelloStranger.otf + fonts/HussarPrintA.otf + fonts/LittleBirdsRegular.ttf + fonts/ReginaldScript.ttf + images/account.svg + README + LICENSE + + From bd2316dbfb8862ade1c7181a782d13a6d0ec077eb091bb7acbfbf9e872143fa2 Mon Sep 17 00:00:00 2001 From: Daniel Stoppek Date: Wed, 26 Feb 2025 15:35:34 +0100 Subject: [PATCH 5/7] BackupSettings.qml --- Gui/BackupSettings.qml | 2 +- qml.qrc | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Gui/BackupSettings.qml b/Gui/BackupSettings.qml index 4a31706..12813bc 100644 --- a/Gui/BackupSettings.qml +++ b/Gui/BackupSettings.qml @@ -38,7 +38,7 @@ GridLayout { id: saveEncryption text: qsTr("Jetzt sichern!") - onClicked: Firsts.open() + onClicked: recoverEnc.open() } Item { diff --git a/qml.qrc b/qml.qrc index 7996b66..a524421 100644 --- a/qml.qrc +++ b/qml.qrc @@ -10,7 +10,6 @@ Gui/CustomerTable.qml Gui/Dashboard.qml Gui/EmployeeTable.qml - Gui/firststart.qml Gui/main.qml Gui/SearchBar.qml js/qmldict.js @@ -44,5 +43,7 @@ Gui/UsersPage.qml Gui/PyqcrmConf.qml Gui/CompanyConf.qml + Gui/Firststart.qml + Gui/BackupSettings.qml From e52872918180632a91ae9d5d4cb319e3c5aa920755556f654d56d568d2e6488e Mon Sep 17 00:00:00 2001 From: Daniel Stoppek Date: Thu, 27 Feb 2025 08:52:33 +0100 Subject: [PATCH 6/7] BackupSettings --- Gui/BackupSettings.qml | 15 +++++++++++---- Gui/Firststart.qml | 1 - Gui/main.qml | 1 + lib/ConfigLoader.py | 6 ++++++ 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Gui/BackupSettings.qml b/Gui/BackupSettings.qml index 12813bc..475fbb4 100644 --- a/Gui/BackupSettings.qml +++ b/Gui/BackupSettings.qml @@ -2,6 +2,8 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import QtQuick.Dialogs +import QtCore + GridLayout { @@ -14,7 +16,6 @@ GridLayout Layout.alignment: Qt.AlignHCenter text: qsTr("Sicherung") font.pixelSize: 35 - } Label @@ -27,7 +28,7 @@ GridLayout { id: saveConfig text: qsTr("Jetzt sichern!") - onClicked: settingsFileDialog.open() + onClicked: dialog.open() } Label { @@ -38,7 +39,7 @@ GridLayout { id: saveEncryption text: qsTr("Jetzt sichern!") - onClicked: recoverEnc.open() + onClicked: apploader.item.recoverEnc.open() } Item { @@ -98,6 +99,12 @@ GridLayout { id: saveConfigFile fileMode: FileDialog.SaveFile - + nameFilters: ["PYQCRM Recovery files (*.pyqrec)"] + currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0] + onAccepted: + { + var test = config.backupConfig(saveConfigFile.currentFile) + console.log() + } } } diff --git a/Gui/Firststart.qml b/Gui/Firststart.qml index 7c2a134..031d688 100644 --- a/Gui/Firststart.qml +++ b/Gui/Firststart.qml @@ -12,7 +12,6 @@ Item property string recpass: "" property bool adminAvailable: true property alias recoverEnc: recoveryPaswordDialog - property alias first: firstStartItem id: firstStartItem anchors.fill: parent diff --git a/Gui/main.qml b/Gui/main.qml index 2d65ba1..cb948c4 100644 --- a/Gui/main.qml +++ b/Gui/main.qml @@ -14,6 +14,7 @@ ApplicationWindow property string confile: "" property alias settingsFileDialog: settingsFiledialog + TopBar { diff --git a/lib/ConfigLoader.py b/lib/ConfigLoader.py index a3bda34..8b2ee1f 100644 --- a/lib/ConfigLoader.py +++ b/lib/ConfigLoader.py @@ -195,6 +195,7 @@ class ConfigLoader(QObject): except Exception as e: print(str(e)) + def getConfig(self): # print(f"In {__file__} file, getConfig()") # print(self.__config) @@ -212,3 +213,8 @@ class ConfigLoader(QObject): self.__config['pyqcrm']['ENCRYPTION_KEY'] = enc_key self.__saveConfig() + @Slot(str) + def backupConfig(self, pw): + print(pw) + new_config = self.getConfig() + print(new_config) From 73542e808970ae7500cc6b04895ac4a7c30cacf7f960c5c48932e987c107955d Mon Sep 17 00:00:00 2001 From: Daniel Stoppek Date: Thu, 27 Feb 2025 14:45:27 +0100 Subject: [PATCH 7/7] Backup Config --- Gui/BackupSettings.qml | 13 +++++--- Gui/main.qml | 2 +- lib/ConfigLoader.py | 75 ++++++++++++++++++++++++++++-------------- lib/Vermasseln.py | 1 - 4 files changed, 61 insertions(+), 30 deletions(-) diff --git a/Gui/BackupSettings.qml b/Gui/BackupSettings.qml index 475fbb4..31a6076 100644 --- a/Gui/BackupSettings.qml +++ b/Gui/BackupSettings.qml @@ -3,6 +3,8 @@ import QtQuick.Controls import QtQuick.Layouts import QtQuick.Dialogs import QtCore +import "../js/qmldict.js" as JsLib + GridLayout @@ -57,7 +59,8 @@ GridLayout { if (configPwd.text === repeatConfigPwd.text) - { console.log("true") + { + saveConfigFile.open() } else @@ -67,12 +70,12 @@ GridLayout configPwd.placeholderTextColor = "red" repeatConfigPwd.placeholderText = qsTr("") repeatConfigPwd.text = "" - console.log("false") } } onRejected: console.log("Cancel clicked") GridLayout { + id: gridPw columns: 2 Label { @@ -80,6 +83,7 @@ GridLayout } TextField { + id: configPwd placeholderText: qsTr("Sicherungspasswort festlegen") } @@ -89,6 +93,7 @@ GridLayout } TextField { + property string name: "password" id: repeatConfigPwd placeholderText: qsTr("Sicherungspasswort wiederholen") } @@ -103,8 +108,8 @@ GridLayout currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0] onAccepted: { - var test = config.backupConfig(saveConfigFile.currentFile) - console.log() + var pw = JsLib.parseForm(gridPw) + config.backupConfig(saveConfigFile.currentFile, pw["password"]) } } } diff --git a/Gui/main.qml b/Gui/main.qml index cb948c4..3d43405 100644 --- a/Gui/main.qml +++ b/Gui/main.qml @@ -93,7 +93,7 @@ ApplicationWindow title: qsTr("PYQCRM Einstellungen") currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0] modality: "ApplicationModal" - nameFilters: [qsTr("PYQCRM Einstellungen (*.pyqcrm)")] + nameFilters: [qsTr("PYQCRM Einstellungen (*.pyqrec)")] onAccepted: { exportFilePassword.open() diff --git a/lib/ConfigLoader.py b/lib/ConfigLoader.py index 8b2ee1f..b56ce66 100644 --- a/lib/ConfigLoader.py +++ b/lib/ConfigLoader.py @@ -110,6 +110,12 @@ class ConfigLoader(QObject): self.backupEncryptionKey.emit() return admin + """###################################################""" + """ """ + """ TODO: Rename method and rename self.__encrypt_key """ + """ """ + """###################################################""" + @Slot(str, str) def saveRecoveryKey(self, recovery_file, recovery_password): # print(f"In {__file__} file, saveRecoveryKey()") @@ -131,30 +137,39 @@ class ConfigLoader(QObject): @Slot(str, str) def getRecoveryKey(self, recovery_file, recovery_password): - # print(f"In {__file__} file, getRecoveryKey()") - local = False rec_file = urlparse(recovery_file) rec_file = rec_file.path if os.name == "nt": rec_file = rec_file [1:] try: - with open(rec_file, "r") as f: - rf = f.read() - rf = Vermasseln().entschluesseln(rf, local) - ek = rf[128:] - ek = ek[:-32] - password = rf[:128] - salt = rf[-32:] - ok = self.__checkRecoveryPassword(recovery_password, password, salt) - if ok: - self.__setEncryptionKey(ek) - self.configurationReady.emit() - else: - self.__invalidateEncryptionKey() - self.invalidEncryptionKey.emit() + ek = self.__parseImport(rec_file, recovery_password) + + if ek: + self.__setEncryptionKey(ek) + self.configurationReady.emit() + else: + self.__invalidateEncryptionKey() + self.invalidEncryptionKey.emit() except Exception as e: print(str(e)) + def __parseImport(self, rec_file, recovery_password): + local = False + with open(rec_file, "r") as f: + + rf = f.read() + rf = Vermasseln().entschluesseln(rf, local) + ek = rf[128:] + ek = ek[:-32] + password = rf[:128] + salt = rf[-32:] + ok = self.__checkRecoveryPassword(recovery_password, password, salt) + if ok: + return ek + else: + return None + + def __invalidateEncryptionKey(self): # print(f"In {__file__} file, __invalidateEncryptionKey()") self.__config['pyqcrm']['ENCRYPTION_KEY_VALID'] = 'No' @@ -173,13 +188,25 @@ class ConfigLoader(QObject): @Slot(str, str) # todo: non local encryption def importConfig(self, confile, password): - # print(f"In {__file__} file, importConfig()") confile = urlparse(confile) confile = confile.path - if os.name == "nt": confile = confile[1:] - shutil.copyfile(confile, self.config_dir+ '/pyqcrm.toml') + try: + ek = self.__parseImport(confile, password) + if ek: + self.__config = toml.loads(ek) + self.__saveConfig() + self.configurationReady.emit() + else: + self.invalidEncryptionKey.emit() + except Exception as e: + print(str(e)) + + + + + def __configLoad(self): # print(f"In {__file__} file, __configLoad()") @@ -213,8 +240,8 @@ class ConfigLoader(QObject): self.__config['pyqcrm']['ENCRYPTION_KEY'] = enc_key self.__saveConfig() - @Slot(str) - def backupConfig(self, pw): - print(pw) - new_config = self.getConfig() - print(new_config) + @Slot(str, str) + def backupConfig(self, filename, password): + self.__encrypt_key = toml.dumps(self.getConfig()) + self.saveRecoveryKey(filename, password) + diff --git a/lib/Vermasseln.py b/lib/Vermasseln.py index 72e3190..67570cb 100644 --- a/lib/Vermasseln.py +++ b/lib/Vermasseln.py @@ -53,7 +53,6 @@ class Vermasseln: hash_pw = (salt + password).encode("utf-8") h_obj = SHA3_512.new(hash_pw) password = salt + "$" + h_obj.hexdigest() - return password