From 16416aad26982cd0a8383238cacf655bc991d919 Mon Sep 17 00:00:00 2001 From: Emilian Schweikert Date: Wed, 19 Aug 2026 14:04:57 +0200 Subject: [PATCH 1/2] fix(dim): fix pool attr right revoke with dots - Resolve an issue where revoking an 'attr' right with trailing or leading dots (e.g., 'attr.audit.') would fail silently because the DB query searched for 'attr' instead of the full attribute right string. - Make 'group_grant_access' and 'group_revoke_access' symmetric and robust by automatically handling both stripped (e.g., 'audit.') and prefixed (e.g., 'attr.audit.') inputs for the 'attr' right type. - Add comprehensive integration tests in 'dim-testsuite/tests/rights_test.py' covering all edge cases (with/without dot, prefix robustness, and independence between rights). Co-authored-by: Gemini --- dim-testsuite/tests/rights_test.py | 36 ++++++++++++++++++++++++++++++ dim/dim/rpc.py | 11 ++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/dim-testsuite/tests/rights_test.py b/dim-testsuite/tests/rights_test.py index 2630b6d4..ba6b93c6 100644 --- a/dim-testsuite/tests/rights_test.py +++ b/dim-testsuite/tests/rights_test.py @@ -91,6 +91,42 @@ def test_grant(self): assert self.user.group_get_access('usergroup') == [] self.net.group_revoke_access('usergroup', 'allocate', 'pool') + # 1. Test for the attr revoke bugfix (with dot) + self.net.group_grant_access('usergroup', 'attr', ['audit.', 'pool']) + assert self.user.ippool_get_access('pool') == [{'action': 'attr.audit.', 'group': 'usergroup', 'object': 'pool'}] + self.net.group_revoke_access('usergroup', 'attr', ['audit.', 'pool']) + assert self.user.ippool_get_access('pool') == [] + + # 2. Test for robustness (symmetry with direct 'attr.' prefix) + self.net.group_grant_access('usergroup', 'attr', ['attr.audit.', 'pool']) + assert self.user.ippool_get_access('pool') == [{'action': 'attr.audit.', 'group': 'usergroup', 'object': 'pool'}] + self.net.group_revoke_access('usergroup', 'attr', ['attr.audit.', 'pool']) + assert self.user.ippool_get_access('pool') == [] + + # 3. Test for attr revoke (without dot) + self.net.group_grant_access('usergroup', 'attr', ['audit', 'pool']) + assert self.user.ippool_get_access('pool') == [{'action': 'attr.audit', 'group': 'usergroup', 'object': 'pool'}] + self.net.group_revoke_access('usergroup', 'attr', ['audit', 'pool']) + assert self.user.ippool_get_access('pool') == [] + + # 4. Independence test (scenario from ticket 2) + # Grant both rights (with and without dot) + self.net.group_grant_access('usergroup', 'attr', ['audit', 'pool']) + self.net.group_grant_access('usergroup', 'attr', ['audit.', 'pool']) + rights = self.user.ippool_get_access('pool') + assert {'action': 'attr.audit', 'group': 'usergroup', 'object': 'pool'} in rights + assert {'action': 'attr.audit.', 'group': 'usergroup', 'object': 'pool'} in rights + + # Delete ONLY the right without dot + self.net.group_revoke_access('usergroup', 'attr', ['audit', 'pool']) + # The right with dot MUST still be there! + assert self.user.ippool_get_access('pool') == [{'action': 'attr.audit.', 'group': 'usergroup', 'object': 'pool'}] + + # Delete also the right with dot + self.net.group_revoke_access('usergroup', 'attr', ['audit.', 'pool']) + assert self.user.ippool_get_access('pool') == [] + + def test_group_rename(self): self.net.group_create('usergroup1') self.net.group_rename('usergroup1', 'usergroup') diff --git a/dim/dim/rpc.py b/dim/dim/rpc.py index 9953232b..6a3f4544 100644 --- a/dim/dim/rpc.py +++ b/dim/dim/rpc.py @@ -197,6 +197,12 @@ def group_revoke_access(self, group, access, object=None): rights = get_rights(access, object) for (access, object) in rights: object_id, object_class = get_object_id_class(access, object) + # Fixes revoke attr bug + if access == 'attr' and object: + if object[0].startswith('attr.'): + access = object[0] + else: + access = 'attr.' + object[0] ar = AccessRight.query.filter_by(access=access, object_id=object_id, object_class=object_class).first() @@ -4122,7 +4128,10 @@ def _group_grant_access(group, access, object): for (access, object) in rights: object_id, object_class = get_object_id_class(access, object) if access == 'attr': - access = 'attr.' + object[0] + if object[0].startswith('attr.'): + access = object[0] + else: + access = 'attr.' + object[0] group.rights.add(AccessRight.find_or_create(access=access, object_id=object_id, object_class=object_class)) From b692a13ff84ad3f94514020010d933ea43bb5881 Mon Sep 17 00:00:00 2001 From: Emilian Schweikert Date: Wed, 19 Aug 2026 14:05:38 +0200 Subject: [PATCH 2/2] docs(dim): document pool attr right revoke fix in CHANGES Co-authored-by: Gemini --- dim/CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/dim/CHANGES b/dim/CHANGES index ffca8d93..1dc85a0e 100644 --- a/dim/CHANGES +++ b/dim/CHANGES @@ -1,5 +1,6 @@ unreleased ---------- +* fix revoking attribute rights on pools when utilizing trailing dots or prefix strings * add support for ALIAS resource records (coexists with other types at zone apex, mutually exclusive with CNAME, disabled in DNSSEC-enabled zones) * add support for DNAME resource records according to RFC 6672 (prevents DNAME at zone apex, prevents records under DNAME subtrees) * improve output update performance by using bulk inserts instead of ORM for zone fan-out