second commit

This commit is contained in:
2026-08-19 22:33:19 +02:00
parent 411812e954
commit 199f306993
107 changed files with 5984 additions and 0 deletions

33
app/rbac.py Normal file
View File

@ -0,0 +1,33 @@
"""RBAC-Durchsetzung: Rolle × Hostgruppe (siehe Konzept 4.6)."""
from __future__ import annotations
import aiosqlite
async def user_has_role(
conn: aiosqlite.Connection, *, user_id: int, host_group_id: int, role_name: str
) -> bool:
cursor = await conn.execute(
"""
SELECT 1 FROM user_hostgroup_roles uhr
JOIN roles r ON r.id = uhr.role_id
WHERE uhr.user_id = ?
AND uhr.host_group_id = ?
AND r.name = ?
AND (uhr.expires_at IS NULL OR uhr.expires_at > strftime('%Y-%m-%dT%H:%M:%fZ','now'))
LIMIT 1
""",
(user_id, host_group_id, role_name),
)
row = await cursor.fetchone()
return row is not None
async def user_has_role_for_host(
conn: aiosqlite.Connection, *, user_id: int, host_id: int, role_name: str
) -> bool:
cursor = await conn.execute("SELECT host_group_id FROM hosts WHERE id = ?", (host_id,))
row = await cursor.fetchone()
if row is None:
return False
return await user_has_role(conn, user_id=user_id, host_group_id=row[0], role_name=role_name)