Skip to content

Commit b851b10

Browse files
fregataaclaude
andcommitted
fix(BA-3696): Fix type errors - add _domain_name field and inherit from RBAC result bases
- Add _domain_name field to CreateUserAction (following group pattern) - Update all result classes to inherit from UserScopeActionResult or UserSingleEntityActionResult - Implement required scope_type()/scope_id() or target_entity_id() methods on results - Update service.py to pass required scope/entity IDs to result constructors - Update API layer (REST, GraphQL) to pass _domain_name when creating CreateUserAction - Add _user_id field to DeleteUserActionResult and PurgeUserActionResult - Simplify search result classes to use specific field names (_domain_name, _project_id, _role_id) All user service files now pass pants fmt, fix, and lint checks. Type check errors in processors.py are pre-existing (111 errors on main branch). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent d824773 commit b851b10

11 files changed

Lines changed: 79 additions & 35 deletions

File tree

src/ai/backend/manager/api/gql_legacy/user.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,7 @@ def value_or_none(value: Any) -> Any | None:
922922
container_gids=value_or_none(self.container_gids),
923923
),
924924
),
925+
_domain_name=str(self.domain_name),
925926
group_ids=value_or_none(self.group_ids),
926927
)
927928

src/ai/backend/manager/api/rest/user/handler.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,11 @@ async def create_user(
102102
)
103103

104104
action_result = await self._user.create_user.wait_for_complete(
105-
CreateUserAction(creator=creator, group_ids=body.parsed.group_ids)
105+
CreateUserAction(
106+
creator=creator,
107+
_domain_name=body.parsed.domain_name,
108+
group_ids=body.parsed.group_ids,
109+
)
106110
)
107111

108112
resp = CreateUserResponse(user=self._adapter.convert_to_dto(action_result.data.user))

src/ai/backend/manager/services/user/actions/create_user.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@
88
from ai.backend.manager.data.user.types import BulkUserCreateResultData, UserCreateResultData
99
from ai.backend.manager.models.user import UserRow
1010
from ai.backend.manager.repositories.base.creator import Creator
11-
from ai.backend.manager.services.user.actions.base import UserAction, UserScopeAction
11+
from ai.backend.manager.services.user.actions.base import (
12+
UserAction,
13+
UserScopeAction,
14+
UserScopeActionResult,
15+
)
1216

1317

1418
@dataclass
1519
class CreateUserAction(UserScopeAction):
1620
creator: Creator[UserRow]
21+
_domain_name: str
1722
group_ids: list[str] | None = None
1823

1924
@override
@@ -23,29 +28,34 @@ def operation_type(cls) -> ActionOperationType:
2328

2429
@override
2530
def scope_type(self) -> ScopeType:
26-
# User creation happens within the domain scope
27-
# Domain is extracted from creator.values['domain_name']
2831
return ScopeType.DOMAIN
2932

3033
@override
3134
def scope_id(self) -> str:
32-
return self.creator.values.get("domain_name", "")
35+
return self._domain_name
3336

3437
@override
3538
def target_element(self) -> RBACElementRef:
36-
return RBACElementRef(RBACElementType.DOMAIN, self.scope_id())
39+
return RBACElementRef(RBACElementType.DOMAIN, self._domain_name)
3740

3841

3942
@dataclass
40-
class CreateUserActionResult(BaseActionResult):
43+
class CreateUserActionResult(UserScopeActionResult):
4144
data: UserCreateResultData
42-
_scope_type: ScopeType
43-
_scope_id: str
45+
_domain_name: str
4446

4547
@override
4648
def entity_id(self) -> str | None:
4749
return str(self.data.user.id)
4850

51+
@override
52+
def scope_type(self) -> ScopeType:
53+
return ScopeType.DOMAIN
54+
55+
@override
56+
def scope_id(self) -> str:
57+
return self._domain_name
58+
4959

5060
@dataclass
5161
class UserCreateSpec:

src/ai/backend/manager/services/user/actions/delete_user.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
from typing import override
33

44
from ai.backend.common.data.permission.types import RBACElementType
5-
from ai.backend.manager.actions.action import BaseActionResult
65
from ai.backend.manager.actions.types import ActionOperationType
76
from ai.backend.manager.data.permission.types import RBACElementRef
8-
from ai.backend.manager.services.user.actions.base import UserSingleEntityAction
7+
from ai.backend.manager.services.user.actions.base import (
8+
UserSingleEntityAction,
9+
UserSingleEntityActionResult,
10+
)
911

1012

1113
@dataclass
@@ -29,7 +31,13 @@ def target_element(self) -> RBACElementRef:
2931

3032

3133
@dataclass
32-
class DeleteUserActionResult(BaseActionResult):
34+
class DeleteUserActionResult(UserSingleEntityActionResult):
35+
_user_id: str
36+
3337
@override
3438
def entity_id(self) -> str | None:
35-
return None
39+
return self._user_id
40+
41+
@override
42+
def target_entity_id(self) -> str:
43+
return self._user_id

src/ai/backend/manager/services/user/actions/get_user.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
from uuid import UUID
44

