Skip to content

[#558] iRODSAccess: Handle iRODSCollection and iRODSDataObject #595

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 2 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 11 additions & 1 deletion irods/access.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import collections
import copy
import six
from irods.collection import iRODSCollection
from irods.data_object import iRODSDataObject
from irods.path import iRODSPath

class _Access_LookupMeta(type):
Expand Down Expand Up @@ -59,7 +61,15 @@ def to_string(cls,key):

def __init__(self, access_name, path, user_name='', user_zone='', user_type=None):
self.access_name = access_name
self.path = path
if isinstance(path, (iRODSCollection, iRODSDataObject)):
self.path = path.path
elif isinstance(path, str):
# This should cover irods.path.iRODSPath as well as it is a descendant type of str.
self.path = path
else:
raise TypeError(
"'path' parameter must be of type 'str', 'irods.collection.iRODSCollection', "
"'irods.data_object.iRODSDataObject', or 'irods.path.iRODSPath'.")
self.user_name = user_name
self.user_zone = user_zone
self.user_type = user_type
Expand Down
80 changes: 80 additions & 0 deletions irods/test/access_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from irods.column import In, Like
from irods.exception import UserDoesNotExist
from irods.models import User,Collection,DataObject
from irods.path import iRODSPath
from irods.user import iRODSUser
from irods.session import iRODSSession
import irods.test.helpers as helpers
Expand Down Expand Up @@ -371,6 +372,85 @@ def test_removed_user_does_not_affect_raw_ACL_queries__issue_431(self):
else:
u.remove()

def test_iRODSAccess_can_be_constructed_using_iRODSCollection__issue_558(self):
user_name = "testuser"
collection_path = "/".join([helpers.home_collection(self.sess), "give_read_access_to_this"])

try:
user = self.sess.users.create(user_name, 'rodsuser')
collection = self.sess.collections.create(collection_path)

# Give user access to data object. This should succeed. Before the fix in #558, this would cause an error
# from pickle during a call to deepcopy of the iRODSAccess object. The library does not know how to pickle
# an iRODSCollection object.
access = iRODSAccess('read', collection, user.name)
self.sess.acls.set(access)

# We can get permissions from collection, and the test user's entry is there.
perms = self.sess.acls.get(collection)
self.assertTrue(any(p for p in perms if p.user_name == user_name))

finally:
self.sess.users.get(user_name).remove()
self.sess.collections.remove(collection_path, force=True)

def test_iRODSAccess_can_be_constructed_using_iRODSDataObject__issue_558(self):
user_name = "testuser"
data_object_path = "/".join([helpers.home_collection(self.sess), "give_read_access_to_this"])

try:
user = self.sess.users.create(user_name, 'rodsuser')
data_object = self.sess.data_objects.create(data_object_path)

# Give user access to data object. This should succeed. Before the fix in #558, this would cause an error
# from pickle during a call to deepcopy of the iRODSAccess object. The library does not know how to pickle
# an iRODSDataObject object.
access = iRODSAccess('read', data_object, user.name)
self.sess.acls.set(access)

# We can get permissions from the data object, and the test user's entry is there.
perms = self.sess.acls.get(data_object)
self.assertTrue(any(p for p in perms if p.user_name == user_name))

finally:
self.sess.users.get(user_name).remove()
self.sess.data_objects.unlink(data_object_path, force=True)

def test_iRODSAccess_can_be_constructed_using_iRODSPath__issue_558(self):
user_name = "testuser"
data_object_path = "/".join([helpers.home_collection(self.sess), "give_read_access_to_this"])

try:
irods_path = iRODSPath(data_object_path)

user = self.sess.users.create(user_name, 'rodsuser')
data_object = self.sess.data_objects.create(data_object_path)

# Give user access to data object. This should succeed. Before the fix in #558, this would cause an error
# from pickle during a call to deepcopy of the iRODSAccess object. The library does not know how to pickle
# an iRODSDataObject object.
access = iRODSAccess('read', irods_path, user.name)
self.sess.acls.set(access)

# We can get permissions from the data object, and the test user's entry is there.
perms = self.sess.acls.get(data_object)
self.assertTrue(any(p for p in perms if p.user_name == user_name))

finally:
self.sess.users.get(user_name).remove()
self.sess.data_objects.unlink(data_object_path, force=True)

def test_iRODSAccess_cannot_be_constructed_using_unsupported_type__issue_558(self):
# Before the fix in #558, this would have been allowed and only later would the type discrepancy be revealed,
# leading to opaque error messages. Now, the types are checked on the way in to ensure clarity and correctness.
# TODO(#480): We cannot use the unittest.assertRaises context manager as this was introduced in python 3.1.
self.assertRaisesRegex(
TypeError,
"'path' parameter must be of type 'str', 'irods.collection.iRODSCollection', "
"'irods.data_object.iRODSDataObject', or 'irods.path.iRODSPath'.",
iRODSAccess, 'read', self.sess)


if __name__ == '__main__':
# let the tests find the parent irods lib
sys.path.insert(0, os.path.abspath('../..'))
Expand Down