-
Notifications
You must be signed in to change notification settings - Fork 175
Expand file tree
/
Copy pathcreators.py
More file actions
139 lines (114 loc) · 4.22 KB
/
creators.py
File metadata and controls
139 lines (114 loc) · 4.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
"""CreatorSpec implementations for permission-related entities."""
from __future__ import annotations
import uuid
from collections.abc import Sequence
from dataclasses import dataclass
from typing import override
from ai.backend.common.data.permission.types import RBACElementType
from ai.backend.manager.data.permission.id import ObjectId, ScopeId
from ai.backend.manager.data.permission.status import PermissionStatus, RoleStatus
from ai.backend.manager.data.permission.types import (
OperationType,
RoleSource,
)
from ai.backend.manager.errors.permission import RoleAlreadyAssigned
from ai.backend.manager.errors.repository import UniqueConstraintViolationError
from ai.backend.manager.models.rbac_models.association_scopes_entities import (
AssociationScopesEntitiesRow,
)
from ai.backend.manager.models.rbac_models.permission.object_permission import ObjectPermissionRow
from ai.backend.manager.models.rbac_models.permission.permission import PermissionRow
from ai.backend.manager.models.rbac_models.role import RoleRow
from ai.backend.manager.models.rbac_models.user_role import UserRoleRow
from ai.backend.manager.repositories.base.creator import CreatorSpec
from ai.backend.manager.repositories.base.types import IntegrityErrorCheck
@dataclass
class RoleCreatorSpec(CreatorSpec[RoleRow]):
"""CreatorSpec for role creation.
Only defines the role itself. Object permissions
are passed separately to create_role() for better separation of concerns.
"""
name: str
source: RoleSource
status: RoleStatus
description: str | None = None
@override
def build_row(self) -> RoleRow:
return RoleRow(
name=self.name,
source=self.source,
status=self.status,
description=self.description,
)
@dataclass
class PermissionCreatorSpec(CreatorSpec[PermissionRow]):
"""CreatorSpec for permissions."""
role_id: uuid.UUID
scope_type: RBACElementType
scope_id: str
entity_type: RBACElementType
operation: OperationType
@override
def build_row(self) -> PermissionRow:
return PermissionRow(
role_id=self.role_id,
scope_type=self.scope_type.to_scope_type(),
scope_id=self.scope_id,
entity_type=self.entity_type.to_entity_type(),
operation=self.operation,
)
@dataclass
class ObjectPermissionCreatorSpec(CreatorSpec[ObjectPermissionRow]):
"""CreatorSpec for object permissions."""
role_id: uuid.UUID
entity_type: RBACElementType
entity_id: str
operation: OperationType
status: PermissionStatus = PermissionStatus.ACTIVE
@override
def build_row(self) -> ObjectPermissionRow:
return ObjectPermissionRow(
role_id=self.role_id,
entity_type=self.entity_type.to_entity_type(),
entity_id=self.entity_id,
operation=self.operation,
)
@dataclass
class UserRoleCreatorSpec(CreatorSpec[UserRoleRow]):
"""CreatorSpec for user role mappings."""
user_id: uuid.UUID
role_id: uuid.UUID
granted_by: uuid.UUID | None = None
@property
@override
def integrity_error_checks(self) -> Sequence[IntegrityErrorCheck]:
return (
IntegrityErrorCheck(
violation_type=UniqueConstraintViolationError,
error=RoleAlreadyAssigned(
f"Role {self.role_id} is already assigned to user {self.user_id}."
),
),
)
@override
def build_row(self) -> UserRoleRow:
row = UserRoleRow(
user_id=self.user_id,
role_id=self.role_id,
)
if self.granted_by is not None:
row.granted_by = self.granted_by
return row
@dataclass
class AssociationScopesEntitiesCreatorSpec(CreatorSpec[AssociationScopesEntitiesRow]):
"""CreatorSpec for association between scopes and entities."""
scope_id: ScopeId
object_id: ObjectId
@override
def build_row(self) -> AssociationScopesEntitiesRow:
return AssociationScopesEntitiesRow(
scope_type=self.scope_id.scope_type,
scope_id=self.scope_id.scope_id,
entity_type=self.object_id.entity_type,
entity_id=self.object_id.entity_id,
)