55
from ai.backend.common.data.permission.types import RBACElementType
6-
from ai.backend.manager.actions.action import BaseActionResult
76
from ai.backend.manager.actions.types import ActionOperationType
87
from ai.backend.manager.data.permission.types import RBACElementRef
98
from ai.backend.manager.data.user.types import UserData
10-
from ai.backend.manager.services.user.actions.base import UserSingleEntityAction
9+
from ai.backend.manager.services.user.actions.base import (
10+
UserSingleEntityAction,
11+
UserSingleEntityActionResult,
12+
)
1113

1214

1315
@dataclass
@@ -31,7 +33,7 @@ def target_element(self) -> RBACElementRef:
3133

3234

3335
@dataclass
34-
class GetUserActionResult(BaseActionResult):
36+
class GetUserActionResult(UserSingleEntityActionResult):
3537
"""Result of GetUserAction containing user data."""
3638

3739
user: UserData
@@ -40,5 +42,6 @@ class GetUserActionResult(BaseActionResult):
4042
def entity_id(self) -> str | None:
4143
return str(self.user.uuid)
4244

45+
@override
4346
def target_entity_id(self) -> str:
4447
return str(self.user.uuid)

src/ai/backend/manager/services/user/actions/modify_user.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@
1111
from ai.backend.manager.data.user.types import BulkUserUpdateResultData, UserData
1212
from ai.backend.manager.models.user import UserRow
1313
from ai.backend.manager.repositories.base.updater import Updater
14-
from ai.backend.manager.services.user.actions.base import UserAction, UserSingleEntityAction
14+
from ai.backend.manager.services.user.actions.base import (
15+
UserAction,
16+
UserSingleEntityAction,
17+
UserSingleEntityActionResult,
18+
)
1519

1620
if TYPE_CHECKING:
1721
from ai.backend.manager.repositories.user.updaters import UserUpdaterSpec
@@ -42,13 +46,14 @@ def target_element(self) -> RBACElementRef:
4246

4347

4448
@dataclass
45-
class ModifyUserActionResult(BaseActionResult):
49+
class ModifyUserActionResult(UserSingleEntityActionResult):
4650
data: UserData
4751

4852
@override
4953
def entity_id(self) -> str | None:
5054
return str(self.data.id)
5155

56+
@override
5257
def target_entity_id(self) -> str:
5358
return str(self.data.id)
5459

src/ai/backend/manager/services/user/actions/purge_user.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
from ai.backend.manager.actions.types import ActionOperationType
88
from ai.backend.manager.data.permission.types import RBACElementRef
99
from ai.backend.manager.data.user.types import BulkUserPurgeResultData, UserInfoContext
10-
from ai.backend.manager.services.user.actions.base import UserAction, UserSingleEntityAction
10+
from ai.backend.manager.services.user.actions.base import (
11+
UserAction,
12+
UserSingleEntityAction,
13+
UserSingleEntityActionResult,
14+
)
1115
from ai.backend.manager.types import OptionalState
1216

1317

@@ -35,9 +39,16 @@ def target_element(self) -> RBACElementRef:
3539

3640

3741
@dataclass
38-
class PurgeUserActionResult(BaseActionResult):
42+
class PurgeUserActionResult(UserSingleEntityActionResult):
43+
_user_id: str
44+
45+
@override
3946
def entity_id(self) -> str | None:
40-
return None
47+
return self._user_id
48+
49+
@override
50+
def target_entity_id(self) -> str:
51+
return self._user_id
4152

4253

4354
@dataclass

src/ai/backend/manager/services/user/actions/search_users_by_domain.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,12 @@ class SearchUsersByDomainActionResult(UserScopeActionResult):
4545
total_count: int
4646
has_next_page: bool
4747
has_previous_page: bool
48-
_scope_type: ScopeType
49-
_scope_id: str
48+
_domain_name: str
5049

5150
@override
5251
def scope_type(self) -> ScopeType:
53-
return self._scope_type
52+
return ScopeType.DOMAIN
5453

5554
@override
5655
def scope_id(self) -> str:
57-
return self._scope_id
56+
return self._domain_name

src/ai/backend/manager/services/user/actions/search_users_by_project.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,12 @@ class SearchUsersByProjectActionResult(UserScopeActionResult):
4545
total_count: int
4646
has_next_page: bool
4747
has_previous_page: bool
48-
_scope_type: ScopeType
49-
_scope_id: str
48+
_project_id: str
5049

5150
@override
5251
def scope_type(self) -> ScopeType:
53-
return self._scope_type
52+
return ScopeType.PROJECT
5453

5554
@override
5655
def scope_id(self) -> str:
57-
return self._scope_id
56+
return self._project_id

src/ai/backend/manager/services/user/actions/search_users_by_role.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,12 @@ class SearchUsersByRoleActionResult(UserScopeActionResult):
4545
total_count: int
4646
has_next_page: bool
4747
has_previous_page: bool
48-
_scope_type: ScopeType
49-
_scope_id: str
48+
_role_id: str
5049

5150
@override
5251
def scope_type(self) -> ScopeType:
53-
return self._scope_type
52+
return ScopeType.ROLE
5453

5554
@override
5655
def scope_id(self) -> str:
57-
return self._scope_id
56+
return self._role_id

0 commit comments

Comments
 (0)