Compare commits

...

20 Commits

Author SHA256 Message Date
e81407b43d Merge linuxero 2025-02-27 14:48:08 +01:00
73542e8089 Backup Config 2025-02-27 14:45:27 +01:00
89e96422cc Merge branch 'refs/heads/linuxero' 2025-02-27 14:44:13 +01:00
e0ec99098e Fixing ObjectAddOnContactPerson.qml conflict 2025-02-27 14:28:27 +01:00
4c62834369 merge main 2025-02-27 09:39:40 +01:00
e528729181 BackupSettings 2025-02-27 08:52:33 +01:00
d7928d25fc Objekte anlegen 2025-02-26 16:59:20 +01:00
bd2316dbfb BackupSettings.qml 2025-02-26 15:35:34 +01:00
82b3c2d403 test 2025-02-26 15:24:24 +01:00
8ee303227e Merge linuxero 2025-02-26 15:20:33 +01:00
2a09fed57a Test 2025-02-26 15:15:39 +01:00
e7d0b7cdb5 i dont know what im doing 2025-02-26 15:10:42 +01:00
f0cde5ec20 Fehler 2025-02-26 15:09:28 +01:00
3738bf1c6e Mitarbeiter anlegen funktioniert 2025-02-26 10:33:01 +01:00
dec4ca59f0 Merge linuxero 2025-02-26 09:23:28 +01:00
7228d5fae9 Merge branch 'main' into schnacke
asdasd
2025-02-25 16:24:15 +01:00
e2410d0852 Änderung AddNewObject 2025-02-25 16:23:49 +01:00
a68ae311bf Test 2025-02-25 16:21:09 +01:00
cc25f85771 Objekt Formular bearbeitet 2025-02-25 15:58:58 +01:00
fdaae34678 Änderungen letzt Woche 2025-02-24 09:28:40 +01:00
10 changed files with 213 additions and 34 deletions

View File

@@ -11,6 +11,7 @@ GridLayout
Layout.fillHeight: true
rowSpacing: 9
//// New grid row
Label
@@ -218,7 +219,9 @@ GridLayout
function checkObjectField()
{
return street.text.trim() && houseno.text.trim() &&
(postcode.editText.trim() || postcode.currentText.trim()) &&
(city.editText.trim() || city.currentText.trim()) &&
cleaningproducts.text.trim()

115
Gui/BackupSettings.qml Normal file
View File

@@ -0,0 +1,115 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Dialogs
import QtCore
import "../js/qmldict.js" as JsLib
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: dialog.open()
}
Label
{
text: qsTr("Verschlüsselung")
Layout.alignment: Qt.AlignRight
}
Button
{
id: saveEncryption
text: qsTr("Jetzt sichern!")
onClicked: apploader.item.recoverEnc.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)
{
saveConfigFile.open()
}
else
{
configPwd.text = ""
configPwd.placeholderText = qsTr("Passwort stimmt nicht überein")
configPwd.placeholderTextColor = "red"
repeatConfigPwd.placeholderText = qsTr("")
repeatConfigPwd.text = ""
}
}
onRejected: console.log("Cancel clicked")
GridLayout
{
id: gridPw
columns: 2
Label
{
text: qsTr("Passwort eingeben")
}
TextField
{
id: configPwd
placeholderText: qsTr("Sicherungspasswort festlegen")
}
Label
{
text: qsTr("Passwort wiederholen")
}
TextField
{
property string name: "password"
id: repeatConfigPwd
placeholderText: qsTr("Sicherungspasswort wiederholen")
}
}
}
FileDialog
{
id: saveConfigFile
fileMode: FileDialog.SaveFile
nameFilters: ["PYQCRM Recovery files (*.pyqrec)"]
currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0]
onAccepted:
{
var pw = JsLib.parseForm(gridPw)
config.backupConfig(saveConfigFile.currentFile, pw["password"])
}
}
}

View File

@@ -11,7 +11,9 @@ Item
{
property string recpass: ""
property bool adminAvailable: true
property alias recoverEnc: recoveryPaswordDialog
id: firstStartItem
anchors.fill: parent
StackView
{
@@ -87,6 +89,7 @@ Item
Dialog
{
id: recoveryPaswordDialog
modal: true
title: qsTr("Wiederherstellung")
@@ -115,6 +118,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")
}
}
}
}

View File

@@ -269,8 +269,10 @@ GridLayout
highlightFollowsCurrentItem: false
onActiveFocusChanged: if(!focus) currentIndex = -1
delegate: Item
{
width: contactView.width
height: 15
MouseArea
{
@@ -282,17 +284,6 @@ GridLayout
}
}
MouseArea
{
id: clickedRow
anchors.fill: parent
onClicked:
{
//var currentIndex = index
console.log(index)
console.log(contactView.currentItem.y)
}
}
Row
{

View File

@@ -21,6 +21,12 @@ Item
{
text: qsTr("Das Unternehmen")
}
TabButton
{
text: qsTr("Sicherung")
}
}
StackLayout
@@ -55,6 +61,17 @@ Item
anchors.fill: parent
}
}
Item
{
id: backup
BackupSettings
{
id: backupSettings
anchors.fill: parent
}
}
}
RowLayout

View File

@@ -12,6 +12,8 @@ ApplicationWindow
visible: true
title: "PYQCRM"
property string confile: ""
property alias settingsFileDialog: settingsFiledialog
TopBar
{
@@ -80,17 +82,18 @@ 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]
modality: "ApplicationModal"
nameFilters: [qsTr("PYQCRM Einstellungen (*.pyqcrm)")]
nameFilters: [qsTr("PYQCRM Einstellungen (*.pyqrec)")]
onAccepted:
{
exportFilePassword.open()

1
enc_key_backup.txt Normal file
View File

@@ -0,0 +1 @@
Lj30yFOP7hJmY5Cub1Go8fJz0UE+Zyo9cEqNxfY23Sc=

View File

@@ -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()")
@@ -195,6 +222,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 +240,8 @@ class ConfigLoader(QObject):
self.__config['pyqcrm']['ENCRYPTION_KEY'] = enc_key
self.__saveConfig()
@Slot(str, str)
def backupConfig(self, filename, password):
self.__encrypt_key = toml.dumps(self.getConfig())
self.saveRecoveryKey(filename, password)

View File

@@ -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

View File

@@ -10,7 +10,6 @@
<file>Gui/CustomerTable.qml</file>
<file>Gui/Dashboard.qml</file>
<file>Gui/EmployeeTable.qml</file>
<file>Gui/firststart.qml</file>
<file>Gui/main.qml</file>
<file>Gui/SearchBar.qml</file>
<file>js/qmldict.js</file>
@@ -44,5 +43,7 @@
<file>Gui/UsersPage.qml</file>
<file>Gui/PyqcrmConf.qml</file>
<file>Gui/CompanyConf.qml</file>
<file>Gui/Firststart.qml</file>
<file>Gui/BackupSettings.qml</file>
</qresource>
</RCC>