Skip to content

Commit c2653ac

Browse files
committed
Remove role-tracking feature no longer used
1 parent 2486153 commit c2653ac

File tree

11 files changed

+129
-394
lines changed

11 files changed

+129
-394
lines changed

ansible_base/rbac/models/role.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -302,11 +302,6 @@ def give_or_remove_permission(self, actor, content_object, giving=True, sync_act
302302

303303
update_after_assignment(update_teams, to_update)
304304

305-
if not sync_action and self.name in permission_registry._trackers:
306-
tracker = permission_registry._trackers[self.name]
307-
with tracker.sync_active():
308-
tracker.sync_relationship(actor, content_object, giving=giving)
309-
310305
return assignment
311306

312307
@classmethod

ansible_base/rbac/permission_registry.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ def __init__(self):
3232
self._parent_fields = dict()
3333
self._managed_roles = dict() # code-defined role definitions, managed=True
3434
self.apps_ready = False
35-
self._tracked_relationships = set()
36-
self._trackers = dict()
3735

3836
def register(self, *args: Type[Model], parent_field_name: Optional[str] = 'organization'):
3937
if self.apps_ready:
@@ -50,9 +48,6 @@ def register(self, *args: Type[Model], parent_field_name: Optional[str] = 'organ
5048
else:
5149
logger.debug(f'Model {cls._meta.model_name} registered to permission registry more than once')
5250

53-
def track_relationship(self, cls, relationship, role_name):
54-
self._tracked_relationships.add((cls, relationship, role_name))
55-
5651
def get_parent_model(self, model) -> Optional[type]:
5752
model = self._name_to_model[model._meta.model_name]
5853
parent_field_name = self.get_parent_fd_name(model)
@@ -158,14 +153,6 @@ def call_when_apps_ready(self, apps, app_config) -> None:
158153
triggers.connect_rbac_signals(cls)
159154
connect_rbac_methods(cls)
160155

161-
for cls, relationship, role_name in self._tracked_relationships:
162-
if role_name in self._trackers:
163-
tracker = self._trackers[role_name]
164-
else:
165-
tracker = triggers.TrackedRelationship(cls, role_name)
166-
self._trackers[role_name] = tracker
167-
tracker.initialize(relationship)
168-
169156
self.register_managed_role_constructors()
170157

171158
@property

ansible_base/rbac/triggers.py

Lines changed: 0 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import logging
2-
from contextlib import contextmanager
32
from typing import Optional, Union
43
from uuid import UUID
54

@@ -303,90 +302,6 @@ def post_migration_rbac_setup(sender, *args, **kwargs):
303302
compute_object_role_permissions()
304303

305304

306-
class TrackedRelationship:
307-
def __init__(self, cls, role_name):
308-
self.cls = cls
309-
self.role_name = role_name
310-
self.user_relationship = None
311-
self.team_relationship = None
312-
self._active_sync_flag = False
313-
314-
def initialize(self, relationship):
315-
manager = getattr(self.cls, relationship)
316-
related_model_name = manager.field.related_model._meta.model_name
317-
if related_model_name == permission_registry.team_model._meta.model_name:
318-
self.team_relationship = relationship
319-
m2m_changed.connect(self.sync_team_to_role, sender=manager.through)
320-
elif related_model_name == permission_registry.user_model._meta.model_name:
321-
self.user_relationship = relationship
322-
m2m_changed.connect(self.sync_user_to_role, sender=manager.through)
323-
else:
324-
raise RuntimeError(f'Can only register user or team relationships, obtained {related_model_name}')
325-
326-
@contextmanager
327-
def sync_active(self):
328-
try:
329-
self._active_sync_flag = True
330-
yield
331-
finally:
332-
self._active_sync_flag = False
333-
334-
def sync_relationship(self, actor, content_object, giving=True):
335-
# Exit if role does not apply for the intended model type, for example
336-
# if user is given "team-member" role to organization, do not add user to the team members
337-
if content_object._meta.model_name != self.cls._meta.model_name:
338-
return
339-
340-
if actor._meta.model_name == permission_registry.team_model._meta.model_name:
341-
if self.team_relationship is None:
342-
return
343-
manager = getattr(content_object, self.team_relationship)
344-
elif actor._meta.model_name == permission_registry.user_model._meta.model_name:
345-
if self.user_relationship is None:
346-
return
347-
manager = getattr(content_object, self.user_relationship)
348-
349-
if giving:
350-
manager.add(actor)
351-
else:
352-
manager.remove(actor)
353-
354-
def _sync_actor_to_role(self, actor_model: type, instance: Model, action: str, pk_set: Optional[set[int]]):
355-
if self._active_sync_flag:
356-
return
357-
if action.startswith('pre_'):
358-
return
359-
rd = RoleDefinition.objects.get(name=self.role_name)
360-
361-
if action in ('post_add', 'post_remove'):
362-
actor_set = pk_set
363-
elif action == 'post_clear':
364-
ct = permission_registry.content_type_model.objects.get_for_model(instance)
365-
role = ObjectRole.objects.get(object_id=instance.pk, content_type=ct, role_definition=rd)
366-
if actor_model._meta.model_name == 'team':
367-
actor_set = set(role.teams.values_list('id', flat=True))
368-
else:
369-
actor_set = set(role.users.values_list('id', flat=True))
370-
371-
giving = bool(action == 'post_add')
372-
for actor in actor_model.objects.filter(pk__in=actor_set):
373-
rd.give_or_remove_permission(actor, instance, giving=giving, sync_action=True)
374-
375-
def sync_team_to_role(self, instance: Model, action: str, model: type, pk_set: Optional[set[int]], reverse: bool, **kwargs):
376-
if not reverse:
377-
self._sync_actor_to_role(permission_registry.team_model, instance, action, pk_set)
378-
else:
379-
for pk in pk_set:
380-
self._sync_actor_to_role(permission_registry.team_model, model(pk=pk), action, {instance.pk})
381-
382-
def sync_user_to_role(self, instance: Model, action: str, model: type, pk_set: Optional[set[int]], reverse: bool, **kwargs):
383-
if not reverse:
384-
self._sync_actor_to_role(permission_registry.user_model, instance, action, pk_set)
385-
else:
386-
for pk in pk_set:
387-
self._sync_actor_to_role(permission_registry.user_model, model(pk=pk), action, {instance.pk})
388-
389-
390305
def connect_rbac_signals(cls):
391306
if cls._meta.model_name == permission_registry.team_model._meta.model_name:
392307
pre_delete.connect(team_pre_delete, sender=cls, dispatch_uid='stash-team-roles-before-delete')

docs/apps/rbac/for_app_developers.md

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -344,27 +344,6 @@ If you create (in code) a role definition that sets `managed` to True, then thes
344344
rules will be disregarded for that particular role definition. Managed role
345345
definitions can not be created through the API, but can be created in code like migration scripts.
346346

347-
### Tracked Relationships
348-
349-
Let's say that you are introducing RBAC, and you have already set up your API
350-
with some relationship, like members of a team, and parents of a team
351-
(to get nested teams).
352-
This sub-feature will use signals to do bidirectional syncing of memberships of
353-
that relationship with memberships of their corresponding role.
354-
355-
```
356-
permission_registry.track_relationship(Team, 'users', 'Team Member')
357-
permission_registry.track_relationship(Team, 'team_parents', 'Team Member')
358-
```
359-
360-
This only works with our 2 "actor" types of users and teams.
361-
Adding these lines will synchronize users and teams of team-object-roles with the "team-member"
362-
role definition (by name) to the `Team.users`
363-
and `Team.tracked_parents` ManyToMany relationships, respectively.
364-
So if you have a team object, `team.users.add(user)` will also give that
365-
user _member permission_ to that team, where those permissions are defined by the
366-
role definition with the name "team-member".
367-
368347

369348
### Role assignment callback
370349

test_app/migrations/0001_initial.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@ class Migration(migrations.Migration):
5555
('description', models.TextField(blank=True, default='', help_text='The organization description.')),
5656
('created_by', models.ForeignKey(default=None, editable=False, help_text='The user who created this resource', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='%(app_label)s_%(class)s_created+', to=settings.AUTH_USER_MODEL)),
5757
('modified_by', models.ForeignKey(default=None, editable=False, help_text='The user who last modified this resource', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='%(app_label)s_%(class)s_modified+', to=settings.AUTH_USER_MODEL)),
58-
('admins', models.ManyToManyField(blank=True, help_text='The list of admins for this organization', related_name='admin_of_organizations', to=settings.AUTH_USER_MODEL)),
59-
('users', models.ManyToManyField(blank=True, help_text='The list of users on this organization', related_name='member_of_organizations', to=settings.AUTH_USER_MODEL))
6058
],
6159
options={'ordering': ['id'], 'permissions': [('member_organization', 'User is member of this organization')]},
6260
),
@@ -85,7 +83,6 @@ class Migration(migrations.Migration):
8583
('created_by', models.ForeignKey(default=None, editable=False, help_text='The user who created this resource', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='%(app_label)s_%(class)s_created+', to=settings.AUTH_USER_MODEL)),
8684
('modified_by', models.ForeignKey(default=None, editable=False, help_text='The user who last modified this resource', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='%(app_label)s_%(class)s_modified+', to=settings.AUTH_USER_MODEL)),
8785
('organization', models.ForeignKey(help_text='The organization of this team.', on_delete=django.db.models.deletion.CASCADE, related_name='teams', to=settings.ANSIBLE_BASE_ORGANIZATION_MODEL)),
88-
('team_parents', models.ManyToManyField(blank=True, related_name='team_children', to=settings.ANSIBLE_BASE_TEAM_MODEL)),
8986
],
9087
options={
9188
'ordering': ('organization__name', 'name'),
Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# Generated by Django 4.2.8 on 2024-03-18 12:43
22

3-
from django.conf import settings
4-
from django.db import migrations, models
3+
from django.db import migrations
54

65

76
class Migration(migrations.Migration):
@@ -11,14 +10,5 @@ class Migration(migrations.Migration):
1110
]
1211

