Login, user in datenbank und encryption key

This commit is contained in:
2024-12-02 16:15:26 +01:00
parent 70ad4d557b
commit 5bf35ce12a
9 changed files with 309 additions and 309 deletions

View File

@@ -24,6 +24,7 @@ GridLayout
Label Label
{ {
id: benutzerNamelabel
text: qsTr("Benutzername:") text: qsTr("Benutzername:")
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
} }
@@ -69,4 +70,17 @@ GridLayout
{ {
Layout.fillHeight: true Layout.fillHeight: true
} }
Component.onCompleted:
{
config.usernameNotAvailable.connect(usernameNotAvailable)
}
function usernameNotAvailable()
{
benutzerName.placeholderText = qsTr ("Benutzername ist bereits vergeben")
benutzerName.clear()
benutzerNamelabel.color = "red"
benutzerNamelabel.font.bold = true
}
} }

View File

@@ -37,6 +37,7 @@ RowLayout
implicitWidth: kunden.implicitContentWidth + 10 implicitWidth: kunden.implicitContentWidth + 10
onClicked: onClicked:
{ {
// TODO: here we should call the model
appLoader.source = "CustomerTables.qml" appLoader.source = "CustomerTables.qml"
} }
} }

View File

@@ -45,7 +45,6 @@ Item
firstStart.push("AdminUserConfig.qml") firstStart.push("AdminUserConfig.qml")
} }
MessageDialog MessageDialog
{ {
id: conErrDialog id: conErrDialog
@@ -62,7 +61,13 @@ Item
title: qsTr("Encryption Key") title: qsTr("Encryption Key")
anchors.centerIn: parent anchors.centerIn: parent
standardButtons: Dialog.Ok | Dialog.Cancel standardButtons: Dialog.Ok | Dialog.Cancel
onAccepted: config.setEncyrptKey(encryptPassword.text) onAccepted:
{
// TODO: signal for EncryptionKey testing
config.setEncyrptKey(encryptPassword.text)
appLoader.source = "Dashboard.qml"
topBar.visible = true
}
ColumnLayout ColumnLayout
{ {
RowLayout RowLayout
@@ -89,6 +94,7 @@ Item
id: firstStart id: firstStart
anchors.fill: parent anchors.fill: parent
initialItem: "DbConfiguration.qml" initialItem: "DbConfiguration.qml"
//initialItem: "AdminUserConfig.qml"
} }
RowLayout RowLayout
{ {
@@ -126,7 +132,7 @@ Item
pyqcrm_conf = Qmldict.func(submitBtn.grids) pyqcrm_conf = Qmldict.func(submitBtn.grids)
if (pyqcrm_conf) if (pyqcrm_conf)
{ {
admin = config.setConfig(pyqcrm_conf) config.setConfig(pyqcrm_conf)
} }
} }

View File

@@ -15,6 +15,7 @@ from .PyqcrmFlags import PyqcrmFlags
class ConfigLoader(QObject): class ConfigLoader(QObject):
__config = None __config = None
__version = "0.1-alpha" __version = "0.1-alpha"
@@ -22,6 +23,7 @@ class ConfigLoader(QObject):
dbConnectionError = Signal(str, bool) dbConnectionError = Signal(str, bool)
adminUserError = Signal(str, bool) adminUserError = Signal(str, bool)
usernameNotAvailable = Signal()
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@@ -46,7 +48,10 @@ class ConfigLoader(QObject):
@Slot(dict, result= bool) @Slot(dict, result= bool)
def addAdminUser(self, user_config): def addAdminUser(self, user_config):
admin = UserManager(user_config["user"], PyqcrmFlags.ADMIN).createUser() admin = UserManager(user_config["user"], PyqcrmFlags.ADMIN).createUser()
return True print (admin)
if not admin:
self.usernameNotAvailable.emit()
return admin
@Slot(dict, result= bool) @Slot(dict, result= bool)
def setConfig(self, app_config): def setConfig(self, app_config):
@@ -93,12 +98,21 @@ class ConfigLoader(QObject):
return False return False
def __checkAdminUser(self): def __checkAdminUser(self):
con = DbManager().getConnection()
cur = con.cursor()
cur.callproc("checkAdmin")
result = cur.fetchall()
if not result:
#if not result[0][0] == 1:
self.adminUserError.emit("Kein Admin vorhanden", False)
else:
self.adminUserError.emit("Admin vorhanden", True)
self.adminUserError.emit("Kein Admin vorhanden", False)
@Slot(str) @Slot(str)
def setEncyrptKey(self, key): def setEncyrptKey(self, key):
self.__config['pyqcrm']['ENCRYPTION_KEY'] = key self.__config['pyqcrm']['ENCRYPTION_KEY'] = key
print(self.__config)
self.__saveConfig() self.__saveConfig()
def __saveConfig(self): def __saveConfig(self):

View File

@@ -1,5 +1,7 @@
from .DbManager import DbManager from .DbManager import DbManager
from ..PyqcrmFlags import PyqcrmFlags from ..PyqcrmFlags import PyqcrmFlags
from ..Vermasseln import Vermasseln
import mariadb
@@ -15,9 +17,24 @@ class UserManager():
def createUser(self): def createUser(self):
self.__cur.callproc("createUser", (self.__username, self.__password, self.__info, self.__role)) self.__hashPassword()
self.__con.commit() user_created = True
self.__closeConnection() try:
self.__cur.callproc("createUser", (self.__username, self.__password, self.__info, self.__role))
self.__con.commit()
except mariadb.Error as e:
print(f"Error: {e}")
print(e.errno)
user_created = False
finally:
self.__cur.close()
#self.__closeConnection()
return user_created
def __hashPassword(self):
self.__password = Vermasseln.userPasswordHash(self.__password)
print (self.__password)
def getUser(self): def getUser(self):
self.__closeConnection() self.__closeConnection()

View File

@@ -2,7 +2,11 @@
from Crypto.Cipher import AES from Crypto.Cipher import AES
from base64 import b64encode, b64decode from base64 import b64encode, b64decode
import platform import platform
from Crypto.Hash import SHA256 from Crypto.Hash import SHA256, SHA3_512
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Random import get_random_bytes
import random
import string
class Vermasseln: class Vermasseln:
@@ -42,6 +46,18 @@ class Vermasseln:
cipher = AES.new(hashed, AES.MODE_SIV, nonce = nonce) cipher = AES.new(hashed, AES.MODE_SIV, nonce = nonce)
return cipher return cipher
@classmethod
def userPasswordHash(self, password):
salt = "".join(random.choice(string.ascii_letters + string.digits) for i in range (32))
hash_pw = (salt + password).encode("utf-8")
h_obj = SHA3_512.new(hash_pw)
password = salt + "$" + h_obj.hexdigest()
return password

View File

@@ -1,78 +0,0 @@
# Resource object code (Python 3)
# Created by: object code
# Created by: The Resource Compiler for Qt version 6.8.0
# WARNING! All changes made in this file will be lost!
from PySide6 import QtCore
qt_resource_data = b"\
\x00\x00\x01\xba\
(\
\xb5/\xfd`\xdd\x04\x85\x0d\x00\xb6\x13=\x1f0s\x1e\
\xb3\xfb\x92H\xd4\xdc\x08\xd0\xcdc\xdb\xa9\xa2\xa0\xc4\xa4\
\xbco\x17:w\xe6&\x14T4\x0c\x034\x003\x00\
4\x00{5\x07\x9f\x8a\x9d\x83\xa1\xb9\x87UdHh\
\xae\x9a\xf1\xedE}\x17W\x7fsTl\x0c\xc4:]\
a\x8c~\xed\xcfF\xa8l\xff\xd9\x0c\x89i^\xac\x94\
\xa7\xb4\xf7\xbe\xac\x18M(4A\x9b,]>\xbe(\
/+\x10M\x90n#\x02\xb8\x85n\x9a{\x0fs\xf5\
o\xeeWb(\xdf^@\xba\xd4\xec\xff\xba\x081\xf6\
\x18\x96\xd4\x1b\xbe\xb9\xd2O\xf6\x8f}Z\xfe\xb4C\xe2\
\xfc\x91'\xdf\x8f\xd6\xe45\x9c\x99\x9a\xb2\x9c\xd6\xe2l\
\xf5\xd3\xca\x80L\xa6f\xd5\x84\x22im\xa4\x96h\xfc\
\xbc6\x95\x9c\xa9\xed\xc8u9\x8a5\x8c\x19\x8c\x85\x10\
\xcd\xcdX\xf9J\x1eV\xd1#\x8a\xdd[\xf6\x8b*\x0e\
\x95\xeadk@\xb9Z+\x0e\xdc\xf3M\xd4\xdc\xecG\
;\xb3/e\xc4Ho/\x0a-\xfe\x87\xa2\x9au\xc2\
N\xa0\x91\x1dB\x8a!\x91))LZ\x03@\x84\x18\
\xc6\xec\x1c\x03\x00\xb53i!-\xd8t\x01r\x1e\xc8\
R\xc2\x99\x15\xe6\xba7\xf5\xb1\x85]\xd9d4\xe6\x0c\
\x07\x95\x88^\xe0\xf7\x96\x0d\xeb\xc7\xa2\xaeQ\xbf\x96\xfd\
\x93\x9c\xd3\x1cX\x94L7\x1bB\xb5\xb0\xc2tNJ\
\x5c\xf0x\x18\x1d\xd3vQ\x82w\xa5\xf6\x18\xb9\xbb\xaa\
\x8d)z\x08\x8f\xf5\xb8\x80\xe7*\xab\xbd\x0f\xd2\x92;\
\xc4\xaa@\x8bdyf\xa1\x0d\xc2[\xc6\xa0QD\x18\
\x97p\xb1\x85\xf3m3\x04\x05\x95=^\xd8SU\xe5\
6\x9e\x93%!~\x0d`\x01_\xdb(\x5c\xa0\xa7\x82\
\x03\xf0\xd6\xb8\x0d\x97\xd8n\x056\x87\xb4\xaf%\xb4\x0d\
\x83\xfb\x1b\xe6\x8aD\x22w*\
\x00\x00\x00$\
m\
odule TopBar\x0aTop\
Bar 1.0 TopBar.q\
ml\x0a\
"
qt_resource_name = b"\
\x00\x03\
\x00\x00n\xb9\
\x00g\
\x00u\x00i\
\x00\x0a\
\x08\x8e<\xbc\
\x00T\
\x00o\x00p\x00B\x00a\x00r\x00.\x00q\x00m\x00l\
\x00\x06\
\x07\x84+\x02\
\x00q\
\x00m\x00l\x00d\x00i\x00r\
"
qt_resource_struct = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x02\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00&\x00\x00\x00\x00\x00\x01\x00\x00\x01\xbe\
\x00\x00\x01\x93+<\x17\x5c\
\x00\x00\x00\x0c\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01\x93*\xc9x\xab\
"
def qInitResources():
QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
def qCleanupResources():
QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
qInitResources()

View File

@@ -6,10 +6,10 @@
from PySide6 import QtCore from PySide6 import QtCore
qt_resource_data = b"\ qt_resource_data = b"\
\x00\x00\x00\x18\ \x00\x00\x00\x1a\
[\ [\
Controls]\x0aStyle=\ Controls]\x0d\x0aStyle\
Fusion\x0a\ =Fusion\x0d\x0a\
\x00\x00\x01\x22\ \x00\x00\x01\x22\
<\ <\
svg xmlns=\x22http:\ svg xmlns=\x22http:\
@@ -194,19 +194,19 @@ qt_resource_struct = b"\
\x00\x00\x000\x00\x02\x00\x00\x00\x06\x00\x00\x00\x03\ \x00\x00\x000\x00\x02\x00\x00\x00\x06\x00\x00\x00\x03\
\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01\x93*\xc9x\xac\ \x00\x00\x01\x93)\xa6\xd7i\
\x00\x00\x00\x80\x00\x00\x00\x00\x00\x01\x00\x00\x02\x9f\ \x00\x00\x00\x80\x00\x00\x00\x00\x00\x01\x00\x00\x02\xa1\
\x00\x00\x01\x93*\xd6\x0c\xbc\ \x00\x00\x01\x93 \xd4\x11\xf3\
\x00\x00\x00\x94\x00\x00\x00\x00\x00\x01\x00\x00\x03Y\ \x00\x00\x00\x94\x00\x00\x00\x00\x00\x01\x00\x00\x03[\
\x00\x00\x01\x93*\xd6\x0c\xbd\ \x00\x00\x01\x93\x00\x9f\x10\x0d\
\x00\x00\x00\xc4\x00\x00\x00\x00\x00\x01\x00\x00\x05\x9a\ \x00\x00\x00\xc4\x00\x00\x00\x00\x00\x01\x00\x00\x05\x9c\
\x00\x00\x01\x93*\xd6\x0c\xbc\ \x00\x00\x01\x93 \xd4\x11\xf4\
\x00\x00\x00\x5c\x00\x00\x00\x00\x00\x01\x00\x00\x01B\ \x00\x00\x00\x5c\x00\x00\x00\x00\x00\x01\x00\x00\x01D\
\x00\x00\x01\x93*\xd6\x0c\xbc\ \x00\x00\x01\x93 \xd4\x11\xf4\
\x00\x00\x00B\x00\x00\x00\x00\x00\x01\x00\x00\x00\x1c\ \x00\x00\x00B\x00\x00\x00\x00\x00\x01\x00\x00\x00\x1e\
\x00\x00\x01\x93*\xd6\x0c\xbd\ \x00\x00\x01\x93\x00\xcf\xe6\x09\
\x00\x00\x00\xae\x00\x00\x00\x00\x00\x01\x00\x00\x04\xd5\ \x00\x00\x00\xae\x00\x00\x00\x00\x00\x01\x00\x00\x04\xd7\
\x00\x00\x01\x93*\xd6\x0c\xbd\ \x00\x00\x01\x92\xfc,B\x0e\
" "
def qInitResources(): def qInitResources():

422
rc_qml.py
View File

@@ -7,212 +7,222 @@ from PySide6 import QtCore
qt_resource_data = b"\ qt_resource_data = b"\
\x00\x00\x01\xba\ \x00\x00\x01\xba\
(\ \x00\
\xb5/\xfd`\xdd\x04\x85\x0d\x00\xb6\x13=\x1f0s\x1e\ \x00\x068x\xda\xb5TMo\xd40\x10\xbd\xaf\xb4\xff\
\xb3\xfb\x92H\xd4\xdc\x08\xd0\xcdc\xdb\xa9\xa2\xa0\xc4\xa4\ \xc1\xca\x09\x84\x94\x16!\x0eD\xea\x81]8 Z\xa1\
\xbco\x17:w\xe6&\x14T4\x0c\x034\x003\x00\ \xa2J\x9c\x1dg6q\xd7\xf1d\xc7cJ\x85\xfa\xdf\
4\x00{5\x07\x9f\x8a\x9d\x83\xa1\xb9\x87UdHh\ q\xe2m\x1c\xba(\x04\xa1\xfa\x10\xe5\xcd\xc7\xf3{c\
\xae\x9a\xf1\xedE}\x17W\x7fsTl\x0c\xc4:]\ it\xdb!\xb1\xb8\xe6k\xaf\xd5~\xbd\xd2\xbf\xe1|\
a\x8c~\xed\xcfF\xa8l\xff\xd9\x0c\x89i^\xac\x94\ \x8b\x96\x09\x8d;I\x5c\xca{\xf4\x1c\xe2\xeb\xd5W\xbc\
\xa7\xb4\xf7\xbe\xac\x18M(4A\x9b,]>\xbe(\ \x8bh\xbd\xfa\xb9^\x89ptU\x08\xc6n#)b\
/+\x10M\x90n#\x02\xb8\x85n\x9a{\x0fs\xf5\ \xd7I\xa5m]\x88\xf3\x88\x1b\xd0u\xc3\x85x\xf36\
o\xeeWb(\xdf^@\xba\xd4\xec\xff\xba\x081\xf6\ \xe2;]qS\x88N\x12X\xce\x07\x14\x13\xd2\xaa\x06\
\x18\x96\xd4\x1b\xbe\xb9\xd2O\xf6\x8f}Z\xfe\xb4C\xe2\ \xc9Ep$\xefO \x1f\xcb\xc3\x7fJ\x18\xd8\xf1\x98\
\xfc\x91'\xdf\x8f\xd6\xe45\x9c\x99\x9a\xb2\x9c\xd6\xe2l\ \xe9A/0\xa6\x1f\x1e\x7f6\x9e\x19\xed\x09g/\xba\
\xf5\xd3\xca\x80L\xa6f\xd5\x84\x22im\xa4\x96h\xfc\ \x92\xae\xd9\xa0\xa4*\x85wF\x06F&\x0f\x93\xeb\xe1\
\xbc6\x95\x9c\xa9\xed\xc8u9\x8a5\x8c\x19\x8c\x85\x10\ G\x88\x1d\xdc\x0d\xbd\xc8>\x84\x96\xb2o\xc9^N\xb8\
\xcd\xcdX\xf9J\x1eV\xd1#\x8a\xdd[\xf6\x8b*\x0e\ \xda\xceh\xa5\xf9[46\xd2\xe6\x8f\x89~\xaeA\xe2\
\x95\xeadk@\xb9Z+\x0e\xdc\xf3M\xd4\xdc\xecG\ \x90\x17\xaf\xc4\xeb\xf3\xd4\x8bv\x1bJ\xf6P\x15)6\
;\xb3/e\xc4Ho/\x0a-\xfe\x87\xa2\x9au\xc2\ \x919\x8c\xa5\xeb.QV@\xb9CO\x0a\xc4\x85H\
N\xa0\x91\x1dB\x8a!\x91))LZ\x03@\x84\x18\ :\xf2Ck\xb2T\xff\xf0/\xfe\xf7\xdeV`\x97\x9b\
\xc6\xec\x1c\x03\x00\xb53i!-\xd8t\x01r\x1e\xc8\ \xff<\xd4\xcf8\x8f\x84\xcfh{\xeb\x1dc\x0bt#\
R\xc2\x99\x15\xe6\xba7\xf5\xb1\x85]\xd9d4\xe6\x0c\ K\x03\xee\xd4\xfbR\xe7X\xde\xc2\x9e\x97;\xff2\xd4\
\x07\x95\x88^\xe0\xf7\x96\x0d\xeb\xc7\xa2\xaeQ\xbf\x96\xfd\ \xcf8\x8f\x84s\xce\x97\x8bk5K*A3\xd0r\
\x93\x9c\xd3\x1cX\x94L7\x1bB\xb5\xb0\xc2tNJ\ \x85W\xa9iF\xe6\x84\xfa\x19_\xe9c`\xc6{\xf8\
\x5c\xf0x\x18\x1d\xd3vQ\x82w\xa5\xf6\x18\xb9\xbb\xaa\ \xdfG\x92%\x81j\xac\xb7\xf5\xf21\xbc\x1f{f\xa6\
\x8d)z\x08\x8f\xf5\xb8\x80\xe7*\xab\xbd\x0f\xd2\x92;\ \x90\x88\xff6\x84Q\xe6'\x86\xf6\x8f\x22\x9b~\xdbM\
\xc4\xaa@\x8bdyf\xa1\x0d\xc2[\xc6\xa0QD\x18\ \x1f*.\xc7|\xa7\x8d9^\x97\xd4.r\xcd\xf2\x16\
\x97p\xb1\x85\xf3m3\x04\x05\x95=^\xd8SU\xe5\ \xdd$\xa6\xd0\x1eg[\x88\xec@\xaa8\xd3\xad\xac\xc1\
6\x9e\x93%!~\x0d`\x01_\xdb(\x5c\xa0\xa7\x82\ \x9d\xb5`}\xee\xbe\xd7\xd9\x93b\x85\x06)\xd4\x12T\
\x03\xf0\xd6\xb8\x0d\x97\xd8n\x056\x87\xb4\xaf%\xb4\x0d\ \xd9\xfc\xe4\x8eZ\xa9\xdf\xcfW\x92jm\x0b\xf1\xee\xc9\
\x83\xfb\x1b\xe6\x8aD\x22w*\ \x0e\x1d>\xbf\x00<\x0b\xa5\xbd\
\x00\x00\x03,\ \x00\x00\x03Y\
i\ i\
mport QtQuick\x0aim\ mport QtQuick\x0d\x0ai\
port QtQuick.Con\ mport QtQuick.Co\
trols\x0aimport QtQ\ ntrols\x0d\x0aimport Q\
uick.Layouts\x0a\x0aGr\ tQuick.Layouts\x0d\x0a\
idLayout\x0a{\x0a i\ \x0d\x0aGridLayout\x0d\x0a{\x0d\
d: passEncryptKe\ \x0a id: passEnc\
yGrid\x0a column\ ryptKeyGrid\x0d\x0a \
s: 2\x0a columnS\ columns: 2\x0d\x0a \
pacing: 5\x0a ro\ columnSpacing: \
wSpacing: 9\x0a \ 5\x0d\x0a rowSpacin\
// anchors.fill:\ g: 9\x0d\x0a // anc\
parent\x0a\x0a pro\ hors.fill: paren\
perty string nam\ t\x0d\x0a\x0d\x0a propert\
e: \x22pyqcrm\x22\x0a\x0a \ y string name: \x22\
Label\x0a {\x0a \ pyqcrm\x22\x0d\x0a\x0d\x0a L\
abel\x0d\x0a {\x0d\x0a \
text: qsTr(\ text: qsTr(\
\x22Encryption Key \ \x22Encryption Key \
eingeben\x22)\x0a \ eingeben\x22)\x0d\x0a \
font.pixelSiz\ font.pixelSi\
e: 40\x0a La\ ze: 40\x0d\x0a \
yout.columnSpan:\ Layout.columnSpa\
2\x0a Layou\ n: 2\x0d\x0a La\
t.alignment: Qt.\ yout.alignment: \
AlignHCenter\x0a \ Qt.AlignHCenter\x0d\
padding: 15\ \x0a padding\
\x0a }\x0a\x0a\x0a Lab\ : 15\x0d\x0a }\x0d\x0a\x0d\x0a\x0d\
el\x0a {\x0a \ \x0a Label\x0d\x0a \
text: qsTr(\x22Enc\ {\x0d\x0a text:\
ryption Key:\x22)\x0a \ qsTr(\x22Encryptio\
n Key:\x22)\x0d\x0a \
Layout.alignme\
nt: Qt.AlignRigh\
t\x0d\x0a }\x0d\x0a\x0d\x0a \
TextField\x0d\x0a {\
\x0d\x0a id: pa\
ssEncryptKey\x0d\x0a \
placeholde\
rText: qsTr(\x22Hie\
r Encryption Key\
eingeben\x22)\x0d\x0a \
Layout.fill\
Width: true\x0d\x0a \
height: 3\x0d\x0a\
echoMode\
: TextInput.Pass\
word\x0d\x0a pr\
operty string na\
me: \x22ENCRYPT_KEY\
\x22\x0d\x0a }\x0d\x0a\x0d\x0a \
Item\x0d\x0a {\x0d\x0a \
Layout.fill\
Height: true\x0d\x0a \
}\x0d\x0a}\x0d\x0a\
\x00\x00\x00#\
m\
odule gui\x0d\x0aTopBa\
r 1.0 TopBar.qml\
\x0d\x0a\
\x00\x00\x02\x06\
\x00\
\x00\x07\xf8x\xda\xb5\x94Ms\xda0\x10\x86\xef\xcc\xf0\
\x1f4>\xb5\x87\x924\xad3S\xe7\x04\x09\xad\x99\xc9\
\x07`\x92\x1e;\xb2\xb5\x80&\xb2\xe4J\xeb\xe6k\xf8\
\xef\x95b\x83\x9d\xba\x9d\x1a\x06l\x1f\xb4\xab\xd5\xee\xbb\
\x8f%\xf14S\x1a\xc9\x04'9O\xee\xbb\x1d\xfe\xc6\
\xee\x9d+\x89Z\x09\xd3\x98\xb8\xa4O*G\xebw\xef\
7\xcdY\xe1\xe8v^\xba\x1db\x9f\xa3#\x92i\x95\
\x81\xc6'B\x05\xa7\x86\xcc\xb96\x18!\xd5\x18\xd4\xc6\
ni\xb1\x82\xb3\x80\xb0\xb8\xb2\x13%\xf2T\x9a\x80\x9c\
\xd4\xed(\xa3\x09\x97\x8b\x80\xf8\x85W\xab\x87\x8d\xeb\x8b\
\xd3\xe2\x9c\x9b\xca\x06\xb5\x9d!\x92\xa6\x10\x10\x8fQ\xa4\
15\xe0\xad\xe3.i\x0c\xa2\x18\x96\xb2\xdd\x83\xf0h\
%\xfe43\xfd\xce\xbb\xa0\x082\xa6\xf2\x9e\x0c\xb94\
\x08B\xe4r\x01\xd2{_\x85\xcf-\xa2^\xc6\x1fA\
D\xfc\xd9\x96\xf9|\x5c\xcd\x15Pz\x1b\xe9r\xd3M\
m\xd6\xe2Y\xc8\x14\xa4-:\xc1^\xdfY\xe1\xb95\
AW\xa1\x19e\xec\xb5\xc7\x8fe\xdf\xab\x82|\xcb.\
\x06\x1fBe0\xa8\xcb\xfew\xf1)_,q\x9d|\
\xb5\x1e\xccl\xbe\xaf\x1c\x04kT*~\x9c+P\xd3\
+h\x02K%\x18\xe8YMH\xc8A\x13\x17I\xc0\
v\x03\xf1[\x92\xa5\xa49\x17\xe2;g\xb8\x0c\x08\xea\
\x1cjI\xff\xfe[/\x06?\xc2\x9bh\xe6\xfd!\xb8\
\x15\x96\xb1\xdd\xd3\xdba\xd9\x0a\x8aK\xdf\x0eJ\xa9e\
'.\xbf\xacZ\xbb\xb7\x95\x0e\xc8H\xe2\xdd\xdaz\x89\
\x15\xa2J\xed\x9e9>\xf1\xcf\x08\xaa, \xa7\xbe\xff\
\xc9?[\xb5a:\xbe\x99\xee\xc6\xf4\xda\xa58\x1cS\
\x97\xbe5S\x17\xbc\xe7\xbdv\xdd\xbf\x1a\xee\xc4e\x00\
2\xc7g\xd0\xf2\xb0|n\x0d\xe8\xad\x18\xd5u\xed\x99\
\xd5m4\x9cz\x8d\xab\xa4\xdd\xc9\xa4\xc6<\x1c\xf8t\
\x16%X\xe5\x87d\xa9\xae\x14\xb3\xea\xdd\xda\x91\xccl\
\xb1f\xd4\xff\xceq\xa9|\xcf,\xc7\xfd(\xf2\x1a\x97\
\xff\x08!m\xb4W+\x12\x82\x03S\xafb\x17\xdb\xef\
7h\x023#\
\x00\x00\x05\x86\
i\
mport QtQuick\x0d\x0ai\
mport QtQuick.Co\
ntrols\x0d\x0aimport Q\
tQuick.Layouts\x0d\x0a\
\x0d\x0aGridLayout\x0d\x0a{\x0d\
\x0a id: createU\
serGrid\x0d\x0a col\
umns: 2\x0d\x0a col\
umnSpacing: 5\x0d\x0a \
rowSpacing: 9\
\x0d\x0a // anchors\
.fill: parent\x0d\x0a\x0d\
\x0a property st\
ring name: \x22user\
\x22\x0d\x0a\x0d\x0a Label\x0d\x0a\
{\x0d\x0a t\
ext: qsTr(\x22Admin\
User erstellen\x22\
)\x0d\x0a font.\
pixelSize: 40\x0d\x0a \
Layout.co\
lumnSpan: 2\x0d\x0a \
Layout.alig\
nment: Qt.AlignH\
Center\x0d\x0a \
padding: 15\x0d\x0a \
}\x0d\x0a\x0d\x0a\x0d\x0a Labe\
l\x0d\x0a {\x0d\x0a \
text: qsTr(\x22Be\
nutzername:\x22)\x0d\x0a \
Layout.al\ Layout.al\
ignment: Qt.Alig\ ignment: Qt.Alig\
nRight\x0a }\x0a\x0a \ nRight\x0d\x0a }\x0d\x0a\x0d\
TextField\x0a \ \x0a TextField\x0d\x0a\
{\x0a id: pa\ {\x0d\x0a i\
ssEncryptKey\x0a \ d: benutzerName\x0d\
placeholder\ \x0a placeho\
Text: qsTr(\x22Hier\ lderText: qsTr(\x22\
Encryption Key \ Hier Benutzernam\
eingeben\x22)\x0a \ e eingeben\x22)\x0d\x0a \
Layout.fillWi\ Layout.fil\
dth: true\x0a \ lWidth: true\x0d\x0a \
height: 3\x0a \ height: 3\x0d\
echoMode: Te\
xtInput.Password\
\x0a propert\ \x0a propert\
y string name: \x22\ y string name: \x22\
ENCRYPT_KEY\x22\x0a \ PYQCRM_USER\x22\x0d\x0a \
}\x0a\x0a Item\x0a \ }\x0d\x0a\x0d\x0a Label\
{\x0a Layou\ \x0d\x0a {\x0d\x0a \
t.fillHeight: tr\ text: qsTr(\x22Pas\
ue\x0a }\x0a}\x0a\ swort:\x22)\x0d\x0a \
\x00\x00\x00!\ Layout.alignme\
m\ nt: Qt.AlignRigh\
odule gui\x0aTopBar\ t\x0d\x0a }\x0d\x0a\x0d\x0a \
1.0 TopBar.qml\x0a\ TextField\x0d\x0a {\
\ \x0d\x0a id: pa\
\x00\x00\x01\xd2\ ssword\x0d\x0a \
(\ echoMode: TextIn\
\xb5/\xfd`T\x06E\x0e\x006VE \x95\x1b\ put.Password\x0d\x0a \
:\xbd\x94\x0a\x13I\xcc\x02\xb9\x88y\xd8\x9e\x053\x99\ placeholde\
t\x01\xbd\x03\x9c\xf1\x18q\x02\xa4`\xa0 :\x00:\ rText: qsTr(\x22Hie\
\x00;\x00\x0c\xafo\x1d\xad\x19&\x19\xca\x09\xdf\xc6\xb7\ r Passwort einge\
\xfe\xda\xc9\xe1\x1b'\x8d,z\xdb\x5c\xb5\x1c\x0f\x06\xcc\ ben\x22)\x0d\x0a L\
\xcc\x8f\xf4\xe4\xb4\x90\xf7\xde\xfd\xae\x8a\xa2\xe4\xd2j\xdf\ ayout.fillWidth:\
+\x83z\x9elv\x97\xbf\xf0\xdb\xcam3\x16\xed\xd0\ true\x0d\x0a p\
\xe4\xa8\xf7\xca\x09L\xde\x9aw\x94\xf6_\x9f\x0e\xf6x\
\xc4\xbc?6&\x80\xbd\xee\x87\xe1\x87\xfaicQ2\
\xf5\x8dX\xfc('\x86\xbdEg\xfb\xf7%@\xd5\x22\
\x18j>\xb3\xc8Y\x86\x8d\xb5\xe6\xb3\x99m\xcf\xea\xb2\
-i\xedt\x16\xa9\xa4=\x1f\x1f\xea\xeb}G\x9b\x98\
\xc0\x04\xff\xd6J\xb0x\xa5\x82\x94\x91\xb3\xfd\xde\x8cJ\
A\xfd\x85\xe1{o\xaeM\x1a\x0d\x0c\x9d\x22\x1c\x18\xf6\
h\x06\xaf\xd4\xd5\xd6\x1f\xb1,\x05\xf5\x1d\xe7\x11\xd8\xb2\
Nj'k\x09\xba7\xbe\x09\xe3\xb02\xb6o\xc6m\
\x8f\xbe\xf3^8&\x0aJo\x91\x82\xa9Xl\xb5L\
\x97U\xa96\x8bFw\xf6\x19v^N\x0d\xa5\x93\xe3\
\x01J\xa0\x91\x11R\xce\x94\x88\x8d\x92(\x9b\x01p&\
\x10\xab2\x0fZ\x99\xb8\xb1\x06\x06\x843+\xcd\x06\x5c\
\xd3g\x83\xcec\x18b!$5\xb7q\xa5\x06\xd6A\
\xa63M\x97\xcdDuH\x11\x0a\xb4\x94Q\xf3\xaa\xa2\
\xc9bD\x0b\x11V?\x8e\x00\xc2\xe9l\xd46\x80\x22\
\x8e\xd1\x9f\x9b\xe0A\x97\xcd\x17\xfa6\x16\x8a\x84;\xc4\
\x84t\xc8#\x8b\x1d\x096\x95\xb2\xbb\xda\xa2*\xde,\
\xbe\xc6\x8e\x1c\x08N2\xfcP(\x1c\x88.\x9a\xd8V\
\x1d\xb5\x06\x82l\xcd\x85\x82\x86\xc6W~\xe3\xe5\x02X\
\x9c[\xdcq\xca@{\xf0f\xady\xa9Z\x15\xbf\x87\
\xe6\xe4\x05\xfd\xe5\xc2Z\x1e\xa6\x8a\x0f\xb8\x22!r\xf7\
\x03\
\x00\x00\x05C\
i\
mport QtQuick\x0aim\
port QtQuick.Con\
trols\x0aimport QtQ\
uick.Layouts\x0a\x0aGr\
idLayout\x0a{\x0a i\
d: createUserGri\
d\x0a columns: 2\
\x0a columnSpaci\
ng: 5\x0a rowSpa\
cing: 9\x0a // a\
nchors.fill: par\
ent\x0a\x0a propert\
y string name: \x22\
pyqcrm\x22\x0a\x0a Lab\
el\x0a {\x0a \
text: qsTr(\x22Adm\
in User erstelle\
n\x22)\x0a font\
.pixelSize: 40\x0a \
Layout.co\
lumnSpan: 2\x0a \
Layout.align\
ment: Qt.AlignHC\
enter\x0a pa\
dding: 15\x0a }\x0a\
\x0a\x0a Label\x0a \
{\x0a text: \
qsTr(\x22Benutzerna\
me:\x22)\x0a La\
yout.alignment: \
Qt.AlignRight\x0a \
}\x0a\x0a TextFie\
ld\x0a {\x0a \
id: benutzerNam\
e\x0a placeh\
olderText: qsTr(\
\x22Hier Benutzerna\
me eingeben\x22)\x0a \
Layout.fil\
lWidth: true\x0a \
height: 3\x0a \
property \
string name: \x22PY\
QCRM_ADMIN\x22\x0a \
}\x0a\x0a Label\x0a \
{\x0a text:\
qsTr(\x22Passwort:\
\x22)\x0a Layou\
t.alignment: Qt.\
AlignRight\x0a }\
\x0a\x0a TextField\x0a\
{\x0a id\
: password\x0a \
echoMode: Tex\
tInput.Password\x0a\
placehol\
derText: qsTr(\x22H\
ier Passwort ein\
geben\x22)\x0a \
Layout.fillWidth\
: true\x0a p\
roperty string n\ roperty string n\
ame: \x22PYQCRM_ADM\ ame: \x22PYQCRM_USE\
IN_PASS\x22\x0a }\x0a \ R_PASS\x22\x0d\x0a }\x0d\x0a\
Label\x0a {\x0a \ Label\x0d\x0a {\
text: qsT\ \x0d\x0a text: \
r(\x22Info:\x22)\x0a \ qsTr(\x22Info:\x22)\x0d\x0a \
Layout.alignm\ Layout.al\
ent: Qt.AlignRig\ ignment: Qt.Alig\
ht\x0a }\x0a\x0a Te\ nRight\x0d\x0a }\x0d\x0a\x0d\
xtField\x0a {\x0a \ \x0a TextField\x0d\x0a\
id: gecos\x0a\ {\x0d\x0a i\
placehol\ d: gecos\x0d\x0a \
derText: qsTr(\x22Z\ placeholderTex\
us\xc3\xa4tzliche Info\ t: qsTr(\x22Zus\xc3\xa4tz\
\x22)\x0a Layou\ liche Info\x22)\x0d\x0a \
t.fillWidth: tru\ Layout.fil\
e\x0a proper\ lWidth: true\x0d\x0a \
ty string name: \ property s\
\x22PYQCRM_ADMIN_IN\ tring name: \x22PYQ\
FO\x22\x0a }\x0a\x0a I\ CRM_USER_INFO\x22\x0d\x0a\
tem\x0a {\x0a \ }\x0d\x0a\x0d\x0a Ite\
m\x0d\x0a {\x0d\x0a \
Layout.fillHei\ Layout.fillHei\
ght: true\x0a }\x0a\ ght: true\x0d\x0a }\
}\x0a\ \x0d\x0a}\x0d\x0a\
" "
qt_resource_name = b"\ qt_resource_name = b"\
@@ -251,15 +261,15 @@ qt_resource_struct = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x02\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x02\
\x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00&\x00\x00\x00\x00\x00\x01\x00\x00\x01\xbe\ \x00\x00\x00&\x00\x00\x00\x00\x00\x01\x00\x00\x01\xbe\
\x00\x00\x01\x93c~Y\x0a\ \x00\x00\x01\x93q\xc1B\xf5\
\x00\x00\x00\x8c\x00\x00\x00\x00\x00\x01\x00\x00\x06\xe9\ \x00\x00\x00\x8c\x00\x00\x00\x00\x00\x01\x00\x00\x07L\
\x00\x00\x01\x93cIV\x9c\ \x00\x00\x01\x93q\xc1B\xf3\
\x00\x00\x00N\x00\x00\x00\x00\x00\x01\x00\x00\x04\xee\ \x00\x00\x00N\x00\x00\x00\x00\x00\x01\x00\x00\x05\x1b\
\x00\x00\x01\x930& \x0f\ \x00\x00\x01\x93>1\xe8\xfe\
\x00\x00\x00\x0c\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\ \x00\x00\x00\x0c\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01\x93*\xc9x\xab\ \x00\x00\x01\x93>1\xe8\xfc\
\x00\x00\x00`\x00\x04\x00\x00\x00\x01\x00\x00\x05\x13\ \x00\x00\x00`\x00\x01\x00\x00\x00\x01\x00\x00\x05B\
\x00\x00\x01\x93cI\x95\xbf\ \x00\x00\x01\x93q\xc1B\xf4\
" "
def qInitResources(): def qInitResources():