Add pages permission

This commit is contained in:
knedlik
2025-12-10 07:43:10 +01:00
parent 96be7567eb
commit 7f21716358
13 changed files with 144 additions and 206 deletions

Binary file not shown.

View File

@@ -15,3 +15,4 @@ def get_list(sql, params=None):
df = pd.read_sql_query(sql, conn, params=params)
conn.close()
return df

View File

@@ -2,7 +2,7 @@
from contextlib import closing
import bcrypt
from app_db.app_db import get_conn
from app_db.app_db import get_conn, get_list
# ---------------------------------------------------------------------------
@@ -35,7 +35,7 @@ def create_user(
# ---------------------------------------------------------------------------
# Benutzer überprüfen (z.B. für deine alte Streamlit-Login-Maske)
# Benutzer überprüfen
# ---------------------------------------------------------------------------
def verify_user(username: str, password: str):
@@ -84,6 +84,60 @@ def get_fullname_for_user(username: str) -> str:
).fetchone()
return row[0] if row else "user"
# ---------------------------------------------------------------------------
# Sidebar-Einträge für den Benutzer
# ---------------------------------------------------------------------------
def get_sidebar(role_text: str, username: str):
if role_text == "admin":
sql = """
select
g.group_id,
g.group_text,
d.dash_id,
d.dash_text,
d.page_file,
d.dash_type
from
groups g
left join dashboards d
on g.group_id = d.group_id
where
g.active = 1
and d.active = 1
"""
else:
sql = """
SELECT
d.group_id,
g.group_text,
p.dash_id,
d.dash_text,
d.page_file,
d.dash_type
FROM
users u
left join permissions p
on u.role_id = p.role_id
left join dashboards d
on p.dash_id = d.dash_id
left join groups g
on d.group_id = g.group_id
where
u.active = 1
and g.active = 1
and d.active = 1
and p.active = 1
and u.username = ?
order by
g.order_no,
d.order_no
"""
params = (username,) if "?" in sql else None
df = get_list(sql, params)
return df
# ---------------------------------------------------------------------------
# Credential-Lader für streamlit-authenticator
# ---------------------------------------------------------------------------

View File

@@ -10,7 +10,7 @@ def get_authenticator():
with open("config/auth.yaml", "r", encoding="utf-8") as f:
base_config = yaml.load(f, Loader=SafeLoader)
db_creds = load_credentials_from_db()
db_creds = load_credentials_from_db() # Hier wird name, email und password geladen
base_config["credentials"] = db_creds
authenticator = stauth.Authenticate(

View File

@@ -1,45 +0,0 @@
import streamlit as st
from auth_runtime import require_login
from ui.sidebar import build_sidebar, hide_sidebar_if_logged_out
from auth import get_fullname_for_user
hide_sidebar_if_logged_out()
st.set_page_config(page_title="Co-App Home", page_icon="🏠")
authenticator = require_login()
st.session_state["authenticator"] = authenticator
build_sidebar()
def render(username: str, role: str):
st.title("Benutzerverwaltung")
with st.expander("Neuen Nutzer anlegen"):
new_u = st.text_input("Neuer Username", key="new_u")
new_fname = st.text_input("Vorname", key="new_fname")
new_lname = st.text_input("Nachname", key="new_lname")
new_email = st.text_input("E-Mail", key="new_email")
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,
new_email.strip() or None,
new_fname.strip() or None,
new_lname.strip() or None,
)
st.success("Nutzer angelegt.") if ok else st.error(
"Username bereits vorhanden oder Fehler."
)
else:
st.warning("Bitte Username und Passwort eingeben.")
st.subheader("Dein Bereich")
st.write(f"Personalisierter Content für **{username}**.")

View File

@@ -1,24 +0,0 @@
import importlib
def get_dashboard_renderer(code: str):
"""
Liefert die passende Render-Funktion zum Dashboard-Code.
- "home" -> interne Funktion home_dashboard
- alles andere -> Modul app.dashboards.<code> mit Funktion render(username, role)
"""
if code == "home":
return home_dashboard
module_name = f"app.dashboards.{code}"
try:
module = importlib.import_module(module_name)
except ModuleNotFoundError:
# Zum Debuggen:
st.error(f"Modul '{module_name}' wurde nicht gefunden.")
return None
if not hasattr(module, "render"):
st.error(f"Modul '{module_name}' hat keine Funktion render().")
return None
return module.render

