Skip to content

Commit 6a15b85

Browse files
committed
More optimizing
1 parent 978bd49 commit 6a15b85

File tree

7 files changed

+618
-7
lines changed

7 files changed

+618
-7
lines changed

ansible_base/rbac/api/views.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,20 @@ class RoleMetadataView(AnsibleBaseDjangoAppApiView, GenericAPIView):
6363
permission_classes = try_add_oauth2_scope_permission([permissions.IsAuthenticated])
6464
serializer_class = RoleMetadataSerializer
6565

66+
def __init__(self, *args, **kwargs):
67+
self.permission_cache = {}
68+
6669
def dispatch(self, request, *args, **kwargs):
6770
# Warm cache to avoid hits to basically all types from serializer
6871
DABContentType.objects.get_for_models(*permission_registry.all_registered_models)
6972
return super().dispatch(request, *args, **kwargs)
7073

74+
def get_for_codename(self, codename):
75+
if codename not in self.permission_cache:
76+
for permission in permission_registry.permission_qs.all():
77+
self.permission_cache[permission.codename] = permission
78+
return self.permission_cache[codename]
79+
7180
def get(self, request, format=None):
7281
data = OrderedDict()
7382
allowed_permissions = OrderedDict()
@@ -84,7 +93,7 @@ def get(self, request, format=None):
8493
cls_repr = f"{get_resource_prefix(cls)}.{cls._meta.model_name}"
8594
allowed_permissions[cls_repr] = []
8695
for codename in list_combine_values(permissions_allowed_for_role(cls)):
87-
perm = permission_registry.permission_qs.get(codename=codename)
96+
perm = self.get_for_codename(codename)
8897
ct = permission_registry.content_type_model.objects.get_for_id(perm.content_type_id)
8998
perm_repr = f"{get_resource_prefix(ct.model_class())}.{codename}"
9099
allowed_permissions[cls_repr].append(perm_repr)

ansible_base/rbac/service_api/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def perform_destroy(self, instance):
112112
class ServiceRoleUserAssignmentViewSet(BaseSerivceRoleAssignmentViewSet):
113113
"""List of user assignments for cross-service communication"""
114114

