Skip to content

[SYNPY-1244] Add delete permissions/acl functionality #1200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 9, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions docs/reference/experimental/async/dataset.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ at your own risk.
- delete_column
- reorder_column
- rename_column
- get_permissions
- get_acl
- set_permissions
- get_permissions_async
- get_acl_async
- set_permissions_async
- delete_permissions_async
---
[](){ #entity-ref-reference-async }
::: synapseclient.models.EntityRef
Expand Down
7 changes: 4 additions & 3 deletions docs/reference/experimental/async/dataset_collection.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ at your own risk.
- delete_column
- reorder_column
- rename_column
- get_permissions
- get_acl
- set_permissions
- get_permissions_async
- get_acl_async
- set_permissions_async
- delete_permissions_async
---
[](){ #entity-ref-dataset-collection-reference-async }
::: synapseclient.models.EntityRef
Expand Down
1 change: 1 addition & 0 deletions docs/reference/experimental/async/entityview.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ at your own risk.
- get_acl_async
- get_permissions_async
- set_permissions_async
- delete_permissions_async
---

[](){ #view-type-mask-reference }
Expand Down
1 change: 1 addition & 0 deletions docs/reference/experimental/async/file.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ at your own risk.
- get_permissions_async
- get_acl_async
- set_permissions_async
- delete_permissions_async
---
[](){ #filehandle-reference-async }
::: synapseclient.models.file.FileHandle
Expand Down
1 change: 1 addition & 0 deletions docs/reference/experimental/async/folder.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ at your own risk.
- get_permissions_async
- get_acl_async
- set_permissions_async
- delete_permissions_async
7 changes: 4 additions & 3 deletions docs/reference/experimental/async/materializedview.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ at your own risk.
- delete_async
- query_async
- query_part_mask_async
- get_permissions
- get_acl
- set_permissions
- get_permissions_async
- get_acl_async
- set_permissions_async
- delete_permissions_async
1 change: 1 addition & 0 deletions docs/reference/experimental/async/project.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ at your own risk.
- get_permissions_async
- get_acl_async
- set_permissions_async
- delete_permissions_async
7 changes: 4 additions & 3 deletions docs/reference/experimental/async/table.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ at your own risk.
- delete_column
- add_column
- reorder_column
- get_permissions
- get_acl
- set_permissions
- get_permissions_async
- get_acl_async
- set_permissions_async
- delete_permissions_async

[](){ #column-reference-async }
::: synapseclient.models.Column
Expand Down
7 changes: 4 additions & 3 deletions docs/reference/experimental/async/virtualtable.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ at your own risk.
- delete_async
- query_async
- query_part_mask_async
- get_permissions
- get_acl
- set_permissions
- get_permissions_async
- get_acl_async
- set_permissions_async
- delete_permissions_async
1 change: 1 addition & 0 deletions docs/reference/experimental/sync/dataset.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ at your own risk.
- get_permissions
- get_acl
- set_permissions
- delete_permissions
---
[](){ #entity-ref-reference-sync }
::: synapseclient.models.EntityRef
Expand Down
1 change: 1 addition & 0 deletions docs/reference/experimental/sync/dataset_collection.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ at your own risk.
- get_permissions
- get_acl
- set_permissions
- delete_permissions
---
[](){ #entity-ref-dataset-collection-reference-sync }
::: synapseclient.models.EntityRef
Expand Down
1 change: 1 addition & 0 deletions docs/reference/experimental/sync/entityview.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ at your own risk.
- get_acl
- get_permissions
- set_permissions
- delete_permissions
---

[](){ #view-type-mask-reference-sync }
Expand Down
1 change: 1 addition & 0 deletions docs/reference/experimental/sync/file.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ at your own risk.
- get_permissions
- get_acl
- set_permissions
- delete_permissions
---
[](){ #filehandle-reference-sync }
::: synapseclient.models.file.FileHandle
Expand Down
1 change: 1 addition & 0 deletions docs/reference/experimental/sync/folder.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ at your own risk.
- get_permissions
- get_acl
- set_permissions
- delete_permissions
1 change: 1 addition & 0 deletions docs/reference/experimental/sync/materializedview.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ at your own risk.
- get_permissions
- get_acl
- set_permissions
- delete_permissions
1 change: 1 addition & 0 deletions docs/reference/experimental/sync/project.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ at your own risk.
- get_permissions
- get_acl
- set_permissions
- delete_permissions
1 change: 1 addition & 0 deletions docs/reference/experimental/sync/submissionview.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ at your own risk.
- get_acl
- get_permissions
- set_permissions
- delete_permissions
1 change: 1 addition & 0 deletions docs/reference/experimental/sync/table.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ at your own risk.
- get_permissions
- get_acl
- set_permissions
- delete_permissions

[](){ #column-reference-sync }
::: synapseclient.models.Column
Expand Down
1 change: 1 addition & 0 deletions docs/reference/experimental/sync/virtualtable.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ at your own risk.
- get_permissions
- get_acl
- set_permissions
- delete_permissions
2 changes: 2 additions & 0 deletions synapseclient/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from .entity_services import (
create_access_requirements_if_none,
delete_entity,
delete_entity_acl,
delete_entity_generated_by,
get_entities_by_md5,
get_entity,
Expand Down Expand Up @@ -81,6 +82,7 @@
"put_entity",
"post_entity",
"delete_entity",
"delete_entity_acl",
"get_upload_destination",
"get_upload_destination_location",
"create_access_requirements_if_none",
Expand Down
54 changes: 54 additions & 0 deletions synapseclient/api/entity_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,60 @@ async def main():
)


async def delete_entity_acl(
entity_id: str,
*,
synapse_client: Optional["Synapse"] = None,
) -> None:
"""
Delete the Access Control List (ACL) for a given Entity.

By default, Entities such as FileEntity and Folder inherit their permission from
their containing Project. For such Entities the Project is the Entity's 'benefactor'.
This permission inheritance can be overridden by creating an ACL for the Entity.
When this occurs the Entity becomes its own benefactor and all permission are
determined by its own ACL.

If the ACL of an Entity is deleted, then its benefactor will automatically be set
to its parent's benefactor. The ACL for a Project cannot be deleted.

Note: The caller must be granted ACCESS_TYPE.CHANGE_PERMISSIONS on the Entity to
call this method.

Arguments:
entity_id: The ID of the entity that should have its ACL deleted.
synapse_client: If not passed in and caching was not disabled by
`Synapse.allow_client_caching(False)` this will use the last created
instance from the Synapse class constructor.

Example: Delete the ACL for entity `syn123`:
This will delete the ACL for the entity, making it inherit permissions from
its parent.

```python
import asyncio
from synapseclient import Synapse
from synapseclient.api import delete_entity_acl

syn = Synapse()
syn.login()

async def main():
await delete_entity_acl(entity_id="syn123")

asyncio.run(main())
```

Returns: None
"""
from synapseclient import Synapse

client = Synapse.get_client(synapse_client=synapse_client)
return await client.rest_delete_async(
uri=f"/entity/{entity_id}/acl",
)


async def get_entity_path(
entity_id: str,
*,
Expand Down
46 changes: 38 additions & 8 deletions synapseclient/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2725,7 +2725,7 @@ def getChildren(

Arguments:
parent: An id or an object of a Synapse container or None to retrieve all projects
includeTypes: Must be a list of entity types (ie. ["folder","file"]) which can be found [here](http://docs.synapse.org/rest/org/sagebionetworks/repo/model/EntityType.html)
includeTypes: Must be a list of entity types (ie. ["folder","file"]) which can be found [here](https://rest-docs.synapse.org/rest/org/sagebionetworks/repo/model/EntityType.html)
sortBy: How results should be sorted. Can be NAME, or CREATED_ON
sortDirection: The direction of the result sort. Can be ASC, or DESC

Expand Down Expand Up @@ -2795,24 +2795,48 @@ def _getBenefactor(

return entity

def _getACL(self, entity: Union[Entity, str]) -> Dict[str, Union[str, list]]:
def _getACL(
self, entity: Union[Entity, str], check_benefactor: bool = True
) -> Dict[str, Union[str, list]]:
"""
Get the effective Access Control Lists (ACL) for a Synapse Entity.

Arguments:
entity: A Synapse Entity or Synapse ID
check_benefactor: If True (default), check the benefactor for the entity
to get the ACL. If False, only check the entity itself.
This is useful for checking the ACL of an entity that has local sharing
settings, but you want to check the ACL of the entity itself and not
the benefactor it may inherit from.

Returns:
A dictionary of the Entity's ACL
"""
if hasattr(entity, "getACLURI"):
uri = entity.getACLURI()
else:
# Get the ACL from the benefactor (which may be the entity itself)
benefactor = self._getBenefactor(entity)
trace.get_current_span().set_attributes({"synapse.id": benefactor["id"]})
uri = "/entity/%s/acl" % (benefactor["id"])
return self.restGET(uri)
if check_benefactor:
# Get the ACL from the benefactor (which may be the entity itself)
benefactor = self._getBenefactor(entity)
trace.get_current_span().set_attributes(
{"synapse.id": benefactor["id"]}
)
uri = "/entity/%s/acl" % (benefactor["id"])
return self.restGET(uri)
else:
synid, _ = utils.get_synid_and_version(entity)
trace.get_current_span().set_attributes({"synapse.id": synid})
uri = "/entity/%s/acl" % (synid)
try:
return self.restGET(uri)
except SynapseHTTPError as e:
if (
"The requested ACL does not exist. This entity inherits its permissions from:"
in str(e)
):
# If the entity does not have an ACL, return an empty ACL
return {"resourceAccess": []}
raise e
Comment on lines +2819 to +2840
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I needed to add this set of changes into the client.py because the access_control.py mixin internally still uses it. The purpose of this changes is to allow us to get the ACL for a specific entity without the code automatically getting the benefactor. This is crucial during testing to verify that a given is or is not overwriting the folders ACL that it's contained within.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a nice addition to grab the ACL of an entity - it's confusing because technically the ACL is inherited on child entities from a benefactor but it's nice to not have it return [] when there is clearly an ACL


def _storeACL(
self, entity: Union[Entity, str], acl: Dict[str, Union[str, list]]
Expand Down Expand Up @@ -2889,6 +2913,7 @@ def get_acl(
self,
entity: Union[Entity, Evaluation, str, collections.abc.Mapping],
principal_id: str = None,
check_benefactor: bool = True,
) -> typing.List[str]:
"""
Get the [ACL](https://rest-docs.synapse.org/rest/org/
Expand All @@ -2898,6 +2923,11 @@ def get_acl(
Arguments:
entity: An Entity or Synapse ID to lookup
principal_id: Identifier of a user or group (defaults to PUBLIC users)
check_benefactor: If True (default), check the benefactor for the entity
to get the ACL. If False, only check the entity itself.
This is useful for checking the ACL of an entity that has local sharing
settings, but you want to check the ACL of the entity itself and not
the benefactor it may inherit from.

Returns:
An array containing some combination of
Expand All @@ -2912,7 +2942,7 @@ def get_acl(
{"synapse.id": id_of(entity), "synapse.principal_id": principal_id}
)

acl = self._getACL(entity)
acl = self._getACL(entity=entity, check_benefactor=check_benefactor)

team_list = self._find_teams_for_principal(principal_id)
team_ids = [int(team.id) for team in team_list]
Expand Down
Loading
Loading