View File

@@ -1,46 +0,0 @@
import streamlit as st
from auth import create_user, get_fullname_for_user, get_role_for_user
from ui.sidebar import build_sidebar
build_sidebar
st.header("Controlling-Portal")
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_fname = st.text_input("Vorname", key="new_fname")
# new_lname = st.text_input("Nachname", key="new_lname")
# new_email = st.text_input("E-Mail", key="new_email")
# 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,
# new_email.strip() or None,
# new_fname.strip() or None,
# new_lname.strip() or None,
# )
# st.success("Nutzer angelegt.") if ok else st.error(
# "Username bereits vorhanden oder Fehler."
# )
# else:
# st.warning("Bitte Username und Passwort eingeben.")
# st.subheader("Dein Bereich")
# st.write(f"Personalisierter Content für **{username}**.")

View File

@@ -2,31 +2,54 @@ import streamlit as st
import logging
from logging_config import setup_logging
from version import __version__
from auth import get_role_for_user, get_fullname_for_user, get_sidebar
from auth_runtime import require_login
from ui.sidebar import build_sidebar
import os
from app_db.app_db import get_list
APP_ENV = os.environ.get("APP_ENV", "dev")
logger = setup_logging(APP_ENV)
#logger.info(f"Starting migration - APP-Version {__version__}")
logger = logging.getLogger(__name__)
def main():
st.set_page_config(
page_title=f"Co-App Start - V{__version__}",
page_title=f"Co-App Home - V{__version__}",
page_icon="🔒",
layout="centered",
)
authenticator = require_login()
# damit build_sidebar den authenticator findet:
#--------------------------------------------------------------------------------
# Ab hier ist Benutzer angemeldet!!
#--------------------------------------------------------------------------------
# Alles was man so braucht in der App wird in session_state abgelegt
# zuerst den authenticator holen ...
st.session_state["authenticator"] = authenticator
# ... dann ist der name des users in der sesstion_state verfügbar!
# Ich suche mir erst mal alles zusammen, was ich dann in session_state speichern will ...
username = st.session_state.get("name") # wird duch authenticator gesetzt
role_text = get_role_for_user(username)
fullname = get_fullname_for_user(username)
sidebar = get_sidebar(role_text, username)
# ... und lege es dann im session_state ab.
st.session_state["role_text"] = role_text
st.session_state["fullname"] = fullname
st.session_state["df_sidebar"] = sidebar
build_sidebar()
st.header("Controlling-Portal")
st.info(f"Willkommen, {st.session_state.get('username')}!")
st.text("Hier könnte eine Nachricht für den Benutzer stehen")
if __name__ == "__main__":
main()

View File

@@ -2,6 +2,16 @@ import streamlit as st
import pandas as pd
from data.scriptloader import get_sql
from data.db import get_conn
from auth_runtime import require_login
from ui.sidebar import build_sidebar, hide_sidebar_if_logged_out
from auth import get_fullname_for_user
hide_sidebar_if_logged_out()
st.set_page_config(page_title="Co-App Home", page_icon="🏠")
authenticator = require_login()
st.session_state["authenticator"] = authenticator

View File

@@ -10,8 +10,9 @@ st.set_page_config(page_title="Co-App Home", page_icon="🏠")
authenticator = require_login()
st.session_state["authenticator"] = authenticator
build_sidebar()
#build_sidebar()
username = st.session_state.get("username")
st.header("Controlling-Portal")
st.info(f"Willkommen, {get_fullname_for_user(username)}!")
st.markdown("**Hier könnte eine Hinweistext für den Benutzer stehen**")

View File

