feat(rbac): add roles and permissions

This commit is contained in:
Schubert Ferenc 2026-07-02 23:05:59 +02:00
parent 86a32a942c
commit 694b7bd09a
37 changed files with 2682 additions and 218 deletions

View file

@ -0,0 +1,74 @@
from datetime import datetime
from pydantic import BaseModel, ConfigDict, Field, field_validator
RoleName = str
class PermissionResponse(BaseModel):
id: int
name: str
display_name: str
description: str
module: str
created_at: datetime
updated_at: datetime
model_config = ConfigDict(from_attributes=True)
class RoleBase(BaseModel):
name: str = Field(min_length=3, max_length=80)
display_name: str = Field(min_length=2, max_length=120)
description: str = Field(default="", max_length=500)
@field_validator("name")
@classmethod
def validate_name(cls, value: str) -> str:
normalized = value.strip().lower()
allowed = normalized.replace("_", "").replace("-", "").replace(".", "")
if not allowed.isalnum():
raise ValueError(
"Rollenname darf nur Buchstaben, Zahlen, Punkt, Unterstrich und Bindestrich enthalten"
)
return normalized
@field_validator("display_name", "description", mode="before")
@classmethod
def normalize_text(cls, value: object) -> str:
if value is None:
return ""
return str(value).strip()
class RoleCreate(RoleBase):
permission_ids: list[int] = Field(default_factory=list)
class RoleUpdate(RoleBase):
permission_ids: list[int] = Field(default_factory=list)
class RolePermissionUpdate(BaseModel):
permission_ids: list[int] = Field(default_factory=list)
class RoleResponse(BaseModel):
id: int
name: str
display_name: str
description: str
is_system: bool
permissions: list[PermissionResponse]
created_at: datetime
updated_at: datetime
model_config = ConfigDict(from_attributes=True)
class CurrentUserResponse(BaseModel):
id: int
username: str
email: str
role: str
permissions: list[str]

View file

@ -1,9 +1,9 @@
from datetime import datetime
from typing import Literal
from pydantic import BaseModel, ConfigDict, EmailStr, Field, field_validator
UserRole = Literal["admin", "manager", "user"]
from app.schemas.rbac import RoleResponse
UserRole = str
class UserBase(BaseModel):
@ -11,7 +11,8 @@ class UserBase(BaseModel):
last_name: str = Field(default="", max_length=100)
username: str = Field(min_length=3, max_length=50)
email: EmailStr
role: UserRole = "user"
role: UserRole = "support"
role_id: int | None = None
is_active: bool = True
@field_validator("first_name", "last_name", "username", mode="before")
@ -65,6 +66,8 @@ class UserResponse(BaseModel):
username: str
email: EmailStr
role: UserRole
role_id: int
primary_role: RoleResponse
is_active: bool
created_at: datetime
updated_at: datetime