import streamlit as st from auth_runtime import require_login # from ui.sidebar import build_sidebar from auth import create_user from pathlib import Path from tools.load_css import load_css from app_db.app_db import get_list, send_cmd from ui.selectboxes import get_roles, get_id import bcrypt DASH_NAME = Path(__file__).stem # Hier muss die dash_id aus der DB stehen -> wird gegen die session_state geprüft (User-Berechtigung) load_css() st.set_page_config(page_title="Co-App Benutzer", page_icon=":material/person:", layout="wide", initial_sidebar_state="collapsed") authenticator = require_login() st.session_state["authenticator"] = authenticator def sidebar(): fullname = st.session_state.get("fullname") role_text = st.session_state.get("role_text") with st.sidebar: st.logo("app/images/GMN_Logo_neu_rgb.png", size="small") st.markdown(f"**{fullname}** ({role_text})") col1, col2 = st.columns([2,2]) with col1: authenticator.logout("Logout") with col2: if st.button("Home", use_container_width=True, icon=":material/home:"): st.switch_page("pages/home.py") user() @st.dialog("Benutzer anlegen") def dialog_create_user(): txt_username = st.text_input("Benutzername") txt_firstname = st.text_input("Vorname") txt_lastname = st.text_input("Nachname") txt_email = st.text_input("Email") txt_pwd = st.text_input("Kennwort", type="password") cmb_role = st.selectbox("Rolle", get_roles(), index=None) if st.button("Save"): if create_user( username=txt_username, firstname=txt_firstname, lastname=txt_lastname, email=txt_email, role_id=get_id(cmb_role), password=txt_pwd ): st.session_state.save_msg = f"✅ Benutzer '{txt_username}' erfolgreich gespeichert" else: st.session_state.save_msg = "❌ Fehler beim Speichern" st.rerun() @st.dialog("Benutzer löschen") def dialog_delete_user(id): if id == None: st.write("kein Benutzer ausgewählt") else: df = get_list("select username from users where id = ?",(id,)) username = df.iloc[0]["username"] st.write(f"Der Benutzer {username} wird gelöscht! Sind Sie sicher?") if st.button("Löschen"): if username != "admin": if send_cmd("delete from users where id = ?",(id,)): st.session_state.delete_msg = f"✅ Benutzer '{username}' erfolgreich gelöscht!" else: st.session_state.delete_msg = f"❌ Benutzer '{username}' konnte nicht gelöscht werden!" else: st.session_state.delete_msg = f"❌ Benutzer '{username}' darf nicht gelöscht werden!" st.rerun() @st.dialog("Benutzer bearbeiten") def dialog_edit_user(id): if id == None: st.write("kein Benutzer ausgewählt") else: sql = """ select u.id, u.username as user, -- ACHTUNG: nicht mit username arbeiten, da Überschneidung in sessionstate!! u.firstname, u.lastname, u.email, u.role_id || ' | ' || r.role_text as role, r.role_text, u.new_pwd, u.active from users u left join roles r on u.role_id = r.role_id where u.id = ? """ df = get_list(sql,(id,)) # df = get_list("select username from users where id = ?",(id,)) # st.session_state.orig_user_data = df df_roles = get_roles() roles = df_roles["text"].tolist() role = df.iloc[0]["role"] try: idx = roles.index(role) except: idx = None col1, col2 = st.columns([2,1],vertical_alignment="center") with col1: txt_username = st.text_input(label="Benutzername", value=df.iloc[0]["user"]) with col2: is_active = st.checkbox(label="Aktiv", value=df.iloc[0]["active"]) txt_firstname = st.text_input(label="Vorname", value=df.iloc[0]["firstname"]) txt_lastname = st.text_input(label="Nachname", value=df.iloc[0]["lastname"]) txt_email = st.text_input(label="Email", value=df.iloc[0]["email"]) txt_pwd = st.text_input(label="Passwort", placeholder="Neues Passwort eingeben", type="password") new_pwd = st.checkbox(label="Neues Passwort", value=df.iloc[0]["new_pwd"]) cmb_role = st.selectbox(label="Rolle", options=roles, placeholder="Rolle auswählen", index=idx) if st.button("Save"): pw_hash = bcrypt.hashpw(txt_pwd.encode("utf-8"), bcrypt.gensalt()).decode("utf-8") if txt_pwd and txt_pwd.strip(): sql = """ update users set username = ?, active = ?, firstname = ?, lastname = ?, email = ?, password_hash = ?, new_pwd = ?, role_id = ? where id = ? """ params = (txt_username, is_active, txt_firstname, txt_lastname, txt_email, pw_hash, new_pwd, get_id(cmb_role), id) # send_cmd(sql,(txt_username, txt_firstname, txt_lastname, txt_email, pw_hash, new_pwd, get_id(cmb_role), id)) else: sql = """ update users set username = ?, active = ?, firstname = ?, lastname = ?, email = ?, new_pwd = ?, role_id = ? where id = ? """ params = (txt_username, is_active, txt_firstname, txt_lastname, txt_email, new_pwd, get_id(cmb_role), id) # send_cmd(sql,(txt_username, txt_firstname, txt_lastname, txt_email, new_pwd, get_id(cmb_role), id)) print (params) if send_cmd(sql, params): st.session_state.save_msg = f"✅ Benutzer '{txt_username}' erfolgreich geändert" else: st.session_state.save_msg = "❌ Fehler beim Speichern" st.rerun() def user(): if "selected_user_id" not in st.session_state: st.session_state.selected_user_id = None # tab_user, tab_role, tab_permission = st.tabs(["Benutzer", "Rollen", "Berechtigungen"]) #-------------------------------------------------------------------------------------------------- # Benutzerverwaltung #-------------------------------------------------------------------------------------------------- # with tab_user: df = get_list(""" select u.id, u.username, u.firstname, u.lastname, u.role_id || ' | ' || r.role_text as role, u.new_pwd, u.active from users u left join roles r on u.role_id = r.role_id """) col_find_user, col_create_user, col_edit_user, col_delete_user = st.columns([3,2,2,2], vertical_alignment="bottom") with col_find_user: txt_search = st.text_input(label="Suche", label_visibility="hidden", placeholder="Benutzer, Vorname, ...", icon=":material/search:") with col_create_user: if st.button(label="Benutzer anlegen", use_container_width=True, icon=":material/person_add:"): dialog_create_user() if "save_msg" in st.session_state: st.toast(st.session_state.save_msg) del st.session_state.save_msg with col_edit_user: if st.button(label="Benutzer bearbeiten", use_container_width=True, icon=":material/person_edit:"): if not st.session_state.selected_user_id is None: dialog_edit_user(st.session_state.selected_user_id) else: st.toast("❌ Bitte erst eine Zeile auswählen") if "save_msg" in st.session_state: st.toast(st.session_state.save_msg) del st.session_state.save_msg with col_delete_user: if st.button(label="Benutzer löschen", use_container_width=True, icon=":material/person_remove:"): if not st.session_state.selected_user_id is None: dialog_delete_user(st.session_state.selected_user_id) else: st.toast("❌ Bitte erst eine Zeile auswählen") if "delete_msg" in st.session_state: st.toast(st.session_state.delete_msg) del st.session_state.delete_msg if txt_search.strip(): txt_search_norm = txt_search.strip().lower() mask = ( df["username"].fillna("").str.lower().str.contains(txt_search_norm) | df["firstname"].fillna("").str.lower().str.contains(txt_search_norm) | df["lastname"].fillna("").str.lower().str.contains(txt_search_norm) ) df_view = df.loc[mask].copy() else: df_view = df.copy() event = st.dataframe(df_view,key="data", on_select="rerun", selection_mode="single-row") rows = event.selection.rows if rows: row_idx = rows[0] st.session_state.selected_user_id = int(df_view.iloc[row_idx]["id"]) else: st.session_state.selected_user_id = None if __name__ == "__main__": sidebar()