# This Python file uses the following encoding: utf-8 import toml from platformdirs import user_config_dir from pathlib import Path from PySide6.QtCore import QObject, Slot, Signal from .Vermasseln import Vermasseln import shutil from urllib.parse import urlparse from .DB.DbManager import DbManager import os from Crypto.Random import get_random_bytes from base64 import b64encode from .DB.UserManager import UserManager from .PyqcrmFlags import PyqcrmFlags class ConfigLoader(QObject): __config = None __version = "0.1-alpha" dbConnectionError = Signal(str, bool) adminUserError = Signal(str, bool) usernameNotAvailable = Signal() configurationReady = Signal(bool) backupEncryptionKey = Signal() def __init__(self): super().__init__() self.config_dir = user_config_dir() + '/pyqcrm' #user_config_dir = Funktion platformdirs config_dir = Path(self.config_dir) if config_dir.exists(): self.__configLoad() 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): confile = urlparse(confile) confile = confile.path if os.name == "nt": confile = confile[1:] shutil.copyfile(confile, self.config_dir+ '/pyqcrm.toml') @Slot(dict, result= bool) def addAdminUser(self, user_config): admin = UserManager(user_config["user"], PyqcrmFlags.ADMIN).createUser() if not admin: self.usernameNotAvailable.emit() else: self.backupEncryptionKey.emit() return admin @Slot(dict, result= bool) def setConfig(self, app_config): base_conf = self.__initializeConfig() conf = self.__checkDbConnection(app_config) app_config = toml.dumps(app_config) if conf: app_config = base_conf + app_config self.__config = toml.loads(app_config) self.__saveConfig() conf = self.__checkAdminUser() if conf: self.configurationReady.emit(True) def __configLoad(self): try: 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: print(f"Invalid Configuration: {__file__}") except Exception as e: print(str(e)) def getConfig(self): return self.__config def __initializeConfig(self): 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 def __checkDbConnection(self, db_config): con = DbManager(db_config['database']).getConnection() if con: self.dbConnectionError.emit("Connection OK", True) return True else: self.dbConnectionError.emit("Connection fehlgeschlagen", False) return False 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) return False else: self.adminUserError.emit("Admin vorhanden", True) return True 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)) f.write(config) except FileNotFoundError: print("Konnte die Konfiguration nicht speichern.")