From e8eed8e949b98b8f39cc52e6236aaa3e27b802da Mon Sep 17 00:00:00 2001 From: Mathieu Leplatre Date: Tue, 9 Feb 2016 15:37:38 +0100 Subject: [PATCH 1/3] Add a method to remove every principals --- CHANGELOG.rst | 1 + cliquet/permission/__init__.py | 7 +++++++ cliquet/permission/memory.py | 7 +++++++ cliquet/permission/postgresql/__init__.py | 7 +++++++ cliquet/permission/redis.py | 7 +++++++ cliquet/tests/test_permission.py | 15 +++++++++++++++ 6 files changed, 44 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ecaeaf3c..9cd8018d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -12,6 +12,7 @@ This document describes changes between each past release. - Resource events are now merged in batch requests. One event per resource and per action is emitted when a transaction is committed (#634) - Monitor time of events listeners execution (fixes #503) +- Add method to remove a principal from every user **Bug fixes** diff --git a/cliquet/permission/__init__.py b/cliquet/permission/__init__.py index 6f1cc3da..1dd9a45c 100644 --- a/cliquet/permission/__init__.py +++ b/cliquet/permission/__init__.py @@ -39,6 +39,13 @@ def remove_user_principal(self, user_id, principal): """ raise NotImplementedError + def remove_principal(self, principal): + """Remove a principal from every user. + + :param str principal: The principal to remove. + """ + raise NotImplementedError + def user_principals(self, user_id): """Return the set of additionnal principals given to a user. diff --git a/cliquet/permission/memory.py b/cliquet/permission/memory.py index baeb9f52..0be8c86c 100644 --- a/cliquet/permission/memory.py +++ b/cliquet/permission/memory.py @@ -43,6 +43,13 @@ def remove_user_principal(self, user_id, principal): else: self._store[user_key] = user_principals + def remove_principal(self, principal): + for user_principals in self._store.values(): + try: + user_principals.remove(principal) + except KeyError: + pass + def user_principals(self, user_id): user_key = 'user:%s' % user_id members = self._store.get(user_key, set()) diff --git a/cliquet/permission/postgresql/__init__.py b/cliquet/permission/postgresql/__init__.py index 3bc12b04..b27e3ad1 100644 --- a/cliquet/permission/postgresql/__init__.py +++ b/cliquet/permission/postgresql/__init__.py @@ -105,6 +105,13 @@ def remove_user_principal(self, user_id, principal): with self.client.connect() as conn: conn.execute(query, dict(user_id=user_id, principal=principal)) + def remove_principal(self, principal): + query = """ + DELETE FROM user_principals + WHERE principal = :principal;""" + with self.client.connect() as conn: + conn.execute(query, dict(principal=principal)) + def user_principals(self, user_id): query = """ SELECT principal diff --git a/cliquet/permission/redis.py b/cliquet/permission/redis.py index 36d58c3a..ee6ecaf0 100644 --- a/cliquet/permission/redis.py +++ b/cliquet/permission/redis.py @@ -55,6 +55,13 @@ def remove_user_principal(self, user_id, principal): if self._client.scard(user_key) == 0: self._client.delete(user_key) + def remove_principal(self, principal): + with self._client.pipeline() as pipe: + user_keys = self._client.scan_iter(match='user:*') + for user_key in user_keys: + self._client.srem(user_key, principal) + pipe.execute() + @wrap_redis_error def user_principals(self, user_id): user_key = 'user:%s' % user_id diff --git a/cliquet/tests/test_permission.py b/cliquet/tests/test_permission.py index df71531e..8ed1458a 100644 --- a/cliquet/tests/test_permission.py +++ b/cliquet/tests/test_permission.py @@ -148,6 +148,21 @@ def test_can_remove_a_unexisting_principal_to_a_user(self): retrieved = self.permission.user_principals(user_id) self.assertEquals(retrieved, set()) + def test_can_remove_principal_from_every_users(self): + user_id1 = 'foo1' + user_id2 = 'foo2' + principal1 = 'bar' + principal2 = 'foobar' + self.permission.add_user_principal(user_id1, principal1) + self.permission.add_user_principal(user_id2, principal1) + self.permission.add_user_principal(user_id2, principal2) + self.permission.remove_principal(principal1) + + retrieved = self.permission.user_principals(user_id1) + self.assertEquals(retrieved, set()) + retrieved = self.permission.user_principals(user_id2) + self.assertEquals(retrieved, {principal2}) + def test_can_add_a_principal_to_an_object_permission(self): object_id = 'foo' permission = 'write' From 964c549a574f69b35c39cd897e3137ea7d0db4b3 Mon Sep 17 00:00:00 2001 From: Mathieu Leplatre Date: Tue, 9 Feb 2016 15:50:35 +0100 Subject: [PATCH 2/3] Fix coverage --- cliquet/tests/test_permission.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cliquet/tests/test_permission.py b/cliquet/tests/test_permission.py index 8ed1458a..040cb33c 100644 --- a/cliquet/tests/test_permission.py +++ b/cliquet/tests/test_permission.py @@ -22,6 +22,7 @@ def test_mandatory_overrides(self): (self.permission.flush,), (self.permission.add_user_principal, '', ''), (self.permission.remove_user_principal, '', ''), + (self.permission.remove_principal, ''), (self.permission.user_principals, ''), (self.permission.add_principal_to_ace, '', '', ''), (self.permission.remove_principal_from_ace, '', '', ''), @@ -157,6 +158,7 @@ def test_can_remove_principal_from_every_users(self): self.permission.add_user_principal(user_id2, principal1) self.permission.add_user_principal(user_id2, principal2) self.permission.remove_principal(principal1) + self.permission.remove_principal('unknown') retrieved = self.permission.user_principals(user_id1) self.assertEquals(retrieved, set()) From 18f236e56315cc9e6a0a278fb9783c6bf4a4da94 Mon Sep 17 00:00:00 2001 From: Mathieu Leplatre Date: Wed, 10 Feb 2016 12:57:34 +0100 Subject: [PATCH 3/3] @Natim review --- cliquet/permission/redis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cliquet/permission/redis.py b/cliquet/permission/redis.py index ee6ecaf0..abab7911 100644 --- a/cliquet/permission/redis.py +++ b/cliquet/permission/redis.py @@ -59,7 +59,7 @@ def remove_principal(self, principal): with self._client.pipeline() as pipe: user_keys = self._client.scan_iter(match='user:*') for user_key in user_keys: - self._client.srem(user_key, principal) + pipe.srem(user_key, principal) pipe.execute() @wrap_redis_error