115-
queryset = RoleUserAssignment.objects.prefetch_related('user__resource', *prefetch_related)
115+
queryset = RoleUserAssignment.objects.prefetch_related('user__resource__content_type', 'content_object', *prefetch_related)
116116
serializer_class = service_serializers.ServiceRoleUserAssignmentSerializer
117117
filter_backends = AnsibleBaseDjangoAppApiView.filter_backends + [
118118
ansible_id_backend.UserAnsibleIdAliasFilterBackend,
@@ -131,7 +131,7 @@ def unassign(self, request):
131131
class ServiceRoleTeamAssignmentViewSet(BaseSerivceRoleAssignmentViewSet):
132132
"""List of team role assignments for cross-service communication"""
133133

134-
queryset = RoleTeamAssignment.objects.prefetch_related('team__resource', *prefetch_related)
134+
queryset = RoleTeamAssignment.objects.prefetch_related('team__resource__content_type', 'content_object', *prefetch_related)
135135
serializer_class = service_serializers.ServiceRoleTeamAssignmentSerializer
136136
filter_backends = AnsibleBaseDjangoAppApiView.filter_backends + [
137137
ansible_id_backend.TeamAnsibleIdAliasFilterBackend,

ansible_base/resource_registry/models/resource.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ def summary_fields(self):
9595

9696
@property
9797
def resource_type(self):
98+
# TODO: better optimize
9899
return resource_type_cache(self.content_type_id).name
99100

100101
@property

test_app/defaults.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@
143143

144144
USE_TZ = True
145145

146-
DEMO_DATA_COUNTS = {'organization': 150, 'user': 379, 'team': 43}
146+
DEMO_DATA_COUNTS = {'organization': 150, 'user': 379, 'team': 43, 'roledefinition': 100}
147147

148148
ANSIBLE_BASE_TEAM_MODEL = 'test_app.Team'
149149
ANSIBLE_BASE_ORGANIZATION_MODEL = 'test_app.Organization'

test_app/management/commands/create_demo_data.py

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from ansible_base.authentication.models import Authenticator, AuthenticatorUser
99
from ansible_base.oauth2_provider.models import OAuth2Application
1010
from ansible_base.rbac import permission_registry
11-
from ansible_base.rbac.models import DABContentType, RoleDefinition
11+
from ansible_base.rbac.models import DABContentType, DABPermission, RoleDefinition
1212
from test_app.models import EncryptionModel, InstanceGroup, Inventory, Organization, Team, User
1313

1414

@@ -20,6 +20,9 @@ def create_large(self, data_counts):
2020
start = time.time()
2121
self.stdout.write('')
2222
self.stdout.write('About to create large demo data set. This will take a while.')
23+
24+
# Create standard models first
25+
created_org_ids = []
2326
for cls in (Organization, Team, User):
2427
count = data_counts[cls._meta.model_name]
2528
for i in range(count):
@@ -28,9 +31,74 @@ def create_large(self, data_counts):
2831
if cls is User:
2932
data = {'username': name}
3033
elif cls is Team:
31-
data['organization_id'] = i + 1 # fudged, teams fewer than orgs
32-
cls.objects.create(**data)
34+
# Use actual created organization IDs, cycling through them
35+
if created_org_ids:
36+
data['organization_id'] = created_org_ids[i % len(created_org_ids)]
37+
else:
38+
raise ValueError("Teams cannot be created before organizations")
39+
obj = cls.objects.create(**data)
40+
# Collect organization IDs for team creation
41+
if cls is Organization:
42+
created_org_ids.append(obj.id)
3343
self.stdout.write(f'Created {count} {cls._meta.model_name}')
44+
45+
# Create RoleDefinitions with permissions
46+
if 'roledefinition' in data_counts:
47+
rd_count = data_counts['roledefinition']
48+
org_ct = DABContentType.objects.get_for_model(Organization)
49+
50+
for i in range(rd_count):
51+
# Create some sample permissions for each role definition
52+
perm1 = DABPermission.objects.create(name=f'Can view large role {i}', codename=f'view_large_role_{i}', content_type=org_ct)
53+
perm2 = DABPermission.objects.create(name=f'Can edit large role {i}', codename=f'edit_large_role_{i}', content_type=org_ct)
54+
55+
# Create role definition with Organization content type
56+
rd = RoleDefinition.objects.create(name=f'Large Role Definition {i}', description=f'Large demo role definition {i}', content_type=org_ct)
57+
58+
# Add permissions to the role definition
59+
rd.permissions.add(perm1, perm2)
60+
61+
self.stdout.write(f'Created {rd_count} role definitions with permissions')
62+
63+
# Create permission assignments for users and teams
64+
if created_org_ids and 'user' in data_counts and 'team' in data_counts:
65+
# Get created users and teams
66+
large_users = list(User.objects.filter(username__startswith='large_user_'))
67+
large_teams = list(Team.objects.filter(name__startswith='large_team_'))
68+
large_orgs = list(Organization.objects.filter(name__startswith='large_organization_'))
69+
large_rds = list(RoleDefinition.objects.filter(name__startswith='Large Role Definition'))
70+
71+
# Give over 25 permissions to users
72+
user_permissions_given = 0
73+
for user in large_users:
74+
for rd in large_rds:
75+
for org in large_orgs:
76+
rd.give_permission(user, org)
77+
user_permissions_given += 1
78+
if user_permissions_given >= 25:
79+
break
80+
if user_permissions_given >= 25:
81+
break
82+
if user_permissions_given >= 25:
83+
break
84+
85+
# Give over 25 permissions to teams
86+
team_permissions_given = 0
87+
for team in large_teams:
88+
for rd in large_rds:
89+
for org in large_orgs:
90+
rd.give_permission(team, org)
91+
team_permissions_given += 1
92+
if team_permissions_given >= 25:
93+
break
94+
if team_permissions_given >= 25:
95+
break
96+
if team_permissions_given >= 25:
97+
break
98+
99+
self.stdout.write(f'Assigned {user_permissions_given} permissions to users')
100+
self.stdout.write(f'Assigned {team_permissions_given} permissions to teams')
101+
34102
self.stdout.write(f'Finished creating large demo data in {time.time() - start:.2f} seconds')
35103

36104
def handle(self, *args, **kwargs):

0 commit comments

Comments
 (0)