Roles '{flamenco,attract}-user' are now linked to 'subscriber'

All users who get 'subscriber' role automatically get 'flamenco-user' and
'attract-user', and when 'subscriber' is revoked, so are
'{flamenco,attract}-user'.
This commit is contained in:
Sybren A. Stüvel 2017-07-11 12:40:13 +02:00
parent a43e84f93e
commit 0a9f0ebddb
4 changed files with 86 additions and 0 deletions

View File

@ -75,6 +75,46 @@ class CloudExtension(PillarExtension):
'current_user_is_subscriber': authorization.user_matches_roles(ROLES_TO_BE_SUBSCRIBER)
}
def setup_app(self, app):
"""Links certain roles to the subscriber role.
This means that users who get the subscriber role also get this linked
role, and when the subscriber role is revoked, the linked role is also
revoked.
"""
from pillar.api.service import signal_user_changed_role
signal_user_changed_role.connect(self._user_changed_role)
def _user_changed_role(self, sender, user: dict):
from pillar.api import service
linked_roles = {'flamenco-user', 'attract-user'}
link_to = 'subscriber'
user_roles = set(user.get('roles', []))
# Determine what to do
has_linked_roles = not (linked_roles - user_roles)
action = ''
if link_to in user_roles and not has_linked_roles:
self._log.info('Granting roles %s to user %s', linked_roles, user['_id'])
action = 'grant'
elif link_to not in user_roles and has_linked_roles:
self._log.info('Revoking roles %s from user %s', linked_roles, user['_id'])
action = 'revoke'
if not action:
return
# Avoid infinite loops while we're changing the user's roles.
service.signal_user_changed_role.disconnect(self._user_changed_role)
try:
for role in linked_roles:
service.do_badger(action, role, user_id=user['_id'])
finally:
service.signal_user_changed_role.connect(self._user_changed_role)
def _get_current_cloud():
"""Returns the Cloud extension of the current application."""

5
setup.cfg Normal file
View File

@ -0,0 +1,5 @@
[tool:pytest]
addopts = -v --cov cloud --cov-report term-missing --ignore node_modules --ignore docker
[pep8]
max-line-length = 100

View File

@ -0,0 +1,24 @@
from pillar.tests import PillarTestServer, AbstractPillarTest
class CloudTestServer(PillarTestServer):
def __init__(self, *args, **kwargs):
PillarTestServer.__init__(self, *args, **kwargs)
from flamenco import FlamencoExtension
from attract import AttractExtension
from cloud import CloudExtension
self.load_extension(FlamencoExtension(), '/flamenco')
self.load_extension(AttractExtension(), '/attract')
self.load_extension(CloudExtension(), None)
class AbstractCloudTest(AbstractPillarTest):
pillar_server_class = CloudTestServer
def tearDown(self):
self.unload_modules('cloud')
self.unload_modules('attract')
self.unload_modules('flamenco')
AbstractPillarTest.tearDown(self)

View File

@ -0,0 +1,17 @@
from abstract_cloud_test import AbstractCloudTest
class LinkedRolesTest(AbstractCloudTest):
def test_linked_roles(self):
user_id = self.create_user(roles=[])
db_user = self.fetch_user_from_db(user_id)
self.badger(db_user['email'], {'subscriber'}, 'grant')
db_user = self.fetch_user_from_db(user_id)
self.assertEqual({'subscriber', 'flamenco-user', 'attract-user'},
set(db_user['roles']))
self.badger(db_user['email'], {'subscriber'}, 'revoke')
db_user = self.fetch_user_from_db(user_id)
self.assertEqual(set(),
set(db_user.get('roles', [])))