From 8c089d4f675ed7d6bf304b6f5fc4e8d8cc629c70 Mon Sep 17 00:00:00 2001 From: mscadm Date: Mon, 13 Jul 2026 15:28:53 +0000 Subject: [PATCH] feat: Nutzerverwaltung + CMDB + Wissensdatenbank (Grundgeruest) --- db.py | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) diff --git a/db.py b/db.py index 482b743..04acd88 100644 --- a/db.py +++ b/db.py @@ -135,6 +135,36 @@ def email_exists(email): return cur.fetchone() is not None +def list_users(tenant_id): + with get_conn() as conn: + with _dict_cursor(conn) as cur: + cur.execute( + "SELECT id, email, role, active, auth_source, created_at, last_login_at " + "FROM users WHERE tenant_id=%s ORDER BY email", (tenant_id,)) + return cur.fetchall() + + +def get_user(tenant_id, user_id): + with get_conn() as conn: + with _dict_cursor(conn) as cur: + cur.execute( + "SELECT id, email, role, active, auth_source, created_at, last_login_at " + "FROM users WHERE tenant_id=%s AND id=%s", (tenant_id, user_id)) + return cur.fetchone() + + +def set_user_role(tenant_id, user_id, role): + with get_conn() as conn: + with conn.cursor() as cur: + cur.execute("UPDATE users SET role=%s WHERE tenant_id=%s AND id=%s", (role, tenant_id, user_id)) + + +def set_user_active(tenant_id, user_id, active): + with get_conn() as conn: + with conn.cursor() as cur: + cur.execute("UPDATE users SET active=%s WHERE tenant_id=%s AND id=%s", (active, tenant_id, user_id)) + + # ── Audit-Log ─────────────────────────────────────────────────────────────────── def log_audit(tenant_id, user_id, aktion, entity_typ=None, entity_id=None, details=None, ip=None): with get_conn() as conn: @@ -321,3 +351,148 @@ def run_retention_cleanup(): finally: with conn.cursor() as cur: cur.execute("SELECT pg_advisory_unlock(%s)", (_RETENTION_LOCK_KEY,)) + + + +# ── CMDB (Configuration Management Database) ───────────────────────────────── +def create_ci(tenant_id, name, ci_typ, status, beschreibung, attribute): + with get_conn() as conn: + with _dict_cursor(conn) as cur: + cur.execute( + """INSERT INTO configuration_items + (tenant_id, name, ci_typ, status, beschreibung, attribute) + VALUES (%s,%s,%s,%s,%s,%s) RETURNING id""", + (tenant_id, name, ci_typ, status, beschreibung, json.dumps(attribute or {})), + ) + return cur.fetchone()["id"] + + +def list_cis(tenant_id, ci_typ=None): + with get_conn() as conn: + with _dict_cursor(conn) as cur: + if ci_typ: + cur.execute( + "SELECT * FROM configuration_items WHERE tenant_id=%s AND ci_typ=%s ORDER BY name", + (tenant_id, ci_typ)) + else: + cur.execute( + "SELECT * FROM configuration_items WHERE tenant_id=%s ORDER BY ci_typ, name", + (tenant_id,)) + return cur.fetchall() + + +def get_ci(tenant_id, ci_id): + with get_conn() as conn: + with _dict_cursor(conn) as cur: + cur.execute( + "SELECT * FROM configuration_items WHERE tenant_id=%s AND id=%s", + (tenant_id, ci_id)) + ci = cur.fetchone() + if not ci: + return None + ci = dict(ci) + cur.execute( + """SELECT r.*, c.name AS to_name FROM ci_relationships r + JOIN configuration_items c ON c.id = r.to_ci_id + WHERE r.tenant_id=%s AND r.from_ci_id=%s ORDER BY r.id""", + (tenant_id, ci_id)) + ci["rel_out"] = cur.fetchall() + cur.execute( + """SELECT r.*, c.name AS from_name FROM ci_relationships r + JOIN configuration_items c ON c.id = r.from_ci_id + WHERE r.tenant_id=%s AND r.to_ci_id=%s ORDER BY r.id""", + (tenant_id, ci_id)) + ci["rel_in"] = cur.fetchall() + return ci + + +def update_ci(tenant_id, ci_id, name, ci_typ, status, beschreibung, attribute): + with get_conn() as conn: + with conn.cursor() as cur: + cur.execute( + """UPDATE configuration_items SET name=%s, ci_typ=%s, status=%s, + beschreibung=%s, attribute=%s, updated_at=now() + WHERE tenant_id=%s AND id=%s""", + (name, ci_typ, status, beschreibung, json.dumps(attribute or {}), tenant_id, ci_id), + ) + + +def delete_ci(tenant_id, ci_id): + with get_conn() as conn: + with conn.cursor() as cur: + cur.execute("DELETE FROM configuration_items WHERE tenant_id=%s AND id=%s", (tenant_id, ci_id)) + + +def create_ci_relationship(tenant_id, from_ci_id, to_ci_id, beziehungs_typ): + with get_conn() as conn: + with _dict_cursor(conn) as cur: + cur.execute( + """INSERT INTO ci_relationships (tenant_id, from_ci_id, to_ci_id, beziehungs_typ) + VALUES (%s,%s,%s,%s) RETURNING id""", + (tenant_id, from_ci_id, to_ci_id, beziehungs_typ), + ) + return cur.fetchone()["id"] + + +def delete_ci_relationship(tenant_id, rel_id): + with get_conn() as conn: + with conn.cursor() as cur: + cur.execute("DELETE FROM ci_relationships WHERE tenant_id=%s AND id=%s", (tenant_id, rel_id)) + + +# ── Wissensdatenbank ────────────────────────────────────────────────────────── +def create_kb_article(tenant_id, titel, kategorie, inhalt, tags, autor_user_id): + with get_conn() as conn: + with _dict_cursor(conn) as cur: + cur.execute( + """INSERT INTO kb_articles (tenant_id, titel, kategorie, inhalt, tags, autor_user_id) + VALUES (%s,%s,%s,%s,%s,%s) RETURNING id""", + (tenant_id, titel, kategorie, inhalt, tags, autor_user_id), + ) + return cur.fetchone()["id"] + + +def list_kb_articles(tenant_id, kategorie=None, q=None): + with get_conn() as conn: + with _dict_cursor(conn) as cur: + sql = """SELECT k.*, u.email AS autor_email FROM kb_articles k + LEFT JOIN users u ON u.id = k.autor_user_id + WHERE k.tenant_id=%s""" + params = [tenant_id] + if kategorie: + sql += " AND k.kategorie=%s" + params.append(kategorie) + if q: + sql += " AND (k.titel ILIKE %s OR k.inhalt ILIKE %s OR k.tags ILIKE %s)" + like = "%%%s%%" % q + params += [like, like, like] + sql += " ORDER BY k.updated_at DESC" + cur.execute(sql, params) + return cur.fetchall() + + +def get_kb_article(tenant_id, article_id): + with get_conn() as conn: + with _dict_cursor(conn) as cur: + cur.execute( + """SELECT k.*, u.email AS autor_email FROM kb_articles k + LEFT JOIN users u ON u.id = k.autor_user_id + WHERE k.tenant_id=%s AND k.id=%s""", + (tenant_id, article_id)) + return cur.fetchone() + + +def update_kb_article(tenant_id, article_id, titel, kategorie, inhalt, tags): + with get_conn() as conn: + with conn.cursor() as cur: + cur.execute( + """UPDATE kb_articles SET titel=%s, kategorie=%s, inhalt=%s, tags=%s, updated_at=now() + WHERE tenant_id=%s AND id=%s""", + (titel, kategorie, inhalt, tags, tenant_id, article_id), + ) + + +def delete_kb_article(tenant_id, article_id): + with get_conn() as conn: + with conn.cursor() as cur: + cur.execute("DELETE FROM kb_articles WHERE tenant_id=%s AND id=%s", (tenant_id, article_id))