diff --git a/Gui/AddCustomer.qml b/Gui/AddCustomer.qml
index 2665c95..faff464 100644
--- a/Gui/AddCustomer.qml
+++ b/Gui/AddCustomer.qml
@@ -2,6 +2,7 @@ import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Controls.Fusion
+import QtQuick.Dialogs
import "../js/qmldict.js" as JsLib
ColumnLayout
@@ -258,6 +259,8 @@ ColumnLayout
id: spacer3
Layout.fillHeight: true
}
+
+
function isEmptyField()
{
if (!firmenName.text.trim() || !street.text.trim() || !city.text.trim())
diff --git a/Gui/AdminUserConfig.qml b/Gui/AdminUserConfig.qml
index 04a2353..6863a15 100644
--- a/Gui/AdminUserConfig.qml
+++ b/Gui/AdminUserConfig.qml
@@ -70,9 +70,13 @@ GridLayout
{
Layout.fillHeight: true
}
+
+
+
Component.onCompleted:
{
config.usernameNotAvailable.connect(usernameNotAvailable)
+
}
function usernameNotAvailable()
{
@@ -81,6 +85,7 @@ GridLayout
benutzerNamelabel.color = "red"
benutzerNamelabel.font.bold = true
}
+
}
diff --git a/Gui/firststart.qml b/Gui/firststart.qml
index ebe38c4..579c52e 100644
--- a/Gui/firststart.qml
+++ b/Gui/firststart.qml
@@ -2,16 +2,26 @@ import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Dialogs
+import QtCore
import "../js/qmldict.js" as Qmldict
Item
{
+ property string recpass: ""
+ property bool adminAvailable: true
Component.onCompleted:
{
config.dbConnectionError.connect(onDbConnectionError)
config.adminUserError.connect(onAdminUserError)
+ config.backupEncryptionKey.connect(onBackupEncryptionKey)
+
+ }
+
+ function onBackupEncryptionKey()
+ {
+ recoveryDialog.open()
}
function onDbConnectionError(msg, success)
@@ -27,8 +37,43 @@ Item
encryptPwDialog.open()
}
else
+ {
+ adminAvailable = false
firstStart.push("AdminUserConfig.qml")
+ }
+
}
+ MessageDialog
+ {
+ id: recoveryDialog
+
+ text: qsTr("Diesen Wiederherstellungscode musst du sicher aufbewahren!\nMöchtest du das jetzt machen?")
+ title: qsTr("Wiederherstellen")
+ buttons: MessageDialog.Yes | MessageDialog.No
+ onAccepted: saveRecoveryDialog.open()
+
+ }
+ FileDialog
+ {
+ id: saveRecoveryDialog
+ title: qsTr("Wiederherstellungsdatei")
+ fileMode: adminAvailable? FileDialog.OpenFile: FileDialog.SaveFile
+ nameFilters: ["PYQCRM Recovery files (*.pyqrec)"]
+ currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0]
+ onAccepted:
+ {
+ if (!adminAvailable) config.saveRecoveryKey(saveRecoveryDialog.currentFile, recpass)
+ else
+ {
+ config.getRecoveryKey(saveRecoveryDialog.currentFile, recpass)
+
+ }
+ appLoader.source = "Dashboard.qml"
+ topBar.visible = true
+ }
+
+ }
+
MessageDialog
{
@@ -43,15 +88,14 @@ Item
{
id: encryptPwDialog
modal: true
- title: qsTr("Encryption Key")
+ title: qsTr("Wiederherstellung")
anchors.centerIn: parent
standardButtons: Dialog.Ok | Dialog.Cancel
onAccepted:
{
- // TODO: signal for EncryptionKey testing
- config.setEncyrptKey(encryptPassword.text)
- appLoader.source = "Dashboard.qml"
- topBar.visible = true
+ recpass = encryptPassword.text
+ saveRecoveryDialog.open()
+
}
ColumnLayout
{
@@ -59,7 +103,7 @@ Item
{
Label
{
- text: qsTr("Encryption Key eingeben:")
+ text: qsTr("Wiederherstellungspasswort eingeben: ")
}
TextField
@@ -67,12 +111,14 @@ Item
id: encryptPassword
echoMode: TextInput.Password
implicitWidth: 300
- placeholderText: qsTr("Hier Encryption Key eingeben")
+ placeholderText: qsTr("Hier Wiederherstellungspasswort eingeben")
}
}
}
}
+
+
anchors.fill: parent
StackView
{
@@ -129,8 +175,8 @@ Item
admin = config.addAdminUser(pyqcrm_conf)
if (admin)
{
- appLoader.source = "Dashboard.qml"
- topBar.visible = true
+ //appLoader.source = "Dashboard.qml"
+ //topBar.visible = true
}
else
{
diff --git a/doc/.$Programmstart Diagramm.drawio.dtmp b/doc/.$Programmstart Diagramm.drawio.dtmp
deleted file mode 100644
index 2e2067a..0000000
--- a/doc/.$Programmstart Diagramm.drawio.dtmp
+++ /dev/null
@@ -1,288 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/Programmstart Diagramm.drawio b/doc/Programmstart Diagramm.drawio
index 1aea176..a240a8c 100644
--- a/doc/Programmstart Diagramm.drawio
+++ b/doc/Programmstart Diagramm.drawio
@@ -81,7 +81,7 @@
-
+
@@ -91,12 +91,12 @@
-
+
-
+
-
+
@@ -111,7 +111,7 @@
-
+
@@ -121,7 +121,7 @@
-
+
@@ -174,7 +174,7 @@
-
+
@@ -197,10 +197,7 @@
-
-
-
-
+
@@ -221,18 +218,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -243,38 +229,32 @@
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
@@ -282,6 +262,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/Programmstart Diagramm.pdf b/doc/Programmstart Diagramm.pdf
index 259a89a..055acff 100644
Binary files a/doc/Programmstart Diagramm.pdf and b/doc/Programmstart Diagramm.pdf differ
diff --git a/lib/ConfigLoader.py b/lib/ConfigLoader.py
index 1f0e165..4922204 100644
--- a/lib/ConfigLoader.py
+++ b/lib/ConfigLoader.py
@@ -24,7 +24,8 @@ class ConfigLoader(QObject):
dbConnectionError = Signal(str, bool)
adminUserError = Signal(str, bool)
usernameNotAvailable = Signal()
- configurationReady = Signal()
+ configurationReady = Signal(bool)
+ backupEncryptionKey = Signal()
def __init__(self):
super().__init__()
@@ -36,6 +37,51 @@ class ConfigLoader(QObject):
else:
config_dir.mkdir(0o750, True, True)
+ @Slot(str, str)
+ def saveRecoveryKey(self, recovery_file, recovery_password):
+ rp = self.__setRecoveryPassword(recovery_password)
+ rf = rp[1] + self.__encrypt_key + rp[0]
+ rf = Vermasseln().oscarVermasseln(rf)
+ rec_file = urlparse(recovery_file)
+ rec_file = rec_file.path
+ if os.name == "nt":
+ rec_file = rec_file [1:]
+ try:
+ with open(rec_file, "w") as f:
+ f.write(rf)
+ self.configurationReady.emit(True)
+ except Exception as e:
+ print(str(e))
+
+
+ @Slot(str, str)
+ def getRecoveryKey(self, recovery_file, recovery_password):
+ 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)
+ ek = rf[128:]
+ ek = ek[:-32]
+ password = rf[:128]
+ salt = rf[-32:]
+ ok = self.__checkRecoveryPassword(recovery_password, password, salt)
+ if ok:
+ self.configurationReady.emit(True)
+ else:
+ self.configurationReady.emit(False)
+ except Exception as e:
+ print(str(e))
+
+ def __checkRecoveryPassword(self, recovery_password, password, salt):
+ rp = self.__setRecoveryPassword(recovery_password, salt)
+ return rp[1] == password
+
+
+
@Slot(str, str)
def importConfig(self, confile, password):
@@ -52,6 +98,8 @@ class ConfigLoader(QObject):
if not admin:
self.usernameNotAvailable.emit()
+ else:
+ self.backupEncryptionKey.emit()
return admin
@Slot(dict, result= bool)
@@ -66,7 +114,7 @@ class ConfigLoader(QObject):
self.__saveConfig()
conf = self.__checkAdminUser()
if conf:
- self.configurationReady.emit()
+ self.configurationReady.emit(True)
@@ -75,6 +123,7 @@ class ConfigLoader(QObject):
with open (self.config_dir + '/pyqcrm.toml', 'r') as f:
config = f.read()
self.__config = toml.loads(Vermasseln().entschluesseln(config))
+ self.configurationReady.emit(True)
except FileNotFoundError:
print("Konnte die Konfiguration nicht laden.")
except TypeError:
@@ -87,8 +136,8 @@ class ConfigLoader(QObject):
return self.__config
def __initializeConfig(self):
- encrypt_key = b64encode(get_random_bytes(32)).decode("utf-8")
- conf = f"[pyqcrm]\nVERSION = \"{self.__version}\"\nENCRYPTION_KEY = \"{encrypt_key}\"\n\n"
+ self.__encrypt_key = b64encode(get_random_bytes(32)).decode("utf-8")
+ conf = f"[pyqcrm]\nVERSION = \"{self.__version}\"\nENCRYPTION_KEY = \"{self.__encrypt_key}\"\n\n"
return conf
@@ -114,12 +163,13 @@ class ConfigLoader(QObject):
self.adminUserError.emit("Admin vorhanden", True)
return True
- @Slot(str)
- def setEncyrptKey(self, key):
- self.__config['pyqcrm']['ENCRYPTION_KEY'] = key
- self.__saveConfig()
+
+ def __setRecoveryPassword(self, key, salt = None):
+ key = Vermasseln.userPasswordHash(key, salt)
+ return key.split("$")
def __saveConfig(self):
+
try:
with open (self.config_dir + '/pyqcrm.toml', 'w') as f:
config = Vermasseln().oscarVermasseln(toml.dumps(self.__config))
diff --git a/main.py b/main.py
index b1b27a2..6826d29 100644
--- a/main.py
+++ b/main.py
@@ -30,16 +30,19 @@ am = None
bm = None
user = None
-def initializeProgram():
- global am, bad_config, bm, user
- dbconf = config.getConfig()['database']
- DbManager(dbconf)
- bad_config = False
- bm = BusinessModel()
- user = UserManager()
- am = AddressModel()
-
- publishContext()
+def initializeProgram(conf_ok):
+ if conf_ok:
+ global am, bad_config, bm, user
+ dbconf = config.getConfig()['database']
+ DbManager(dbconf)
+ bad_config = False
+ bm = BusinessModel()
+ user = UserManager()
+ am = AddressModel()
+ publishContext()
+ else:
+ # TODO: show message and exit program
+ print("Kein Zugriff auf die Datenbank")
def publishContext():
global engine