Add some new fields for users table

This commit is contained in:
handi
2025-11-30 14:55:02 +01:00
parent 84e1e152f8
commit 111d0d2756
11 changed files with 184 additions and 139 deletions

View File

@@ -10,31 +10,39 @@ from db import get_conn
# DB Initialisierung: `users`-Tabelle
# ---------------------------------------------------------------------------
def init_auth_db():
"""
Legt die users-Tabelle an.
WICHTIG: password_hash wird als TEXT gespeichert, damit sowohl
streamlit-authenticator als auch dein eigener bcrypt-Code kompatibel sind.
"""
with closing(get_conn()) as conn, conn:
conn.execute(
"""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
email TEXT,
password_hash TEXT NOT NULL,
role TEXT NOT NULL DEFAULT 'user'
)
"""
)
# def init_auth_db():
# """
# Legt die users-Tabelle an.
# WICHTIG: password_hash wird als TEXT gespeichert, damit sowohl
# streamlit-authenticator als auch dein eigener bcrypt-Code kompatibel sind.
# """
# with closing(get_conn()) as conn, conn:
# conn.execute(
# """
# CREATE TABLE IF NOT EXISTS users (
# id INTEGER PRIMARY KEY AUTOINCREMENT,
# username TEXT UNIQUE NOT NULL,
# email TEXT,
# password_hash TEXT NOT NULL,
# role TEXT NOT NULL DEFAULT 'user'
# )
# """
# )
# ---------------------------------------------------------------------------
# Benutzer anlegen
# ---------------------------------------------------------------------------
def create_user(username: str, password: str, role: str = "user", email: str | None = None) -> bool:
def create_user(
username: str,
password: str,
role: str = "user",
email: str | None = None,
firstname: str | None = None,
lastname: str | None = None
) -> bool:
"""
Passwort wird als bcrypt-Hash (TEXT) gespeichert.
"""
@@ -43,8 +51,8 @@ def create_user(username: str, password: str, role: str = "user", email: str | N
try:
with closing(get_conn()) as conn, conn:
conn.execute(
"INSERT INTO users (username, email, password_hash, role) VALUES (?, ?, ?, ?)",
(username, email, pw_hash, role),
"INSERT INTO users (username, email, password_hash, role, firstname, lastname) VALUES (?, ?, ?, ?, ?, ?)",
(username, email, pw_hash, role, firstname, lastname),
)
return True
except Exception:

View File

@@ -1,58 +1,94 @@
# app/main.py
import streamlit as st
from auth import (
init_auth_db,
ensure_logged_in,
authed_header,
current_user,
create_user, # falls du Admin-Funktion brauchst
)
import yaml
from yaml.loader import SafeLoader
import streamlit_authenticator as stauth
from auth_core import load_credentials_from_db, get_role_for_user, create_user
from version import __version__
def content_for(role: str, username: str):
st.header("Dashboard")
def content_for(username: str, role: str):
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)
st.success("Nutzer angelegt.") if ok else st.error(
"Username bereits vorhanden."
)
ok = create_user(new_u.strip(), new_p, new_role, new_email, new_fname, new_lname)
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}**.")
# fachliche Inhalte …
def main():
st.set_page_config(
page_title="Intranet-Portal",
page_title=f"Co-App Start - V{__version__}",
page_icon="🔒",
layout="centered",
)
init_auth_db()
# DB-Struktur sicherstellen
# init_auth_db()
# hier wird entweder:
# - st.session_state genutzt, oder
# - ?session_id=... aus URL geprüft, oder
# - Login-Form gezeigt (und Script gestoppt)
ensure_logged_in()
# --- Config laden (Cookie, etc.) ---
with open("config/auth.yaml", "r", encoding="utf-8") as f:
base_config = yaml.load(f, Loader=SafeLoader)
authed_header()
username, role = current_user()
content_for(role, username)
# --- Credentials dynamisch aus DB laden ---
db_creds = load_credentials_from_db()
base_config["credentials"] = db_creds
authenticator = stauth.Authenticate(
base_config["credentials"],
base_config["cookie"]["name"],
base_config["cookie"]["key"],
base_config["cookie"]["expiry_days"],
#base_config.get("preauthorized", {}),
)
#name, auth_status, username = authenticator.login(location="main", key="Login")
# login_result = authenticator.login(location="main", key="Login")
# if login_result is None:
# st.error("Login-Initialisierung fehlgeschlagen (keine gültigen Credentials?).")
# return
# name, auth_status, username = login_result
authenticator.login(location="main", key="Login")
auth_status = st.session_state.get("authentication_status")
name = st.session_state.get("name")
username = st.session_state.get("username")
if auth_status is False:
st.error("Login fehlgeschlagen.")
return
if auth_status is None:
st.warning("Bitte Benutzername und Passwort eingeben.")
return
# ---- Ab hier eingeloggt (persistenter Cookie) ----
role = get_role_for_user(username)
authenticator.logout("Logout", "sidebar")
st.sidebar.write(f"Angemeldet als **{name}** ({username}, Rolle: {role})")
content_for(username, role)
if __name__ == "__main__":

