diff --git a/login.py b/login.py new file mode 100644 index 0000000..eaa8797 --- /dev/null +++ b/login.py @@ -0,0 +1,110 @@ +import streamlit as st +import sqlite3 +import bcrypt +from contextlib import closing + +DB_PATH = "users.db" + +# ---------- DB helpers ---------- +def get_conn(): + return sqlite3.connect(DB_PATH, check_same_thread=False) + +def init_db(): + with closing(get_conn()) as conn, conn: + conn.execute(""" + CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT UNIQUE NOT NULL, + password_hash BLOB NOT NULL, + role TEXT NOT NULL DEFAULT 'user' + ) + """) + +def create_user(username: str, password: str, role: str = "user") -> bool: + pw_hash = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()) + try: + with closing(get_conn()) as conn, conn: + conn.execute( + "INSERT INTO users (username, password_hash, role) VALUES (?, ?, ?)", + (username, pw_hash, role), + ) + return True + except sqlite3.IntegrityError: + return False + +def verify_user(username: str, password: str): + 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 + ok = bcrypt.checkpw(password.encode("utf-8"), stored_hash) + return ok, role if ok else (False, None) + +# ---------- UI helpers ---------- +def login_view(): + st.title("Intranet Login") + with st.form("login"): + u = st.text_input("Username") + p = st.text_input("Passwort", type="password") + submitted = st.form_submit_button("Anmelden") + if submitted: + ok, role = verify_user(u.strip(), p) + if ok: + st.session_state["auth"] = True + st.session_state["username"] = u.strip() + st.session_state["role"] = role + st.success("Erfolgreich angemeldet.") + st.rerun() + else: + st.error("Login fehlgeschlagen.") + +def authed_header(): + st.sidebar.write(f"Angemeldet als **{st.session_state['username']}** ({st.session_state['role']})") + if st.sidebar.button("Logout"): + for k in ["auth", "username", "role"]: + st.session_state.pop(k, None) + st.rerun() + +def content_for(role: str, username: str): + # Beispiel: rollen- und nutzerbezogene Inhalte + st.header("Dashboard") + st.info(f"Willkommen, {username}!") + + if role == "admin": + st.subheader("Admin-Bereich") + st.write("Nur Admins sehen das hier.") + with st.expander("Neuen Nutzer anlegen"): + new_u = st.text_input("Neuer Username", key="new_u") + new_p = st.text_input("Neues Passwort", type="password", key="new_p") + new_role = st.selectbox("Rolle", ["user", "admin"], key="new_role") + if st.button("Anlegen"): + if new_u and new_p: + ok = create_user(new_u.strip(), new_p, new_role) + st.success("Nutzer angelegt.") if ok else st.error("Username bereits vorhanden.") + else: + st.warning("Bitte Username und Passwort eingeben.") + + st.subheader("Dein Bereich") + st.write(f"Personalisierter Content für **{username}**.") + # Hier würdest du z. B. Daten aus einer Fach-DB nutzerbezogen filtern/anzeigen. + +# ---------- App start ---------- +def main(): + st.set_page_config(page_title="Intranet-Portal", page_icon="🔒", layout="centered") + init_db() + + # Optional: Initialer Admin (einmalig manuell auskommentieren, starten, dann wieder aus) + #create_user("admin", "change_me", role="admin") + + if not st.session_state.get("auth"): + login_view() + else: + authed_header() + content_for(st.session_state["role"], st.session_state["username"]) + +if __name__ == "__main__": + main() diff --git a/users.db b/users.db new file mode 100644 index 0000000..feec234 Binary files /dev/null and b/users.db differ