Add pages permission
This commit is contained in:
Binary file not shown.
@@ -14,4 +14,5 @@ def get_list(sql, params=None):
|
|||||||
conn = get_conn()
|
conn = get_conn()
|
||||||
df = pd.read_sql_query(sql, conn, params=params)
|
df = pd.read_sql_query(sql, conn, params=params)
|
||||||
conn.close()
|
conn.close()
|
||||||
return df
|
return df
|
||||||
|
|
||||||
|
|||||||
58
app/auth.py
58
app/auth.py
@@ -2,7 +2,7 @@
|
|||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
import bcrypt
|
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):
|
def verify_user(username: str, password: str):
|
||||||
@@ -84,6 +84,60 @@ def get_fullname_for_user(username: str) -> str:
|
|||||||
).fetchone()
|
).fetchone()
|
||||||
return row[0] if row else "user"
|
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
|
# Credential-Lader für streamlit-authenticator
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ def get_authenticator():
|
|||||||
with open("config/auth.yaml", "r", encoding="utf-8") as f:
|
with open("config/auth.yaml", "r", encoding="utf-8") as f:
|
||||||
base_config = yaml.load(f, Loader=SafeLoader)
|
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
|
base_config["credentials"] = db_creds
|
||||||
|
|
||||||
authenticator = stauth.Authenticate(
|
authenticator = stauth.Authenticate(
|
||||||
|
|||||||
@@ -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}**.")
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
@@ -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}**.")
|
|
||||||
31
app/main.py
31
app/main.py
@@ -2,31 +2,54 @@ import streamlit as st
|
|||||||
import logging
|
import logging
|
||||||
from logging_config import setup_logging
|
from logging_config import setup_logging
|
||||||
from version import __version__
|
from version import __version__
|
||||||
|
from auth import get_role_for_user, get_fullname_for_user, get_sidebar
|
||||||
from auth_runtime import require_login
|
from auth_runtime import require_login
|
||||||
from ui.sidebar import build_sidebar
|
from ui.sidebar import build_sidebar
|
||||||
import os
|
import os
|
||||||
|
from app_db.app_db import get_list
|
||||||
|
|
||||||
APP_ENV = os.environ.get("APP_ENV", "dev")
|
APP_ENV = os.environ.get("APP_ENV", "dev")
|
||||||
|
|
||||||
logger = setup_logging(APP_ENV)
|
logger = setup_logging(APP_ENV)
|
||||||
#logger.info(f"Starting migration - APP-Version {__version__}")
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
st.set_page_config(
|
st.set_page_config(
|
||||||
page_title=f"Co-App Start - V{__version__}",
|
page_title=f"Co-App Home - V{__version__}",
|
||||||
page_icon="🔒",
|
page_icon="🔒",
|
||||||
layout="centered",
|
layout="centered",
|
||||||
)
|
)
|
||||||
|
|
||||||
authenticator = require_login()
|
authenticator = require_login()
|
||||||
# damit build_sidebar den authenticator findet:
|
|
||||||
st.session_state["authenticator"] = authenticator
|
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------------------
|
||||||
|
# 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()
|
build_sidebar()
|
||||||
|
|
||||||
st.header("Controlling-Portal")
|
st.header("Controlling-Portal")
|
||||||
st.info(f"Willkommen, {st.session_state.get('username')}!")
|
st.info(f"Willkommen, {st.session_state.get('username')}!")
|
||||||
|
|
||||||
|
st.text("Hier könnte eine Nachricht für den Benutzer stehen")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
@@ -2,6 +2,16 @@ import streamlit as st
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
from data.scriptloader import get_sql
|
from data.scriptloader import get_sql
|
||||||
from data.db import get_conn
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ st.set_page_config(page_title="Co-App Home", page_icon="🏠")
|
|||||||
authenticator = require_login()
|
authenticator = require_login()
|
||||||
st.session_state["authenticator"] = authenticator
|
st.session_state["authenticator"] = authenticator
|
||||||
|
|
||||||
build_sidebar()
|
#build_sidebar()
|
||||||
|
|
||||||
username = st.session_state.get("username")
|
username = st.session_state.get("username")
|
||||||
st.header("Controlling-Portal")
|
st.header("Controlling-Portal")
|
||||||
st.info(f"Willkommen, {get_fullname_for_user(username)}!")
|
st.info(f"Willkommen, {get_fullname_for_user(username)}!")
|
||||||
|
st.markdown("**Hier könnte eine Hinweistext für den Benutzer stehen**")
|
||||||
@@ -2,16 +2,25 @@ import streamlit as st
|
|||||||
from auth_runtime import require_login
|
from auth_runtime import require_login
|
||||||
from ui.sidebar import hide_sidebar_if_logged_out
|
from ui.sidebar import hide_sidebar_if_logged_out
|
||||||
from auth import create_user
|
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()
|
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()
|
authenticator = require_login()
|
||||||
st.session_state["authenticator"] = authenticator
|
|
||||||
username = st.session_state.get("username")
|
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")
|
st.title("Benutzerverwaltung")
|
||||||
|
|
||||||
|
|||||||
27
app/tools/check_permission.py
Normal file
27
app/tools/check_permission.py
Normal 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
|
||||||
@@ -11,64 +11,18 @@ def build_sidebar():
|
|||||||
return
|
return
|
||||||
|
|
||||||
authenticator = st.session_state.get("authenticator")
|
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:
|
if not authenticator or not username:
|
||||||
return
|
return
|
||||||
|
|
||||||
role = get_role_for_user(username)
|
df = st.session_state.get("df_sidebar")
|
||||||
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)
|
|
||||||
|
|
||||||
with st.sidebar:
|
with st.sidebar:
|
||||||
st.logo("app/images/GMN_Logo_neu_rgb.png", size="small")
|
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)
|
col1, col2 = st.columns(2)
|
||||||
with col1:
|
with col1:
|
||||||
@@ -81,32 +35,6 @@ def build_sidebar():
|
|||||||
st.divider()
|
st.divider()
|
||||||
st.markdown("## Menü")
|
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 ---
|
# --- Suchfeld ---
|
||||||
query = st.text_input("Menü-Suche", "", placeholder="z.B. Umsatz, Kosten, User ...")
|
query = st.text_input("Menü-Suche", "", placeholder="z.B. Umsatz, Kosten, User ...")
|
||||||
query = query.strip()
|
query = query.strip()
|
||||||
@@ -145,7 +73,7 @@ def build_sidebar():
|
|||||||
|
|
||||||
# Streamlit-Page
|
# Streamlit-Page
|
||||||
if dash_type == "page" and isinstance(page_file, str) and page_file.strip():
|
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
|
# Externer Link
|
||||||
elif dash_type == "url" and isinstance(page_file, str) and page_file.strip():
|
elif dash_type == "url" and isinstance(page_file, str) and page_file.strip():
|
||||||
|
|||||||
Reference in New Issue
Block a user