@@ -2,16 +2,25 @@ import streamlit as st
from auth_runtime import require_login
from ui.sidebar import hide_sidebar_if_logged_out
from auth import create_user
from pathlib import Path
from tools.check_permission import check
DASH_NAME = Path(__file__).stem # Hier muss die dash_id aus der DB stehen -> wird gegen die session_state geprüft (User-Berechtigung)
hide_sidebar_if_logged_out()
st.set_page_config(page_title="Co-App Home", page_icon="🏠")
st.set_page_config(page_title="Co-App Benutzer", page_icon="🏠")
authenticator = require_login()
st.session_state["authenticator"] = authenticator
username = st.session_state.get("username")
df = st.session_state.get("df_sidebar")
# build_sidebar()
if check(df,DASH_NAME) == False:
st.markdown("**FEHLER**")
st.error("Die Seite kann nicht angezeigt werden - keine Berechtigung!")
st.stop()
st.title("Benutzerverwaltung")

View File

@@ -0,0 +1,27 @@
import streamlit as st
from auth_runtime import require_login
from auth import get_sidebar, get_fullname_for_user, get_role_for_user
def check(df, page_name):
if "df_sidebar" not in st.session_state:
# authenticator = require_login()
username = st.session_state.get("username")
role_text = get_role_for_user(username)
fullname = get_fullname_for_user(username)
df = get_sidebar(role_text, username)
st.session_state["role_text"] = role_text
st.session_state["fullname"] = fullname
st.session_state["df_sidebar"] = df
if df is None or df.empty:
return False # oder True je nach gewünschtem Verhalten
allowed = not df[
(df["dash_type"] == "page") &
(df["page_file"] == page_name)
].empty
return True

View File

@@ -11,64 +11,18 @@ def build_sidebar():
return
authenticator = st.session_state.get("authenticator")
username = st.session_state.get("username")
username = st.session_state.get("name")
role_text = st.session_state.get("role_text")
fullname = st.session_state.get("fullname")
if not authenticator or not username:
return
role = get_role_for_user(username)
fullname = get_fullname_for_user(username)
if role == "admin":
sql = """
select
g.group_id,
g.group_text,
d.dash_id,
d.dash_text,
d.page_file,
d.dash_type
from
groups g
left join dashboards d
on g.group_id = d.group_id
where
g.active = 1
and d.active = 1
"""
else:
sql = """
SELECT
d.group_id,
g.group_text,
p.dash_id,
d.dash_text,
d.page_file,
d.dash_type
FROM
users u
left join permissions p
on u.role_id = p.role_id
left join dashboards d
on p.dash_id = d.dash_id
left join groups g
on d.group_id = g.group_id
where
u.active = 1
and g.active = 1
and d.active = 1
and p.active = 1
and u.username = ?
order by
g.order_no,
d.order_no
"""
params = (username,) if "?" in sql else None
df = get_list(sql, params)
df = st.session_state.get("df_sidebar")
with st.sidebar:
st.logo("app/images/GMN_Logo_neu_rgb.png", size="small")
st.write(f"**{fullname}** ({role})")
st.markdown(f"**{fullname}** ({role_text})")
col1, col2 = st.columns(2)
with col1:
@@ -81,32 +35,6 @@ def build_sidebar():
st.divider()
st.markdown("## Menü")
# for group_text, df_group in df.groupby("group_text"):
# with st.expander(group_text, expanded=False):
# for _, row in df_group.iterrows():
# dash_type = row.get("dash_type")
# page_file = row.get("page_file")
# label = row.get("dash_text", "")
# print(dash_type, page_file, label)
# # 1) echte Streamlit-Page
# if dash_type == "page" and isinstance(page_file, str) and page_file.strip():
# st.page_link(
# page_file, # z.B. "pages/umsatz.py"
# label=label,
# )
# # 2) externer Link (oder interner HTTP-Link)
# elif dash_type == "url" and isinstance(page_file, str) and page_file.strip():
# st.markdown(
# f"[{label}]({page_file})",
# unsafe_allow_html=False,
# )
# # 3) Platzhalter / noch nicht implementiert
# else:
# st.write(f"▫️ {label} (in Vorbereitung)")
# --- Suchfeld ---
query = st.text_input("Menü-Suche", "", placeholder="z.B. Umsatz, Kosten, User ...")
query = query.strip()
@@ -145,7 +73,7 @@ def build_sidebar():
# Streamlit-Page
if dash_type == "page" and isinstance(page_file, str) and page_file.strip():
st.page_link(page_file, label=label)
st.page_link(f"pages/{page_file}.py", label=label)
# Externer Link
elif dash_type == "url" and isinstance(page_file, str) and page_file.strip():