initial commit

This commit is contained in:
hansi
2025-11-22 14:54:34 +01:00
parent 5f87571abe
commit 5fceae9a45
2 changed files with 110 additions and 0 deletions

110
login.py Normal file
View File

@@ -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()

BIN
users.db Normal file

Binary file not shown.