# import streamlit as st # import pandas as pd # from db_users import init_db, get_user, update_user, set_password # wie zuvor # from db_users_search import search_users # wie zuvor # st.set_page_config(layout="wide") # init_db() # if "selected_user_id" not in st.session_state: # st.session_state.selected_user_id = None # def open_edit(user_id: int): # st.session_state.selected_user_id = user_id # st.session_state.show_edit = True # @st.dialog("Benutzer bearbeiten") # def edit_user_dialog(user_id: int): # user = get_user(user_id) # if not user: # st.error("Benutzer nicht gefunden.") # return # st.markdown(f"**{user['username']}** (ID {user['id']})") # with st.form("edit_user_form"): # display_name = st.text_input("Anzeigename", value=user.get("display_name") or "") # email = st.text_input("E-Mail", value=user.get("email") or "") # role = st.selectbox("Rolle", ["user", "admin"], index=0 if user["role"] == "user" else 1) # is_active = st.checkbox("Aktiv", value=bool(user["is_active"])) # save = st.form_submit_button("Speichern") # if save: # update_user(user_id, display_name, email, role, is_active) # st.success("Gespeichert.") # st.session_state.show_edit = False # st.rerun() # st.divider() # st.markdown("**Passwort zurücksetzen**") # with st.form("pw_form", clear_on_submit=True): # pw = st.text_input("Neues Passwort", type="password") # pw_save = st.form_submit_button("Passwort setzen") # if pw_save: # if not pw: # st.error("Bitte Passwort eingeben.") # else: # set_password(user_id, pw) # st.success("Passwort aktualisiert.") # st.session_state.show_edit = False # st.rerun() # st.title("Benutzerverwaltung") # q = st.text_input("Suche", placeholder="username / Name / E-Mail") # rows, total = search_users(q, limit=20, offset=0) # st.caption(f"{total} Treffer") # for r in rows: # c1, c2, c3, c4 = st.columns([2, 2, 3, 1]) # c1.write(r["username"]) # c2.write(r.get("display_name") or "") # c3.write(r.get("email") or "") # if c4.button("Ändern", key=f"edit_{r['id']}"): # open_edit(r["id"]) # # Dialog öffnen, wenn Flag gesetzt # if st.session_state.get("show_edit") and st.session_state.selected_user_id: # edit_user_dialog(int(st.session_state.selected_user_id)) # # admin_users.py # import streamlit as st # import pandas as pd # from db_users import init_db, list_users, get_user, create_user, update_user, set_password, delete_user # st.set_page_config(page_title="User Admin", layout="wide") # init_db() # st.title("Benutzerverwaltung") # # --- Übersicht --- # users = list_users() # df = pd.DataFrame(users) # if df.empty: # st.info("Noch keine Benutzer vorhanden.") # df = pd.DataFrame(columns=["id","username","display_name","email","role","is_active","created_at"]) # st.subheader("Übersicht") # st.dataframe(df, use_container_width=True, hide_index=True) # st.divider() # colA, colB = st.columns(2, gap="large") # # --- Neuen Benutzer anlegen --- # with colA: # st.subheader("Neuen Benutzer anlegen") # with st.form("create_user", clear_on_submit=True): # username = st.text_input("Username*", max_chars=50) # password = st.text_input("Initiales Passwort*", type="password") # display_name = st.text_input("Anzeigename") # email = st.text_input("E-Mail") # role = st.selectbox("Rolle", ["user", "admin"], index=0) # is_active = st.checkbox("Aktiv", value=True) # submitted = st.form_submit_button("Anlegen") # if submitted: # if not username or not password: # st.error("Username und Passwort sind Pflicht.") # else: # try: # create_user(username, password, display_name, email, role, is_active) # st.success("Benutzer angelegt.") # st.rerun() # except Exception as e: # st.error(f"Fehler beim Anlegen: {e}") # # --- Bestehenden Benutzer bearbeiten/löschen --- # with colB: # st.subheader("Benutzer bearbeiten / löschen") # user_ids = df["id"].tolist() if "id" in df.columns else [] # selected_id = st.selectbox("Benutzer wählen", user_ids, format_func=lambda uid: f"{uid} – {df.loc[df.id==uid,'username'].values[0] if len(df)>0 else uid}" if uid in user_ids else str(uid)) # user = get_user(int(selected_id)) if selected_id else None # if user: # with st.form("edit_user"): # display_name2 = st.text_input("Anzeigename", value=user.get("display_name") or "") # email2 = st.text_input("E-Mail", value=user.get("email") or "") # role2 = st.selectbox("Rolle", ["user", "admin"], index=0 if user["role"]=="user" else 1) # is_active2 = st.checkbox("Aktiv", value=bool(user["is_active"])) # save = st.form_submit_button("Änderungen speichern") # if save: # update_user(int(selected_id), display_name2, email2, role2, is_active2) # st.success("Gespeichert.") # st.rerun() # st.markdown("**Passwort zurücksetzen**") # with st.form("reset_pw", clear_on_submit=True): # new_pw = st.text_input("Neues Passwort", type="password") # reset = st.form_submit_button("Passwort setzen") # if reset: # if not new_pw: # st.error("Bitte ein Passwort eingeben.") # else: # set_password(int(selected_id), new_pw) # st.success("Passwort aktualisiert.") # st.markdown("**Löschen**") # confirm = st.checkbox("Ich möchte diesen Benutzer wirklich löschen.") # if st.button("Benutzer löschen", disabled=not confirm): # delete_user(int(selected_id)) # st.success("Benutzer gelöscht.") # st.rerun() 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_modify_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 txt_username = st.text_input(label="Benutzername", value=df.iloc[0]["user"]) 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 = ?, firstname = ?, lastname = ?, email = ?, password_hash = ?, new_pwd = ?, role_id = ? where id = ? """ params = (txt_username, 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 = ?, firstname = ?, lastname = ?, email = ?, new_pwd = ?, role_id = ? where id = ? """ params = (txt_username, 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_modify_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_modify_user: if st.button(label="Benutzer bearbeiten", use_container_width=True, icon=":material/person:"): if not st.session_state.selected_user_id is None: dialog_modify_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()