Files
co_app/app/pages/user.py
2025-12-19 08:27:36 +01:00

276 lines
9.3 KiB
Python

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