1312
operations = [
14-
migrations.AddField(
15-
model_name='team',
16-
name='admins',
17-
field=models.ManyToManyField(blank=True, help_text='The list of admins for this team', related_name='teams_administered', to=settings.AUTH_USER_MODEL),
18-
),
19-
migrations.AddField(
20-
model_name='team',
21-
name='users',
22-
field=models.ManyToManyField(blank=True, help_text='The list of users on this team', related_name='teams', to=settings.AUTH_USER_MODEL),
23-
),
13+
# Removed team admins and user relationsips
2414
]

test_app/models.py

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,6 @@ class Meta:
3030

3131
resource = AnsibleResourceField(primary_key_field="id")
3232

33-
users = models.ManyToManyField(
34-
settings.AUTH_USER_MODEL,
35-
related_name='member_of_organizations',
36-
blank=True,
37-
help_text="The list of users on this organization",
38-
)
39-
40-
admins = models.ManyToManyField(
41-
settings.AUTH_USER_MODEL,
42-
related_name='admin_of_organizations',
43-
blank=True,
44-
help_text="The list of admins for this organization",
45-
)
46-
4733
extra_field = models.CharField(max_length=100, null=True)
4834

4935

@@ -73,7 +59,6 @@ class ManagedUser(User):
7359

7460
class Team(AbstractTeam):
7561
resource = AnsibleResourceField(primary_key_field="id")
76-
team_parents = models.ManyToManyField('Team', related_name='team_children', blank=True)
7762

