diff --git a/awx/main/models/organization.py b/awx/main/models/organization.py index 1caa694dd5..d79a6972e2 100644 --- a/awx/main/models/organization.py +++ b/awx/main/models/organization.py @@ -53,12 +53,12 @@ class Organization(CommonModel, ResourceMixin): related_name='organizations', ) admin_role = ImplicitRoleField( - role_name='Organization Administrator', + role_name='Organization Administrator', resource_field='resource', permissions = { 'all': True } ) auditor_role = ImplicitRoleField( - role_name='Organization Auditor', + role_name='Organization Auditor', resource_field='resource', permissions = { 'read': True } ) @@ -76,6 +76,16 @@ class Organization(CommonModel, ResourceMixin): script.save() super(Organization, self).mark_inactive(save=save) + def migrate_to_rbac(self): + migrated_users = [] + for admin in self.admins.all(): + self.admin_role.members.add(admin) + migrated_users.append(admin) + for user in self.users.all(): + self.auditor_role.members.add(user) + migrated_user.append(user) + return migrated_users + class Team(CommonModelNameNotUnique, ResourceMixin): ''' @@ -105,19 +115,19 @@ class Team(CommonModelNameNotUnique, ResourceMixin): related_name='teams', ) admin_role = ImplicitRoleField( - role_name='Team Administrator', + role_name='Team Administrator', parent_role='organization.admin_role', resource_field='resource', permissions = { 'all': True } ) auditor_role = ImplicitRoleField( - role_name='Team Auditor', + role_name='Team Auditor', parent_role='organization.auditor_role', resource_field='resource', permissions = { 'read': True } ) member_role = ImplicitRoleField( - role_name='Team Member', + role_name='Team Member', parent_role='admin_role', ) @@ -210,7 +220,7 @@ class Profile(CreatedModifiedModel): ) """ -Since expiration and session expiration is event driven a token could be +Since expiration and session expiration is event driven a token could be invalidated for both reasons. Further, we only support a single reason for a session token being invalid. For this case, mark the token as expired. @@ -234,7 +244,7 @@ class AuthToken(BaseModel): class Meta: app_label = 'main' - + key = models.CharField(max_length=40, primary_key=True) user = models.ForeignKey('auth.User', related_name='auth_tokens', on_delete=models.CASCADE) @@ -351,7 +361,7 @@ def user_mark_inactive(user, save=True): user.is_active = False if save: user.save() - + User.add_to_class('mark_inactive', user_mark_inactive) diff --git a/awx/main/tests/functional/test_rbac_migrations.py b/awx/main/tests/functional/test_rbac_migrations.py new file mode 100644 index 0000000000..9747f67ee9 --- /dev/null +++ b/awx/main/tests/functional/test_rbac_migrations.py @@ -0,0 +1,29 @@ +import pytest + +from awx.main.models.organization import Organization +from django.contrib.auth.models import User + +def make_user(name, admin=False): + email = '%s@example.org' % name + if admin == True: + return User.objects.create_superuser(name, email, name) + else: + return User.objects.create_user(name, email, name) + +@pytest.fixture +def organization(): + return Organization.objects.create(name="test-org", description="test-org-desc") + +@pytest.mark.django_db +@pytest.mark.parametrize("username,admin", [ + ("admin", True), + ("user", False), +]) +def test_organization_migration(organization, username, admin): + user = make_user(username, admin) + organization.admins.add(user) + + migrated_users = organization.migrate_to_rbac() + assert len(migrated_users) == 1 + assert migrated_users[0] == user +