feat: права и инвайты

This commit is contained in:
Artem Tsyrulnikov
2025-12-14 13:49:25 +03:00
parent f3e09a08eb
commit 4c3873c727
43 changed files with 1111 additions and 127 deletions

View File

@@ -54,6 +54,17 @@ __all__ = (
'CreateWorkspaceInput',
'CreateWorkspaceOutput',
'UpdateWorkspaceInput',
'WorkspaceMemberOutput',
'WorkspaceMemberUserOutput',
'WorkspacePermissionOutput',
'WorkspacePermissionScopeOutput',
'GetWorkspaceMembersOutput',
'WorkspacePermissionInput',
'WorkspacePermissionScopeInput',
'UpdateWorkspaceMemberPermissionsInput',
'CreateWorkspaceInviteInput',
'WorkspaceInviteOutput',
'GetWorkspaceInvitesOutput',
)
from .analytics import (
@@ -117,8 +128,19 @@ from .views import (
)
from .workspace import (
CreateWorkspaceInput,
CreateWorkspaceInviteInput,
CreateWorkspaceOutput,
GetWorkspaceInvitesOutput,
GetWorkspaceMembersOutput,
GetWorkspacesOutput,
UpdateWorkspaceInput,
UpdateWorkspaceMemberPermissionsInput,
WorkspaceInviteOutput,
WorkspaceMemberOutput,
WorkspaceMembershipOutput,
WorkspaceMemberUserOutput,
WorkspacePermissionInput,
WorkspacePermissionOutput,
WorkspacePermissionScopeInput,
WorkspacePermissionScopeOutput,
)

View File

@@ -2,6 +2,8 @@ import uuid
import pydantic
from src import domain
class WorkspaceMembershipOutput(pydantic.BaseModel):
id: uuid.UUID
@@ -21,3 +23,102 @@ class CreateWorkspaceInput(pydantic.BaseModel):
class UpdateWorkspaceInput(pydantic.BaseModel):
name: str | None = None
class WorkspaceMemberUserOutput(pydantic.BaseModel):
id: uuid.UUID
telegram_id: int
username: str | None
class WorkspacePermissionScopeOutput(pydantic.BaseModel):
type: domain.PermissionScopeType
id: uuid.UUID
class WorkspacePermissionOutput(pydantic.BaseModel):
key: domain.PermissionKey
scopes: list[WorkspacePermissionScopeOutput]
class WorkspaceMemberOutput(pydantic.BaseModel):
id: uuid.UUID
status: domain.WorkspaceUserStatus
user: WorkspaceMemberUserOutput
permissions: list[WorkspacePermissionOutput]
class GetWorkspaceMembersOutput(pydantic.BaseModel):
members: list[WorkspaceMemberOutput]
class WorkspacePermissionScopeInput(pydantic.BaseModel):
type: domain.PermissionScopeType = pydantic.Field(
description='Тип области действия. Сейчас используется только "project".'
)
id: uuid.UUID = pydantic.Field(description='Идентификатор сущности в указанной области (например, project_id).')
class WorkspacePermissionInput(pydantic.BaseModel):
key: domain.PermissionKey = pydantic.Field(
description=(
'Ключ права. Доступные значения: "projects_read", "projects_write", '
'"placements_read", "placements_write", "analytics_read", "admin_full".'
)
)
scopes: list[WorkspacePermissionScopeInput] = pydantic.Field(
default_factory=list,
description='Ограничения по областям. Пустой список означает глобальное право.',
)
class UpdateWorkspaceMemberPermissionsInput(pydantic.BaseModel):
permissions: list[WorkspacePermissionInput] = pydantic.Field(
default_factory=list,
description='Список прав, который полностью заменит текущий набор участника.',
)
model_config = pydantic.ConfigDict(
json_schema_extra={
'examples': [
{
'permissions': [
{'key': 'admin_full'},
{
'key': 'projects_write',
'scopes': [
{'type': 'project', 'id': '11111111-1111-1111-1111-111111111111'},
{'type': 'project', 'id': '22222222-2222-2222-2222-222222222222'},
],
},
]
}
]
}
)
class CreateWorkspaceInviteInput(pydantic.BaseModel):
username: str = pydantic.Field(min_length=1)
@pydantic.field_validator('username')
@classmethod
def normalize_username(cls, value: str) -> str:
username = value.strip()
if username.startswith('@'):
username = username[1:]
username = username.strip()
if not username:
raise ValueError('Username must not be empty')
return username
class WorkspaceInviteOutput(pydantic.BaseModel):
id: uuid.UUID
status: domain.WorkspaceInviteStatus
user: WorkspaceMemberUserOutput
invited_by: WorkspaceMemberUserOutput
class GetWorkspaceInvitesOutput(pydantic.BaseModel):
invites: list[WorkspaceInviteOutput]