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

@@ -31,13 +31,16 @@ class Postgres(DatabaseBase):
async def delete_workspace(self, workspace_id: uuid.UUID) -> None:
await domain.Workspace.filter(id=workspace_id).delete()
async def add_user_to_workspace(self, workspace_id: uuid.UUID, user_id: uuid.UUID) -> None:
await domain.WorkspaceUser.create(
async def add_user_to_workspace(self, workspace_id: uuid.UUID, user_id: uuid.UUID) -> domain.WorkspaceUser:
return await domain.WorkspaceUser.create(
workspace_id=workspace_id,
user_id=user_id,
status=domain.WorkspaceUserStatus.ACTIVE,
)
async def update_workspace_user(self, workspace_user: domain.WorkspaceUser) -> None:
await workspace_user.save()
async def get_user_workspaces(self, user_id: uuid.UUID) -> list[domain.WorkspaceUser]:
return (
await domain.WorkspaceUser.filter(user_id=user_id)
@@ -69,10 +72,83 @@ class Postgres(DatabaseBase):
async def get_workspace_membership(
self, workspace_id: uuid.UUID, user_id: uuid.UUID
) -> domain.WorkspaceUser | None:
return await domain.WorkspaceUser.get_or_none(workspace_id=workspace_id, user_id=user_id).prefetch_related(
'workspace'
return (
await domain.WorkspaceUser.filter(workspace_id=workspace_id, user_id=user_id)
.prefetch_related('workspace', 'user', 'permissions', 'permission_scopes')
.first()
)
async def get_workspace_members(self, workspace_id: uuid.UUID) -> list[domain.WorkspaceUser]:
return (
await domain.WorkspaceUser.filter(workspace_id=workspace_id)
.prefetch_related('workspace', 'user', 'permissions', 'permission_scopes')
.order_by('created_at')
.all()
)
async def get_workspace_member(self, workspace_user_id: uuid.UUID) -> domain.WorkspaceUser | None:
return (
await domain.WorkspaceUser.filter(id=workspace_user_id)
.prefetch_related('workspace', 'user', 'permissions', 'permission_scopes')
.first()
)
async def create_workspace_invite(self, invite: domain.WorkspaceInvite) -> None:
await invite.save()
async def update_workspace_invite(self, invite: domain.WorkspaceInvite) -> None:
await invite.save()
async def get_workspace_invite(self, invite_id: uuid.UUID) -> domain.WorkspaceInvite | None:
return (
await domain.WorkspaceInvite.filter(id=invite_id)
.prefetch_related('workspace', 'user', 'invited_by')
.first()
)
async def get_workspace_invite_by_user(
self, workspace_id: uuid.UUID, user_id: uuid.UUID
) -> domain.WorkspaceInvite | None:
return await domain.WorkspaceInvite.get_or_none(workspace_id=workspace_id, user_id=user_id)
async def get_workspace_invites(self, workspace_id: uuid.UUID) -> list[domain.WorkspaceInvite]:
return (
await domain.WorkspaceInvite.filter(workspace_id=workspace_id)
.prefetch_related('user', 'invited_by')
.order_by('created_at')
.all()
)
async def set_workspace_user_permissions(
self,
workspace_user_id: uuid.UUID,
global_permissions: set[domain.PermissionKey],
scoped_permissions: list[tuple[domain.PermissionKey, domain.PermissionScopeType, uuid.UUID]],
) -> None:
await domain.WorkspaceUserPermission.filter(workspace_user_id=workspace_user_id).delete()
await domain.WorkspaceUserPermissionScope.filter(workspace_user_id=workspace_user_id).delete()
if global_permissions:
await domain.WorkspaceUserPermission.bulk_create(
[
domain.WorkspaceUserPermission(workspace_user_id=workspace_user_id, permission=permission)
for permission in global_permissions
]
)
if scoped_permissions:
await domain.WorkspaceUserPermissionScope.bulk_create(
[
domain.WorkspaceUserPermissionScope(
workspace_user_id=workspace_user_id,
permission=permission,
scope_type=scope_type,
scope_id=scope_id,
)
for permission, scope_type, scope_id in scoped_permissions
]
)
async def create_login_token(self, login_token: domain.LoginToken) -> None:
await login_token.save()
@@ -87,6 +163,9 @@ class Postgres(DatabaseBase):
raise ValueError('Either user_id or telegram_id must be provided')
async def get_user_by_username(self, username: str) -> domain.User | None:
return await domain.User.get_or_none(username__iexact=username)
async def get_login_token(self, token: str) -> domain.LoginToken | None:
return await domain.LoginToken.get_or_none(token=token)
@@ -163,13 +242,17 @@ class Postgres(DatabaseBase):
async def update_project(self, project: domain.Project) -> None:
await project.save()
async def get_workspace_projects(self, workspace_id: uuid.UUID) -> list[domain.Project]:
return (
await domain.Project.filter(workspace_id=workspace_id)
.prefetch_related('channel')
.order_by('created_at')
.all()
)
async def get_workspace_projects(
self, workspace_id: uuid.UUID, allowed_project_ids: set[uuid.UUID] | None = None
) -> list[domain.Project]:
query = domain.Project.filter(workspace_id=workspace_id).prefetch_related('channel')
if allowed_project_ids is not None:
if not allowed_project_ids:
return []
query = query.filter(id__in=list(allowed_project_ids))
return await query.order_by('created_at').all()
async def get_active_purchase_plan(self, project_id: uuid.UUID) -> domain.PurchasePlan | None:
return await domain.PurchasePlan.get_or_none(project_id=project_id, status=domain.PurchasePlanStatus.ACTIVE)
@@ -237,12 +320,20 @@ class Postgres(DatabaseBase):
await creative.save()
async def get_workspace_creatives(
self, workspace_id: uuid.UUID, project_id: uuid.UUID | None = None, include_archived: bool = False
self,
workspace_id: uuid.UUID,
project_id: uuid.UUID | None = None,
include_archived: bool = False,
allowed_project_ids: set[uuid.UUID] | None = None,
) -> list[domain.Creative]:
query = domain.Creative.filter(workspace_id=workspace_id)
if project_id:
query = query.filter(project_id=project_id)
elif allowed_project_ids is not None:
if not allowed_project_ids:
return []
query = query.filter(project_id__in=list(allowed_project_ids))
if not include_archived:
query = query.filter(status=domain.CreativeStatus.ACTIVE)
@@ -270,11 +361,16 @@ class Postgres(DatabaseBase):
placement_channel_id: uuid.UUID | None = None,
creative_id: uuid.UUID | None = None,
include_archived: bool = False,
allowed_project_ids: set[uuid.UUID] | None = None,
) -> list[domain.Placement]:
query = domain.Placement.filter(workspace_id=workspace_id)
if project_id:
query = query.filter(project_id=project_id)
elif allowed_project_ids is not None:
if not allowed_project_ids:
return []
query = query.filter(project_id__in=list(allowed_project_ids))
if placement_channel_id:
query = query.filter(placement_channel_id=placement_channel_id)
if creative_id: