Skip to content

Commit 2818e25

Browse files
committed
refactor: Seperate DTOs based on whether relationship data load is needed
1 parent 147ce90 commit 2818e25

5 files changed

Lines changed: 53 additions & 3 deletions

File tree

src/ai/backend/manager/data/permission/permission_group.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,11 @@ class PermissionGroupData:
2828
role_id: uuid.UUID
2929
scope_id: ScopeId
3030

31+
32+
@dataclass
33+
class PermissionGroupExtendedData:
34+
id: uuid.UUID
35+
role_id: uuid.UUID
36+
scope_id: ScopeId
37+
3138
permissions: list[PermissionData]

src/ai/backend/manager/data/permission/role.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
ObjectPermissionCreateInputBeforeRoleCreation,
1313
ObjectPermissionData,
1414
)
15-
from .permission_group import PermissionGroupCreatorBeforeRoleCreation, PermissionGroupData
15+
from .permission_group import (
16+
PermissionGroupCreatorBeforeRoleCreation,
17+
PermissionGroupExtendedData,
18+
)
1619
from .status import RoleStatus
1720
from .types import EntityType, OperationType, RoleSource
1821

@@ -73,7 +76,7 @@ class RoleDataWithPermissions:
7376
source: RoleSource
7477
status: RoleStatus
7578

76-
permission_groups: list[PermissionGroupData]
79+
permission_groups: list[PermissionGroupExtendedData]
7780
object_permissions: list[ObjectPermissionData]
7881

7982
created_at: datetime
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
**최종 목표**
2+
- UserNode의 `get_connection` 리졸버에 project name을 바탕으로 user를 필터링하는 로직을 추가하고 싶습니다
3+
4+
**배경**
5+
- 현재 구조의 경우 `get_connection`리졸버에 인자로 들어온 str 형태의 filter_expr를 _queryfilter_fieldspec에 있는 필터 스펙을 바탕으로 Lark로 AST를 만들고, 이를 통해 SQL문을 `generate_sql_info_for_gql_connection`을 만드는 구조로 되어있습니다
6+
- 하지만 _queryfilter_fieldspec으로 만든 AST로 SQL을 만드는 현재 플로우의 경우 UserNode가 사용하는 users 테이블에 있는 컬럼(`src/ai/backend/manager/models/user.py`에 UserRow 참고)에 있는 것들에 대해서만 필터링을 한다는 것을 가정하고 만들어졌습니다.
7+
- Project의 name의 경우 GroupRow에 있고, User와 Group은 AssocGroupUserRow라는 중간 테이블을 매개로 N:N 관계를 맺고 있습니다
8+
9+
**구현**
10+
- _queryfilter_fieldspec은 UserRow에 있는 테이블 정보를 반영한다고 생각하고, 별도의 테이블에서 가져오는 스펙을 만들고 이를 바탕으로 필터링하는 로직을 만들어주세요
11+
- join 쿼리는 아래를 참고하면 테이블 구조를 대강 알 수 있을 겁니다
12+
```python
13+
j = sa.join(
14+
UserRow,
15+
AssocGroupUserRow,
16+
UserRow.uuid == AssocGroupUserRow.user_id,
17+
).join(GroupRow, AssocGroupUserRow.group_id == GroupRow.id)
18+
19+
query = query.select_from(j).where(project_name_filter_clause).distinct()
20+
21+
cnt_query = sa.select(sa.func.count(sa.distinct(UserRow.uuid))).select_from(j)
22+
cnt_query = cnt_query.where(project_name_filter_clause)
23+
for cond in conditions:
24+
cnt_query = cnt_query.where(cond)
25+
```
26+
- 쿼리를 최대한 효율적으로 작성해주세요. AND나 OR이 걸렸을 때 또 JOIN하지 않도록 해주세요. 아니면 아예 일관성있게 비효율적으로 처음부터 join을 박거나 하는 방법도 좋습니다 (if 분기타면서 join하거나 그런 유지보수가 힘든 쿼리를 만들지 말라는 뜻)
27+
28+
29+
**유의사항**
30+
- 구현이 더럽더라도(Table에 대한 정보를 GQL이라는 API 레이어에서 알고 있는 것) 상관없습니다. 어짜피 Graphene으로 작성된 것은 Strawberry로 넘어가면서 새로 작성할 것이기 때문입니다
31+
- 다만 UserNode의 경우에도 이후 `src/ai/backend/manager/api/gql/artifact.py`의 resolve_artifacts 함수처럼 filter나 OrderBy 객체를 만들고, 이를 서비스 레이어에 넘기는 방식으로 리팩토링 할 것입니다.
32+
- 현재 UserNode가 ArtifactFilter 처럼 Filter, Order 객체를 만들어서 넘기는 등의 대대적인 개편을 하지는 마세요. 다만 이후 그렇게 넘어가기 쉽도록 다른 테이블의 컬럼을 바탕으로 필터링하는 로직을 설계해주세요

src/ai/backend/manager/models/rbac_models/permission/permission_group.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from ai.backend.manager.data.permission.permission_group import (
1111
PermissionGroupCreator,
1212
PermissionGroupData,
13+
PermissionGroupExtendedData,
1314
)
1415
from ai.backend.manager.data.permission.types import (
1516
ScopeType,
@@ -73,5 +74,12 @@ def to_data(self) -> PermissionGroupData:
7374
id=self.id,
7475
role_id=self.role_id,
7576
scope_id=ScopeId(scope_type=self.scope_type, scope_id=self.scope_id),
77+
)
78+
79+
def to_extended_data(self) -> PermissionGroupExtendedData:
80+
return PermissionGroupExtendedData(
81+
id=self.id,
82+
role_id=self.role_id,
83+
scope_id=ScopeId(scope_type=self.scope_type, scope_id=self.scope_id),
7684
permissions=[permission.to_data() for permission in self.permission_rows],
7785
)

src/ai/backend/manager/models/rbac_models/role.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def to_data_with_permissions(self) -> RoleDataWithPermissions:
104104
updated_at=self.updated_at,
105105
deleted_at=self.deleted_at,
106106
description=self.description,
107-
permission_groups=[pg_row.to_data() for pg_row in self.permission_group_rows],
107+
permission_groups=[pg_row.to_extended_data() for pg_row in self.permission_group_rows],
108108
object_permissions=[op_row.to_data() for op_row in self.object_permission_rows],
109109
)
110110

0 commit comments

Comments
 (0)