diff --git a/irods/manager/user_manager.py b/irods/manager/user_manager.py index 90f4be81..9a934c30 100644 --- a/irods/manager/user_manager.py +++ b/irods/manager/user_manager.py @@ -45,7 +45,30 @@ def remove_quota(self, user_name, resource="total"): self._get_session, "set-quota", "user", user_name, resource, "0" ) + @staticmethod + def _parse_user_and_zone(user_param, zone_param): + """Parse out the uesr name ane zone name from USER and ZONE string parameters. + If the USER string contains # and a non-null-length ZONE spec, ensure that + multiply specified zone names agree. + """ + if '#' in user_param: + u_parsed_user, u_parsed_zone = user_param.split('#', 1) + if not u_parsed_zone: + raise RuntimeError("The compound user#zone specification may not contain a zero-length zone") + else: + if '#' in u_parsed_zone: + raise RuntimeError(f"{u_parsed_zone = } is wrongly formatted") + if zone_param and (u_parsed_zone != zone_param): + raise RuntimeError( + f"Two nonzero-length zone names ({u_parsed_zone}, {zone_param}) " + " were given, but they do not agree." + ) + return u_parsed_user, u_parsed_zone + return user_param, zone_param + def get(self, user_name, user_zone=""): + user_name, user_zone = self._parse_user_and_zone(user_name, user_zone) + if not user_zone: user_zone = self.sess.zone @@ -121,6 +144,12 @@ def create(self, user_name, user_type, user_zone="", auth_str=""): def remove(self, user_name, user_zone="", _object=None): if _object is None: _object = self.get(user_name, user_zone) + + if _object.type == "rodsgroup": + uz_args = (f"{_object.name}",) + else: + uz_args = (f"{_object.name}#{_object.zone}",) + message_body = GeneralAdminRequest( "rm", ( @@ -128,8 +157,7 @@ def remove(self, user_name, user_zone="", _object=None): if (_object.type != "rodsgroup" or self.sess.server_version < (4, 3, 2)) else "group" ), - user_name, - user_zone, + *uz_args, ) request = iRODSMessage( "RODS_API_REQ", msg=message_body, int_info=api_number["GENERAL_ADMIN_AN"] diff --git a/irods/test/admin_test.py b/irods/test/admin_test.py index 91faad39..b0760061 100644 --- a/irods/test/admin_test.py +++ b/irods/test/admin_test.py @@ -4,16 +4,19 @@ import os import sys import unittest -from irods.models import User, Group + +from irods.column import Like from irods.exception import ( UserDoesNotExist, ResourceDoesNotExist, SYS_NO_API_PRIV, ) -from irods.session import iRODSSession +from irods.models import Collection, Group, User from irods.resource import iRODSResource -import irods.test.helpers as helpers +from irods.session import iRODSSession + import irods.keywords as kw +import irods.test.helpers as helpers class TestAdmin(unittest.TestCase): @@ -531,6 +534,20 @@ def test_set_user_info(self): with self.assertRaises(UserDoesNotExist): self.sess.users.get(self.new_user_name) + def test_deleting_remote_user_including_home_collection_and_trash_artifact__issue_763(self): + remote_zone = remote_user = None + try: + remote_zone = (sess := self.sess).zones.create('other_zone', 'remote') + remote_user = sess.users.create(user_name='myuser', user_type='rodsuser', user_zone=remote_zone.name) + remote_user.remove() + remaining_collections = list( + sess.query(Collection).filter(Like(Collection.name, f'%/{remote_user}#{remote_zone}')) + ) + self.assertEqual(len(remaining_collections), 0) + finally: + if remote_zone: + remote_zone.remove() + if __name__ == "__main__": # let the tests find the parent irods lib diff --git a/irods/test/user_group_test.py b/irods/test/user_group_test.py index 5ce8b84a..4d9f0c52 100644 --- a/irods/test/user_group_test.py +++ b/irods/test/user_group_test.py @@ -143,6 +143,7 @@ def generator(p=OLDPASS): shutil.rmtree(ENV_DIR) ses.users.remove("alice") + def test_modifying_password_at_various_lengths__issue_328(self): ses = self.sess try: