Skip to content

Commit

Permalink
[Core] Validate access mode for API functions
Browse files Browse the repository at this point in the history
Closes OpenAssetIO#57. OpenAssetIO/OpenAssetIO#1016 refined the Context access
patterns to formalize the creation of "children" and other related
entities via publish to an existing reference. BAL does not yet support
this kind of creation, and so should error in the case.

So respond appropriately to Access mode in various API functions,
by calling the provided error callback, except in the case of
`managementPolicy` which responds with empty `TraitsData` objects
(signifying "unmanaged").

Note that for consistency, this changes the error message output when
attempting to `resolve` with `kWrite` access.

Signed-off-by: David Feltell <david.feltell@foundry.com>
  • Loading branch information
feltech committed Aug 23, 2023
1 parent df9b00b commit 5c0f358
Show file tree
Hide file tree
Showing 4 changed files with 269 additions and 18 deletions.
4 changes: 4 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ v1.0.0-alpha.x

- Added a runtime dependency on the `openassetio-mediacreation` package.

- Added validation to API methods to error on unsupported
`Context.Access` modes.
[#57](https://github.com/OpenAssetIO/OpenAssetIO-Manager-BAL/issues/57)

### New features

- The entity reference scheme consumed by BAL can be adjusted from the
Expand Down
103 changes: 90 additions & 13 deletions plugin/openassetio_manager_bal/BasicAssetLibraryInterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@
import time

from functools import wraps
from typing import List, Any, Iterable
from urllib.parse import urlparse, parse_qs

from openassetio import constants, BatchElementError, EntityReference, TraitsData
from openassetio import constants, BatchElementError, EntityReference, TraitsData, Context
from openassetio.exceptions import MalformedEntityReference, PluginError
from openassetio.managerApi import ManagerInterface, EntityReferencePagerInterface

Expand Down Expand Up @@ -145,7 +146,14 @@ def initialize(self, managerSettings, hostSession):
)

def managementPolicy(self, traitSets, context, hostSession):
access = "read" if context.isForRead() else "write"
if context.isForRead():
access = "read"
elif context.access == Context.Access.kWrite:
access = "write"
else:
# kCreateRelated unsupported.
return [TraitsData() for _ in traitSets]

return [
self.__dict_to_traits_data(bal.management_policy(trait_set, access, self.__library))
for trait_set in traitSets
Expand All @@ -155,28 +163,27 @@ def isEntityReferenceString(self, someString, hostSession):
return someString.startswith(self.__entity_refrence_prefix())

@simulated_delay
def entityExists(self, entityRefs, _context, _hostSession, successCallback, errorCallback):
results = []
def entityExists(self, entityRefs, context, _hostSession, successCallback, errorCallback):
for idx, ref in enumerate(entityRefs):
try:
entity_info = self.__parse_entity_ref(ref.toString())
result = bal.exists(entity_info, self.__library)
successCallback(idx, result)
except Exception as exc: # pylint: disable=broad-except
self.__handle_exception(exc, idx, errorCallback)
return results

@simulated_delay
def resolve(
self, entityReferences, traitSet, context, hostSession, successCallback, errorCallback
):
# pylint: disable=too-many-locals
if context.isForWrite():
result = BatchElementError(
BatchElementError.ErrorCode.kEntityAccessError, "BAL entities are read-only"
)
for idx in range(len(entityReferences)):
errorCallback(idx, result)
if not self.__validate_access(
"resolve",
(Context.Access.kRead,),
context,
entityReferences,
errorCallback,
):
return

for idx, ref in enumerate(entityReferences):
Expand All @@ -202,6 +209,15 @@ def resolve(
def preflight(
self, targetEntityRefs, traitsDatas, context, hostSession, successCallback, errorCallback
):
if not self.__validate_access(
"preflight",
(Context.Access.kWrite,),
context,
targetEntityRefs,
errorCallback,
):
return

for idx, ref in enumerate(targetEntityRefs):
try:
# Remove version info from the reference, as publishing will
Expand All @@ -223,6 +239,15 @@ def register(
successCallback,
errorCallback,
):
if not self.__validate_access(
"register",
(Context.Access.kWrite,),
context,
targetEntityRefs,
errorCallback,
):
return

for idx, ref in enumerate(targetEntityRefs):
try:
entity_info = self.__parse_entity_ref(ref.toString())
Expand All @@ -245,6 +270,14 @@ def getWithRelationship(
successCallback,
errorCallback,
):
if not self.__validate_access(
"relationship query",
(Context.Access.kRead,),
context,
entityReferences,
errorCallback,
):
return
for idx, entity_ref in enumerate(entityReferences):
try:
entity_info = self.__parse_entity_ref(entity_ref.toString())
Expand All @@ -266,6 +299,14 @@ def getWithRelationships(
successCallback,
errorCallback,
):
if not self.__validate_access(
"relationship query",
(Context.Access.kRead,),
context,
relationshipTraitsDatas,
errorCallback,
):
return
for idx, relationship in enumerate(relationshipTraitsDatas):
try:
entity_info = self.__parse_entity_ref(entityReference.toString())
Expand All @@ -281,11 +322,19 @@ def getWithRelationshipPaged(
relationshipTraitsData,
resultTraitSet,
pageSize,
_context,
context,
_hostSession,
successCallback,
errorCallback,
):
if not self.__validate_access(
"relationship query",
(Context.Access.kRead,),
context,
entityReferences,
errorCallback,
):
return
for idx, entity_ref in enumerate(entityReferences):
try:
entity_info = self.__parse_entity_ref(entity_ref.toString())
Expand Down Expand Up @@ -313,11 +362,19 @@ def getWithRelationshipsPaged(
relationshipTraitsDatas,
resultTraitSet,
pageSize,
_context,
context,
_hostSession,
successCallback,
errorCallback,
):
if not self.__validate_access(
"relationship query",
(Context.Access.kRead,),
context,
relationshipTraitsDatas,
errorCallback,
):
return
for idx, relationship in enumerate(relationshipTraitsDatas):
try:
entity_info = self.__parse_entity_ref(entityReference.toString())
Expand Down Expand Up @@ -449,6 +506,26 @@ def __add_trait_to_traits_data(trait_id: str, trait_properties: dict, traits_dat
for name, value in trait_properties.items():
traits_data.setTraitProperty(trait_id, name, value)

def __validate_access(
self,
function_name: str,
allowed_access: Iterable[Context.Access],
context: Context,
batch_elems: List[Any],
error_callback,
):
if context.access in allowed_access:
return True
for idx, _ in enumerate(batch_elems):
error_callback(
idx,
BatchElementError(
BatchElementError.ErrorCode.kEntityAccessError,
f"Unsupported access mode for {function_name}",
),
)
return False

@staticmethod
def __handle_exception(exc, idx, error_callback):
"""
Expand Down
Loading

0 comments on commit 5c0f358

Please sign in to comment.