Compare commits
20 Commits
eacd3dacc7
...
e81407b43d
| Author | SHA256 | Date | |
|---|---|---|---|
| e81407b43d | |||
| 73542e8089 | |||
| 89e96422cc | |||
| e0ec99098e | |||
| 4c62834369 | |||
| e528729181 | |||
| d7928d25fc | |||
| bd2316dbfb | |||
| 82b3c2d403 | |||
| 8ee303227e | |||
| 2a09fed57a | |||
| e7d0b7cdb5 | |||
| f0cde5ec20 | |||
| 3738bf1c6e | |||
| dec4ca59f0 | |||
| 7228d5fae9 | |||
| e2410d0852 | |||
| a68ae311bf | |||
| cc25f85771 | |||
| fdaae34678 |
@@ -11,6 +11,7 @@ GridLayout
|
|||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
rowSpacing: 9
|
rowSpacing: 9
|
||||||
|
|
||||||
|
|
||||||
//// New grid row
|
//// New grid row
|
||||||
|
|
||||||
Label
|
Label
|
||||||
@@ -218,7 +219,9 @@ GridLayout
|
|||||||
|
|
||||||
function checkObjectField()
|
function checkObjectField()
|
||||||
{
|
{
|
||||||
|
|
||||||
return street.text.trim() && houseno.text.trim() &&
|
return street.text.trim() && houseno.text.trim() &&
|
||||||
|
|
||||||
(postcode.editText.trim() || postcode.currentText.trim()) &&
|
(postcode.editText.trim() || postcode.currentText.trim()) &&
|
||||||
(city.editText.trim() || city.currentText.trim()) &&
|
(city.editText.trim() || city.currentText.trim()) &&
|
||||||
cleaningproducts.text.trim()
|
cleaningproducts.text.trim()
|
||||||
|
|||||||
115
Gui/BackupSettings.qml
Normal file
115
Gui/BackupSettings.qml
Normal 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"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,9 @@ Item
|
|||||||
{
|
{
|
||||||
property string recpass: ""
|
property string recpass: ""
|
||||||
property bool adminAvailable: true
|
property bool adminAvailable: true
|
||||||
|
property alias recoverEnc: recoveryPaswordDialog
|
||||||
|
|
||||||
|
id: firstStartItem
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
StackView
|
StackView
|
||||||
{
|
{
|
||||||
@@ -87,6 +89,7 @@ Item
|
|||||||
|
|
||||||
Dialog
|
Dialog
|
||||||
{
|
{
|
||||||
|
|
||||||
id: recoveryPaswordDialog
|
id: recoveryPaswordDialog
|
||||||
modal: true
|
modal: true
|
||||||
title: qsTr("Wiederherstellung")
|
title: qsTr("Wiederherstellung")
|
||||||
@@ -115,6 +118,19 @@ Item
|
|||||||
implicitWidth: 300
|
implicitWidth: 300
|
||||||
placeholderText: qsTr("Hier Wiederherstellungspasswort eingeben")
|
placeholderText: qsTr("Hier Wiederherstellungspasswort eingeben")
|
||||||
}
|
}
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
text: qsTr("Wiederherstellungspasswort eingeben: ")
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField
|
||||||
|
{
|
||||||
|
id: repeatRecoveryPaswordInput
|
||||||
|
text: ""
|
||||||
|
echoMode: TextInput.Password
|
||||||
|
implicitWidth: 300
|
||||||
|
placeholderText: qsTr("Hier Wiederherstellungspasswort eingeben")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,8 +269,10 @@ GridLayout
|
|||||||
highlightFollowsCurrentItem: false
|
highlightFollowsCurrentItem: false
|
||||||
onActiveFocusChanged: if(!focus) currentIndex = -1
|
onActiveFocusChanged: if(!focus) currentIndex = -1
|
||||||
delegate: Item
|
delegate: Item
|
||||||
|
|
||||||
{
|
{
|
||||||
width: contactView.width
|
width: contactView.width
|
||||||
|
|
||||||
height: 15
|
height: 15
|
||||||
MouseArea
|
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
|
Row
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ Item
|
|||||||
{
|
{
|
||||||
text: qsTr("Das Unternehmen")
|
text: qsTr("Das Unternehmen")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TabButton
|
||||||
|
{
|
||||||
|
text: qsTr("Sicherung")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StackLayout
|
StackLayout
|
||||||
@@ -55,6 +61,17 @@ Item
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
id: backup
|
||||||
|
BackupSettings
|
||||||
|
{
|
||||||
|
id: backupSettings
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout
|
RowLayout
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ ApplicationWindow
|
|||||||
visible: true
|
visible: true
|
||||||
title: "PYQCRM"
|
title: "PYQCRM"
|
||||||
property string confile: ""
|
property string confile: ""
|
||||||
|
property alias settingsFileDialog: settingsFiledialog
|
||||||
|
|
||||||
|
|
||||||
TopBar
|
TopBar
|
||||||
{
|
{
|
||||||
@@ -80,17 +82,18 @@ ApplicationWindow
|
|||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
standardButtons: Dialog.Yes | Dialog.No
|
standardButtons: Dialog.Yes | Dialog.No
|
||||||
onAccepted: settingsFiledialog.open()
|
onAccepted: settingsFiledialog.open()
|
||||||
onRejected: appLoader.source= "firststart.qml"
|
onRejected: appLoader.source= "Firststart.qml"
|
||||||
title: qsTr("Einstellungen importieren")
|
title: qsTr("Einstellungen importieren")
|
||||||
}
|
}
|
||||||
|
|
||||||
FileDialog
|
FileDialog
|
||||||
{
|
{
|
||||||
|
|
||||||
id: settingsFiledialog
|
id: settingsFiledialog
|
||||||
title: qsTr("PYQCRM Einstellungen")
|
title: qsTr("PYQCRM Einstellungen")
|
||||||
currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0]
|
currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0]
|
||||||
modality: "ApplicationModal"
|
modality: "ApplicationModal"
|
||||||
nameFilters: [qsTr("PYQCRM Einstellungen (*.pyqcrm)")]
|
nameFilters: [qsTr("PYQCRM Einstellungen (*.pyqrec)")]
|
||||||
onAccepted:
|
onAccepted:
|
||||||
{
|
{
|
||||||
exportFilePassword.open()
|
exportFilePassword.open()
|
||||||
|
|||||||
1
enc_key_backup.txt
Normal file
1
enc_key_backup.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Lj30yFOP7hJmY5Cub1Go8fJz0UE+Zyo9cEqNxfY23Sc=
|
||||||
@@ -110,6 +110,12 @@ class ConfigLoader(QObject):
|
|||||||
self.backupEncryptionKey.emit()
|
self.backupEncryptionKey.emit()
|
||||||
return admin
|
return admin
|
||||||
|
|
||||||
|
"""###################################################"""
|
||||||
|
""" """
|
||||||
|
""" TODO: Rename method and rename self.__encrypt_key """
|
||||||
|
""" """
|
||||||
|
"""###################################################"""
|
||||||
|
|
||||||
@Slot(str, str)
|
@Slot(str, str)
|
||||||
def saveRecoveryKey(self, recovery_file, recovery_password):
|
def saveRecoveryKey(self, recovery_file, recovery_password):
|
||||||
# print(f"In {__file__} file, saveRecoveryKey()")
|
# print(f"In {__file__} file, saveRecoveryKey()")
|
||||||
@@ -131,14 +137,26 @@ class ConfigLoader(QObject):
|
|||||||
|
|
||||||
@Slot(str, str)
|
@Slot(str, str)
|
||||||
def getRecoveryKey(self, recovery_file, recovery_password):
|
def getRecoveryKey(self, recovery_file, recovery_password):
|
||||||
# print(f"In {__file__} file, getRecoveryKey()")
|
|
||||||
local = False
|
|
||||||
rec_file = urlparse(recovery_file)
|
rec_file = urlparse(recovery_file)
|
||||||
rec_file = rec_file.path
|
rec_file = rec_file.path
|
||||||
if os.name == "nt":
|
if os.name == "nt":
|
||||||
rec_file = rec_file [1:]
|
rec_file = rec_file [1:]
|
||||||
try:
|
try:
|
||||||
|
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:
|
with open(rec_file, "r") as f:
|
||||||
|
|
||||||
rf = f.read()
|
rf = f.read()
|
||||||
rf = Vermasseln().entschluesseln(rf, local)
|
rf = Vermasseln().entschluesseln(rf, local)
|
||||||
ek = rf[128:]
|
ek = rf[128:]
|
||||||
@@ -147,13 +165,10 @@ class ConfigLoader(QObject):
|
|||||||
salt = rf[-32:]
|
salt = rf[-32:]
|
||||||
ok = self.__checkRecoveryPassword(recovery_password, password, salt)
|
ok = self.__checkRecoveryPassword(recovery_password, password, salt)
|
||||||
if ok:
|
if ok:
|
||||||
self.__setEncryptionKey(ek)
|
return ek
|
||||||
self.configurationReady.emit()
|
|
||||||
else:
|
else:
|
||||||
self.__invalidateEncryptionKey()
|
return None
|
||||||
self.invalidEncryptionKey.emit()
|
|
||||||
except Exception as e:
|
|
||||||
print(str(e))
|
|
||||||
|
|
||||||
def __invalidateEncryptionKey(self):
|
def __invalidateEncryptionKey(self):
|
||||||
# print(f"In {__file__} file, __invalidateEncryptionKey()")
|
# print(f"In {__file__} file, __invalidateEncryptionKey()")
|
||||||
@@ -173,13 +188,25 @@ class ConfigLoader(QObject):
|
|||||||
|
|
||||||
@Slot(str, str) # todo: non local encryption
|
@Slot(str, str) # todo: non local encryption
|
||||||
def importConfig(self, confile, password):
|
def importConfig(self, confile, password):
|
||||||
# print(f"In {__file__} file, importConfig()")
|
|
||||||
confile = urlparse(confile)
|
confile = urlparse(confile)
|
||||||
confile = confile.path
|
confile = confile.path
|
||||||
|
|
||||||
if os.name == "nt":
|
if os.name == "nt":
|
||||||
confile = confile[1:]
|
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):
|
def __configLoad(self):
|
||||||
# print(f"In {__file__} file, __configLoad()")
|
# print(f"In {__file__} file, __configLoad()")
|
||||||
@@ -195,6 +222,7 @@ class ConfigLoader(QObject):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(str(e))
|
print(str(e))
|
||||||
|
|
||||||
|
|
||||||
def getConfig(self):
|
def getConfig(self):
|
||||||
# print(f"In {__file__} file, getConfig()")
|
# print(f"In {__file__} file, getConfig()")
|
||||||
# print(self.__config)
|
# print(self.__config)
|
||||||
@@ -212,3 +240,8 @@ class ConfigLoader(QObject):
|
|||||||
self.__config['pyqcrm']['ENCRYPTION_KEY'] = enc_key
|
self.__config['pyqcrm']['ENCRYPTION_KEY'] = enc_key
|
||||||
self.__saveConfig()
|
self.__saveConfig()
|
||||||
|
|
||||||
|
@Slot(str, str)
|
||||||
|
def backupConfig(self, filename, password):
|
||||||
|
self.__encrypt_key = toml.dumps(self.getConfig())
|
||||||
|
self.saveRecoveryKey(filename, password)
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ class Vermasseln:
|
|||||||
hash_pw = (salt + password).encode("utf-8")
|
hash_pw = (salt + password).encode("utf-8")
|
||||||
h_obj = SHA3_512.new(hash_pw)
|
h_obj = SHA3_512.new(hash_pw)
|
||||||
password = salt + "$" + h_obj.hexdigest()
|
password = salt + "$" + h_obj.hexdigest()
|
||||||
|
|
||||||
return password
|
return password
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
3
qml.qrc
3
qml.qrc
@@ -10,7 +10,6 @@
|
|||||||
<file>Gui/CustomerTable.qml</file>
|
<file>Gui/CustomerTable.qml</file>
|
||||||
<file>Gui/Dashboard.qml</file>
|
<file>Gui/Dashboard.qml</file>
|
||||||
<file>Gui/EmployeeTable.qml</file>
|
<file>Gui/EmployeeTable.qml</file>
|
||||||
<file>Gui/firststart.qml</file>
|
|
||||||
<file>Gui/main.qml</file>
|
<file>Gui/main.qml</file>
|
||||||
<file>Gui/SearchBar.qml</file>
|
<file>Gui/SearchBar.qml</file>
|
||||||
<file>js/qmldict.js</file>
|
<file>js/qmldict.js</file>
|
||||||
@@ -44,5 +43,7 @@
|
|||||||
<file>Gui/UsersPage.qml</file>
|
<file>Gui/UsersPage.qml</file>
|
||||||
<file>Gui/PyqcrmConf.qml</file>
|
<file>Gui/PyqcrmConf.qml</file>
|
||||||
<file>Gui/CompanyConf.qml</file>
|
<file>Gui/CompanyConf.qml</file>
|
||||||
|
<file>Gui/Firststart.qml</file>
|
||||||
|
<file>Gui/BackupSettings.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
Reference in New Issue
Block a user