59
app/main__.py Normal file
View File

@@ -0,0 +1,59 @@
# app/main.py
import streamlit as st
from auth import (
init_auth_db,
ensure_logged_in,
authed_header,
current_user,
create_user, # falls du Admin-Funktion brauchst
)
def content_for(role: str, username: str):
st.header("Dashboard")
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_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)
st.success("Nutzer angelegt.") if ok else st.error(
"Username bereits vorhanden."
)
else:
st.warning("Bitte Username und Passwort eingeben.")
st.subheader("Dein Bereich")
st.write(f"Personalisierter Content für **{username}**.")
# fachliche Inhalte …
def main():
st.set_page_config(
page_title="Intranet-Portal",
page_icon="🔒",
layout="centered",
)
init_auth_db()
# hier wird entweder:
# - st.session_state genutzt, oder
# - ?session_id=... aus URL geprüft, oder
# - Login-Form gezeigt (und Script gestoppt)
ensure_logged_in()
authed_header()
username, role = current_user()
content_for(role, username)
if __name__ == "__main__":
main()

View File

@@ -1,87 +0,0 @@
# app/main.py
import streamlit as st
import yaml
from yaml.loader import SafeLoader
import streamlit_authenticator as stauth
from auth_core import (
init_auth_db,
load_credentials_from_db,
get_role_for_user,
create_user,
)
from version import __version__
def content_for(username: str, role: str):
st.header("Dashboard")
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_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)
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}**.")
def main():
st.set_page_config(
page_title=f"Intranet-Portal v{__version__}",
page_icon="🔒",
layout="centered",
)
# DB-Struktur sicherstellen
init_auth_db()
# --- Config laden (Cookie, etc.) ---
with open("config/auth.yaml", "r", encoding="utf-8") as f:
base_config = yaml.load(f, Loader=SafeLoader)
# --- Credentials dynamisch aus DB laden ---
db_creds = load_credentials_from_db()
base_config["credentials"] = db_creds
authenticator = stauth.Authenticate(
base_config["credentials"],
base_config["cookie"]["name"],
base_config["cookie"]["key"],
base_config["cookie"]["expiry_days"],
base_config.get("preauthorized", {}),
)
name, auth_status, username = authenticator.login("Login", "main")
if auth_status is False:
st.error("Login fehlgeschlagen.")
return
if auth_status is None:
st.warning("Bitte Benutzername und Passwort eingeben.")
return
# ---- Ab hier eingeloggt (persistenter Cookie) ----
role = get_role_for_user(username)
authenticator.logout("Logout", "sidebar")
st.sidebar.write(f"Angemeldet als **{name}** ({username}, Rolle: {role})")
content_for(username, role)
if __name__ == "__main__":
main()

View File

@@ -6,7 +6,7 @@ from logging_config import setup_logging
import os
from contextlib import closing
import getpass
from auth import create_user
from auth_core import create_user
APP_ENV = os.environ.get("APP_ENV", "dev")
logger = setup_logging(APP_ENV)
@@ -107,7 +107,14 @@ def create_admin_user():
logger.warning("Passwörter stimmen nicht überein! Abbruch.")
return
ok = create_user(ADMIN_USERNAME, pw1, role="admin")
ok = create_user(
username=ADMIN_USERNAME,
password=pw1,
role="admin",
email="admin@co_app",
firstname="co_app",
lastname="admin"
)
if ok:
logger.info(f"Admin-Benutzer '{ADMIN_USERNAME}' wurde angelegt.")

View File

@@ -1,7 +1,7 @@
cookie:
expiry_days: 7
key: "please_change_this_cookie_signing_key"
name: "intranet_session"
key: "tHr1FXOYg-xsYBGVu7amRrY8PAdC2gM_zyjPEPPkPgG8tAsLY4QGPZvCvMS9win0D94uawAxsmZjN6O_VlRhUQ"
name: "co_app-session"
preauthorized:
emails: []

Binary file not shown.

View File

@@ -1,3 +1,5 @@
begin;
CREATE TABLE IF NOT EXISTS sessions (
id TEXT PRIMARY KEY,
username TEXT NOT NULL,
@@ -5,6 +7,7 @@ CREATE TABLE IF NOT EXISTS sessions (
expires_at INTEGER NOT NULL,
FOREIGN KEY (username) REFERENCES users(username) ON DELETE CASCADE
);
INSERT INTO schema_version (version) VALUES ('20251129_162900_add_table_sessions');
COMMIT;

View File

@@ -0,0 +1,8 @@
begin;
alter table users
add column email text not null;
INSERT INTO schema_version (version) VALUES ('20251130_124700_add_col_email_users');
COMMIT;

View File

@@ -0,0 +1,11 @@
begin;
alter table users
add column firstname text;
alter table users
add column lastname text;
INSERT INTO schema_version (version) VALUES ('20251130_1411_add_col_name_users');
COMMIT;