Skip to content

Commit 74e5349

Browse files
committed
Remove role-tracking feature no longer used
1 parent 259cae5 commit 74e5349

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
@@ -297,11 +297,6 @@ def give_or_remove_permission(self, actor, content_object, giving=True, sync_act
297297

298298
update_after_assignment(update_teams, to_update)
299299

300-
if not sync_action and self.name in permission_registry._trackers:
301-
tracker = permission_registry._trackers[self.name]
302-
with tracker.sync_active():
303-
tracker.sync_relationship(actor, content_object, giving=giving)
304-
305300
return assignment
306301

307302
@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

@@ -285,90 +284,6 @@ def post_migration_rbac_setup(sender, *args, **kwargs):
285284
compute_object_role_permissions()
286285

287286

288-
class TrackedRelationship:
289-
def __init__(self, cls, role_name):
290-
self.cls = cls
291-
self.role_name = role_name
292-
self.user_relationship = None
293-
self.team_relationship = None
294-
self._active_sync_flag = False
295-
296-
def initialize(self, relationship):
297-
manager = getattr(self.cls, relationship)
298-
related_model_name = manager.field.related_model._meta.model_name
299-
if related_model_name == permission_registry.team_model._meta.model_name:
300-
self.team_relationship = relationship
301-
m2m_changed.connect(self.sync_team_to_role, sender=manager.through)
302-
elif related_model_name == permission_registry.user_model._meta.model_name:
303-
self.user_relationship = relationship
304-
m2m_changed.connect(self.sync_user_to_role, sender=manager.through)
305-
else:
306-
raise RuntimeError(f'Can only register user or team relationships, obtained {related_model_name}')
307-
308-
@contextmanager
309-
def sync_active(self):
310-
try:
311-
self._active_sync_flag = True
312-
yield
313-
finally:
314-
self._active_sync_flag = False
315-
316-
def sync_relationship(self, actor, content_object, giving=True):
317-
# Exit if role does not apply for the intended model type, for example
318-
# if user is given "team-member" role to organization, do not add user to the team members
319-
if content_object._meta.model_name != self.cls._meta.model_name:
320-
return
321-
322-
if actor._meta.model_name == permission_registry.team_model._meta.model_name:
323-
if self.team_relationship is None:
324-
return
325-
manager = getattr(content_object, self.team_relationship)
326-
elif actor._meta.model_name == permission_registry.user_model._meta.model_name:
327-
if self.user_relationship is None:
328-
return
329-
manager = getattr(content_object, self.user_relationship)
330-
331-
if giving:
332-
manager.add(actor)
333-
else:
334-
manager.remove(actor)
335-
336-
def _sync_actor_to_role(self, actor_model: type, instance: Model, action: str, pk_set: Optional[set[int]]):
337-
if self._active_sync_flag:
338-
return
339-
if action.startswith('pre_'):
340-
return
341-
rd = RoleDefinition.objects.get(name=self.role_name)
342-
343-
if action in ('post_add', 'post_remove'):
344-
actor_set = pk_set
345-
elif action == 'post_clear':
346-
ct = permission_registry.content_type_model.objects.get_for_model(instance)
347-
role = ObjectRole.objects.get(object_id=instance.pk, content_type=ct, role_definition=rd)
348-
if actor_model._meta.model_name == 'team':
349-
actor_set = set(role.teams.values_list('id', flat=True))
350-
else:
351-
actor_set = set(role.users.values_list('id', flat=True))
352-
353-
giving = bool(action == 'post_add')
354-
for actor in actor_model.objects.filter(pk__in=actor_set):
355-
rd.give_or_remove_permission(actor, instance, giving=giving, sync_action=True)
356-
357-
def sync_team_to_role(self, instance: Model, action: str, model: type, pk_set: Optional[set[int]], reverse: bool, **kwargs):
358-
if not reverse:
359-
self._sync_actor_to_role(permission_registry.team_model, instance, action, pk_set)
360-
else:
361-
for pk in pk_set:
362-
self._sync_actor_to_role(permission_registry.team_model, model(pk=pk), action, {instance.pk})
363-
364-
def sync_user_to_role(self, instance: Model, action: str, model: type, pk_set: Optional[set[int]], reverse: bool, **kwargs):
365-
if not reverse:
366-
self._sync_actor_to_role(permission_registry.user_model, instance, action, pk_set)
367-
else:
368-
for pk in pk_set:
369-
self._sync_actor_to_role(permission_registry.user_model, model(pk=pk), action, {instance.pk})
370-
371-
372287
def connect_rbac_signals(cls):
373288
if cls._meta.model_name == permission_registry.team_model._meta.model_name:
374289
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)