diff --git a/changes/9992.enhance.md b/changes/9992.enhance.md new file mode 100644 index 00000000000..bf068744ca7 --- /dev/null +++ b/changes/9992.enhance.md @@ -0,0 +1 @@ +Refactor artifact registry action classes to RBAC-aware base classes (`ArtifactRegistrySingleEntityAction`) to enable RBAC validator wiring diff --git a/src/ai/backend/manager/services/artifact_registry/actions/base.py b/src/ai/backend/manager/services/artifact_registry/actions/base.py index 6135a54f77d..fbe9b450946 100644 --- a/src/ai/backend/manager/services/artifact_registry/actions/base.py +++ b/src/ai/backend/manager/services/artifact_registry/actions/base.py @@ -1,4 +1,3 @@ -from dataclasses import dataclass from typing import override from ai.backend.common.data.permission.types import EntityType @@ -11,7 +10,6 @@ from ai.backend.manager.actions.action.types import FieldData -@dataclass class ArtifactRegistryAction(BaseAction): @override @classmethod @@ -19,7 +17,6 @@ def entity_type(cls) -> EntityType: return EntityType.ARTIFACT_REGISTRY -@dataclass class ArtifactBatchRegistryAction(BaseBatchAction): @override @classmethod diff --git a/src/ai/backend/manager/services/artifact_registry/actions/common/get_meta.py b/src/ai/backend/manager/services/artifact_registry/actions/common/get_meta.py index 196ee0dc5e4..9585d13e570 100644 --- a/src/ai/backend/manager/services/artifact_registry/actions/common/get_meta.py +++ b/src/ai/backend/manager/services/artifact_registry/actions/common/get_meta.py @@ -2,31 +2,44 @@ from dataclasses import dataclass from typing import override -from ai.backend.manager.actions.action import BaseActionResult +from ai.backend.common.data.permission.types import RBACElementType from ai.backend.manager.actions.types import ActionOperationType from ai.backend.manager.data.artifact_registries.types import ArtifactRegistryData -from ai.backend.manager.services.artifact_registry.actions.base import ArtifactRegistryAction +from ai.backend.manager.data.permission.types import RBACElementRef +from ai.backend.manager.errors.api import InvalidAPIParameters +from ai.backend.manager.services.artifact_registry.actions.base import ( + ArtifactRegistrySingleEntityAction, + ArtifactRegistrySingleEntityActionResult, +) @dataclass -class GetArtifactRegistryMetaAction(ArtifactRegistryAction): +class GetArtifactRegistryMetaAction(ArtifactRegistrySingleEntityAction): registry_id: uuid.UUID | None = None registry_name: str | None = None - @override - def entity_id(self) -> str | None: - return str(self.registry_id) - @override @classmethod def operation_type(cls) -> ActionOperationType: return ActionOperationType.GET + @override + def target_entity_id(self) -> str: + if self.registry_id: + return str(self.registry_id) + if self.registry_name: + return self.registry_name + raise InvalidAPIParameters("Either registry_id or registry_name must be provided.") + + @override + def target_element(self) -> RBACElementRef: + return RBACElementRef(RBACElementType.ARTIFACT_REGISTRY, self.target_entity_id()) + @dataclass -class GetArtifactRegistryMetaActionResult(BaseActionResult): +class GetArtifactRegistryMetaActionResult(ArtifactRegistrySingleEntityActionResult): result: ArtifactRegistryData @override - def entity_id(self) -> str | None: + def target_entity_id(self) -> str: return str(self.result.id) diff --git a/src/ai/backend/manager/services/artifact_registry/processors.py b/src/ai/backend/manager/services/artifact_registry/processors.py index 47a4463dec9..9c1bb1f3ff3 100644 --- a/src/ai/backend/manager/services/artifact_registry/processors.py +++ b/src/ai/backend/manager/services/artifact_registry/processors.py @@ -121,7 +121,7 @@ class ArtifactRegistryProcessors(AbstractProcessorPackage): search_reservoir_registries: ActionProcessor[ SearchReservoirRegistriesAction, SearchReservoirRegistriesActionResult ] - get_registry_meta: ActionProcessor[ + get_registry_meta: SingleEntityActionProcessor[ GetArtifactRegistryMetaAction, GetArtifactRegistryMetaActionResult ] get_registry_metas: ActionProcessor[ @@ -192,6 +192,12 @@ def __init__( validators=[validators.rbac.single_entity], ) + self.get_registry_meta = SingleEntityActionProcessor( + service.get_registry_meta, + action_monitors, + validators=[validators.rbac.single_entity], + ) + # Internal/batch actions without RBAC self.get_huggingface_registries = ActionProcessor( service.get_huggingface_registries, action_monitors @@ -199,7 +205,6 @@ def __init__( self.get_reservoir_registries = ActionProcessor( service.get_reservoir_registries, action_monitors ) - self.get_registry_meta = ActionProcessor(service.get_registry_meta, action_monitors) self.get_registry_metas = ActionProcessor(service.get_registry_metas, action_monitors) @override