7863
encryptioner = models.ForeignKey('test_app.EncryptionModel', on_delete=models.SET_NULL, null=True)
7964

@@ -89,20 +74,6 @@ class Meta:
8974
ordering = ('organization__name', 'name')
9075
permissions = [('member_team', 'Has all roles assigned to this team')]
9176

92-
users = models.ManyToManyField(
93-
User,
94-
related_name='teams',
95-
blank=True,
96-
help_text="The list of users on this team",
97-
)
98-
99-
admins = models.ManyToManyField(
100-
User,
101-
related_name='teams_administered',
102-
blank=True,
103-
help_text="The list of admins for this team",
104-
)
105-
10677

10778
class ResourceMigrationTestModel(models.Model):
10879
name = models.CharField(max_length=255)
@@ -383,17 +354,6 @@ class Meta:
383354
permission_registry.register(ExtraExtraUUIDModel, parent_field_name='extra_uuid')
384355

385356

386-
# NOTE(cutwater): Using hard coded role names instead of ones defined in ReconcileUser class,
387-
# to avoid circular dependency between models and claims modules. This is a temporary workarond,
388-
# since we plan to drop support of tracked relationships in future.
389-
permission_registry.track_relationship(Team, 'users', 'Team Member')
390-
permission_registry.track_relationship(Team, 'admins', 'Team Admin')
391-
permission_registry.track_relationship(Team, 'team_parents', 'Team Member')
392-
393-
permission_registry.track_relationship(Organization, 'users', 'Organization Member')
394-
permission_registry.track_relationship(Organization, 'admins', 'Organization Admin')
395-
396-
397357
class MultipleFieldsModel(NamedCommonModel):
398358
class Meta:
399359
app_label = "test_app"

test_app/tests/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -667,15 +667,15 @@ def org_member_rd():
667667

668668
@pytest.fixture
669669
def member_rd():
670-
"Member role for a team, place in root conftest because it is needed for the team users tracked relationship"
670+
"Member role for a team"
671671
RoleDefinition.objects.managed.clear()
672672
yield RoleDefinition.objects.managed.team_member
673673
RoleDefinition.objects.managed.clear()
674674

675675

676676
@pytest.fixture
677677
def admin_rd():
678-
"Member role for a team, place in root conftest because it is needed for the team users tracked relationship"
678+
"Admin role for a team"
679679
RoleDefinition.objects.managed.clear()
680680
yield RoleDefinition.objects.managed.team_admin
681681
RoleDefinition.objects.managed.clear()

0 commit comments

Comments
 (0)