import sqlite3 from pathlib import Path import bcrypt BASE_DIR = Path(__file__).resolve().parent.parent DB_PATH = BASE_DIR / "data" / "app.db" def get_conn(): # check_same_thread=False, damit Streamlit mehrere Threads nutzen kann return sqlite3.connect(DB_PATH, check_same_thread=False) def create_user( username: str, password: str, role: str = "user", email: str | None = None, firstname: str | None = None, lastname: str | None = None ) -> bool: """ Passwort wird als bcrypt-Hash (TEXT) gespeichert. """ pw_hash = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()).decode("utf-8") try: with closing(get_conn()) as conn, conn: conn.execute( "INSERT INTO users (username, email, password_hash, role, firstname, lastname) VALUES (?, ?, ?, ?, ?, ?)", (username, email, pw_hash, role, firstname, lastname), ) return True except Exception: return False def verify_user(username: str, password: str): """ Vergleicht eingegebenes Passwort mit dem gespeicherten bcrypt-Hash. Rückgabe: (True, role) oder (False, None) """ with closing(get_conn()) as conn: row = conn.execute( "SELECT password_hash, role FROM users WHERE username = ?", (username,), ).fetchone() if not row: return False, None stored_hash, role = row # stored_hash ist TEXT → zurück nach bytes ok = bcrypt.checkpw(password.encode("utf-8"), stored_hash.encode("utf-8")) return (ok, role) if ok else (False, None) def get_role_for_user(username: str) -> str: with closing(get_conn()) as conn: row = conn.execute( "SELECT role FROM users WHERE username = ?", (username,), ).fetchone() return row[0] if row else "user"