umbau 1.0
This commit is contained in:
@ -16,8 +16,7 @@ USERNAME_RE = re.compile(r"^[a-zA-Z0-9._-]{3,64}$")
|
||||
HOSTNAME_LABEL_RE = re.compile(r"^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$")
|
||||
|
||||
ROLE_NAME = Literal[
|
||||
"ssh_connect", "rdp_connect", "file_transfer", "clipboard",
|
||||
"session_recording_view", "admin_hostgroup",
|
||||
"ssh_connect", "rdp_connect", "file_transfer",
|
||||
# Hinzugefuegt fuer RBAC-Erweiterung 'Credentials ins RBAC-Modell' (Migration
|
||||
# 0008_credentials_roles.sql): erlaubt Nicht-Admins mit dieser Rolle auf
|
||||
# einer Hostgruppe gezielten Zugriff auf Zugangsdaten (SSH-Keys, RDP-
|
||||
@ -25,6 +24,13 @@ ROLE_NAME = Literal[
|
||||
# require_admin_scope_or_host_role und admin/routes.py (rdp-credentials,
|
||||
# ssh-keys-Zuordnung, GET /admin/hosts/{id}/credentials).
|
||||
"credentials_view", "credentials_manage",
|
||||
# 'clipboard', 'session_recording_view' und 'admin_hostgroup' wurden mit
|
||||
# Migration 0015_remove_dead_roles.sql entfernt (Teil D.6 Schritt 1,
|
||||
# Umsetzungsauftrag_Sonnet5.md) -- sie waren seit 0001_initial.sql
|
||||
# vergebbar, aber kein Codepfad hat sie je geprueft. Betreiberentscheidung
|
||||
# (2026-08-31): Clipboard bleibt host-global (hosts.clipboard_enabled),
|
||||
# Sitzungs-Playback bleibt global-admin-only, keine delegierte
|
||||
# Hostgruppen-Admin-Ebene.
|
||||
]
|
||||
|
||||
|
||||
@ -58,11 +64,6 @@ class UserCreateRequest(BaseModel):
|
||||
username: str = Field(min_length=3, max_length=64)
|
||||
initial_password: str = Field(min_length=12, max_length=256)
|
||||
is_admin: bool = False
|
||||
# Nur relevant, wenn der anlegende Principal Mandanten-Admin ist: wird
|
||||
# serverseitig ohnehin auf den/die erlaubten Mandanten erzwungen (siehe
|
||||
# create_user() in admin/routes.py) -- ein Mandanten-Admin kann hierueber
|
||||
# KEINEN User einem fremden Mandanten zuordnen. Fuer Super-Admins optional.
|
||||
home_tenant_id: int | None = None
|
||||
|
||||
@field_validator("username")
|
||||
@classmethod
|
||||
@ -78,27 +79,9 @@ class UserUpdateRequest(BaseModel):
|
||||
new_password: str | None = Field(default=None, min_length=12, max_length=256)
|
||||
|
||||
|
||||
class TenantCreateRequest(BaseModel):
|
||||
name: str = Field(min_length=1, max_length=128)
|
||||
description: str | None = Field(default=None, max_length=1024)
|
||||
|
||||
|
||||
class TenantUpdateRequest(BaseModel):
|
||||
name: str | None = Field(default=None, min_length=1, max_length=128)
|
||||
description: str | None = Field(default=None, max_length=1024)
|
||||
is_active: bool | None = None
|
||||
|
||||
|
||||
class TenantAdminAssignRequest(BaseModel):
|
||||
user_id: int
|
||||
|
||||
|
||||
class HostGroupCreateRequest(BaseModel):
|
||||
name: str = Field(min_length=1, max_length=128)
|
||||
description: str | None = Field(default=None, max_length=1024)
|
||||
# Nur fuer Super-Admins relevant (Mandanten-Admins werden serverseitig
|
||||
# ohnehin auf ihren eigenen Mandanten festgelegt, siehe admin/routes.py).
|
||||
tenant_id: int | None = None
|
||||
|
||||
|
||||
class HostGroupUpdateRequest(BaseModel):
|
||||
@ -179,7 +162,6 @@ class RoleRevokeRequest(BaseModel):
|
||||
class UserGroupCreateRequest(BaseModel):
|
||||
name: str = Field(min_length=1, max_length=128)
|
||||
description: str | None = Field(default=None, max_length=1024)
|
||||
tenant_id: int | None = None
|
||||
|
||||
|
||||
class UserGroupUpdateRequest(BaseModel):
|
||||
@ -204,14 +186,29 @@ class GroupRoleRevokeRequest(BaseModel):
|
||||
role_name: ROLE_NAME
|
||||
|
||||
|
||||
class GroupCredentialGrantRequest(BaseModel):
|
||||
"""Achse B (Teil D Schritt 3+5, Umsetzungsauftrag_Sonnet5.md): Freigabe
|
||||
EINES Zugangsdatensatzes (SSH-Key, RDP-Zugangsdaten oder SSH-Passwort --
|
||||
die Art steht im Endpunktpfad, nicht im Body, siehe app/admin/routes.py)
|
||||
an eine Benutzergruppe. Struktur bewusst identisch zu
|
||||
GroupRoleGrantRequest (Achse A), nur mit `credential_id` statt
|
||||
`host_group_id`/`role_names` -- unterschiedliche Achse, gleiches
|
||||
Vergabemuster (Gruppe + Ziel + optionales Ablaufdatum)."""
|
||||
user_group_id: int
|
||||
credential_id: int
|
||||
expires_at: str | None = None
|
||||
|
||||
|
||||
class GroupCredentialRevokeRequest(BaseModel):
|
||||
user_group_id: int
|
||||
credential_id: int
|
||||
|
||||
|
||||
class ApiTokenCreateRequest(BaseModel):
|
||||
label: str = Field(min_length=1, max_length=128)
|
||||
user_id: int
|
||||
scopes: list[str] = Field(min_length=1, max_length=32)
|
||||
expires_at: str | None = None
|
||||
# Nur fuer Super-Admins relevant -- ein Mandanten-Admin wird serverseitig
|
||||
# ohnehin auf seinen eigenen Mandanten festgelegt.
|
||||
tenant_id: int | None = None
|
||||
|
||||
|
||||
class SshKeyCreateRequest(BaseModel):
|
||||
@ -219,7 +216,6 @@ class SshKeyCreateRequest(BaseModel):
|
||||
private_key_pem: str = Field(min_length=1, max_length=32_768)
|
||||
public_key: str = Field(min_length=1, max_length=8192)
|
||||
key_type: Literal["ed25519", "rsa-3072", "rsa-4096", "ca-cert"]
|
||||
tenant_id: int | None = None
|
||||
# Anmeldename am Zielsystem. Gehoert zum Schluessel, nicht zum Host
|
||||
# (Migration 0010): ein Schluessel ist immer "der Zugang von Benutzer X".
|
||||
# Fuer mehrere Konten wird je ein Schluesseleintrag angelegt.
|
||||
@ -264,7 +260,6 @@ class RdpCredentialCreateRequest(BaseModel):
|
||||
username: str = Field(min_length=1, max_length=128)
|
||||
domain: str | None = Field(default=None, max_length=128)
|
||||
password: str = Field(min_length=1, max_length=512)
|
||||
tenant_id: int | None = None
|
||||
|
||||
|
||||
class RdpCredentialUpdateRequest(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user