Files
ssh-jumphost/app/catalog/routes.py
2026-08-20 17:10:19 +02:00

109 lines
4.6 KiB
Python

"""Sicht fuer normale Nutzer: nur die Hosts/Aktionen, fuer die RBAC eine
Rolle in der jeweiligen Hostgruppe vergeben hat -- entweder direkt (Konzept
4.6) oder ueber eine Benutzergruppe, in der der User Mitglied ist (volle
Rollen-Vererbung, siehe app/rbac.py)."""
from __future__ import annotations
from fastapi import APIRouter, Depends
from app.auth.deps import CurrentUser, get_current_user
from app.db import get_db
router = APIRouter(prefix="/catalog", tags=["catalog"])
@router.get("/hosts")
async def my_hosts(user: CurrentUser = Depends(get_current_user)):
conn = get_db()
if user.is_admin:
cursor = await conn.execute(
"SELECT h.id, h.hostname, h.address, h.protocol, h.os_type, h.host_group_id, "
"g.name, h.clipboard_enabled, h.file_transfer_enabled "
"FROM hosts h JOIN host_groups g ON g.id = h.host_group_id "
"WHERE h.is_active = 1 ORDER BY g.name, h.hostname"
)
rows = await cursor.fetchall()
hosts = [dict(zip(
("id", "hostname", "address", "protocol", "os_type", "host_group_id", "host_group_name",
"clipboard_enabled", "file_transfer_enabled"), r
)) for r in rows]
for h in hosts:
h["can_connect"] = True
h["can_file_transfer"] = True
h["can_view_credentials"] = True
return hosts
cursor = await conn.execute(
"""
SELECT h.id, h.hostname, h.address, h.protocol, h.os_type, h.host_group_id,
g.name, h.clipboard_enabled, h.file_transfer_enabled
FROM hosts h
JOIN host_groups g ON g.id = h.host_group_id
WHERE h.is_active = 1
AND (
EXISTS (
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 = h.host_group_id
AND r.name IN ('ssh_connect', 'rdp_connect')
AND (uhr.expires_at IS NULL OR uhr.expires_at > strftime('%Y-%m-%dT%H:%M:%fZ','now'))
)
OR EXISTS (
SELECT 1 FROM group_hostgroup_roles ghr
JOIN roles r ON r.id = ghr.role_id
JOIN user_group_members ugm ON ugm.user_group_id = ghr.user_group_id
WHERE ugm.user_id = ? AND ghr.host_group_id = h.host_group_id
AND r.name IN ('ssh_connect', 'rdp_connect')
AND (ghr.expires_at IS NULL OR ghr.expires_at > strftime('%Y-%m-%dT%H:%M:%fZ','now'))
)
)
ORDER BY g.name, h.hostname
""",
(user.id, user.id),
)
rows = await cursor.fetchall()
hosts = [dict(zip(
("id", "hostname", "address", "protocol", "os_type", "host_group_id", "host_group_name",
"clipboard_enabled", "file_transfer_enabled"), r
)) for r in rows]
ft_cursor = await conn.execute(
"""
SELECT uhr.host_group_id FROM user_hostgroup_roles uhr
JOIN roles r ON r.id = uhr.role_id
WHERE uhr.user_id = ? AND r.name = 'file_transfer'
AND (uhr.expires_at IS NULL OR uhr.expires_at > strftime('%Y-%m-%dT%H:%M:%fZ','now'))
UNION
SELECT ghr.host_group_id FROM group_hostgroup_roles ghr
JOIN roles r ON r.id = ghr.role_id
JOIN user_group_members ugm ON ugm.user_group_id = ghr.user_group_id
WHERE ugm.user_id = ? AND r.name = 'file_transfer'
AND (ghr.expires_at IS NULL OR ghr.expires_at > strftime('%Y-%m-%dT%H:%M:%fZ','now'))
""",
(user.id, user.id),
)
ft_groups = {row[0] for row in await ft_cursor.fetchall()}
cred_cursor = await conn.execute(
"""
SELECT uhr.host_group_id FROM user_hostgroup_roles uhr
JOIN roles r ON r.id = uhr.role_id
WHERE uhr.user_id = ? AND r.name IN ('credentials_view', 'credentials_manage')
AND (uhr.expires_at IS NULL OR uhr.expires_at > strftime('%Y-%m-%dT%H:%M:%fZ','now'))
UNION
SELECT ghr.host_group_id FROM group_hostgroup_roles ghr
JOIN roles r ON r.id = ghr.role_id
JOIN user_group_members ugm ON ugm.user_group_id = ghr.user_group_id
WHERE ugm.user_id = ? AND r.name IN ('credentials_view', 'credentials_manage')
AND (ghr.expires_at IS NULL OR ghr.expires_at > strftime('%Y-%m-%dT%H:%M:%fZ','now'))
""",
(user.id, user.id),
)
cred_groups = {row[0] for row in await cred_cursor.fetchall()}
for h in hosts:
h["can_connect"] = True
h["can_file_transfer"] = h["host_group_id"] in ft_groups and bool(h["file_transfer_enabled"])
h["can_view_credentials"] = h["host_group_id"] in cred_groups
return hosts