Handle missing Organization Member/Admin role definitions gracefully

Use filter().first() instead of get() for RoleDefinition lookups in
organization list and detail views. Returns 0 for user/admin counts
when role definitions are not yet created, preventing 500 errors in
environments where post_migrate signals haven't run.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dirk Julich
2026-06-18 15:19:09 +02:00
parent be85b5b67f
commit 3bdb6362ad
2 changed files with 51 additions and 44 deletions

View File

@@ -179,27 +179,29 @@ class OrganizationCountsMixin(object):
db_results['projects'] = project_qs.values('organization').annotate(Count('organization')).order_by('organization') db_results['projects'] = project_qs.values('organization').annotate(Count('organization')).order_by('organization')
member_rd = RoleDefinition.objects.get(name='Organization Member') member_rd = RoleDefinition.objects.filter(name='Organization Member').first()
admin_rd = RoleDefinition.objects.get(name='Organization Admin') admin_rd = RoleDefinition.objects.filter(name='Organization Admin').first()
def assignment_count(rd): if member_rd and admin_rd:
return Coalesce(
Subquery(
RoleUserAssignment.objects.filter(
object_id=OuterRef('pk'),
role_definition=rd,
)
.values('role_definition')
.annotate(c=Count('pk'))
.values('c')
),
0,
)
db_results['users'] = org_qs.annotate( def assignment_count(rd):
users=assignment_count(member_rd), return Coalesce(
admins=assignment_count(admin_rd), Subquery(
).values('id', 'users', 'admins') RoleUserAssignment.objects.filter(
object_id=OuterRef('pk'),
role_definition=rd,
)
.values('role_definition')
.annotate(c=Count('pk'))
.values('c')
),
0,
)
db_results['users'] = org_qs.annotate(
users=assignment_count(member_rd),
admins=assignment_count(admin_rd),
).values('id', 'users', 'admins')
count_context = {} count_context = {}
for org in org_id_list: for org in org_id_list:

View File

@@ -79,36 +79,41 @@ class OrganizationDetail(RelatedJobsPreventDeleteMixin, RetrieveUpdateDestroyAPI
org_counts = {} org_counts = {}
access_kwargs = {'accessor': self.request.user, 'role_field': 'read_role'} access_kwargs = {'accessor': self.request.user, 'role_field': 'read_role'}
member_rd = RoleDefinition.objects.get(name='Organization Member') member_rd = RoleDefinition.objects.filter(name='Organization Member').first()
admin_rd = RoleDefinition.objects.get(name='Organization Admin') admin_rd = RoleDefinition.objects.filter(name='Organization Admin').first()
def assignment_count(rd): if member_rd and admin_rd:
return Coalesce(
Subquery( def assignment_count(rd):
RoleUserAssignment.objects.filter( return Coalesce(
object_id=OuterRef('pk'), Subquery(
role_definition=rd, RoleUserAssignment.objects.filter(
) object_id=OuterRef('pk'),
.values('role_definition') role_definition=rd,
.annotate(c=Count('pk')) )
.values('c') .values('role_definition')
), .annotate(c=Count('pk'))
0, .values('c')
),
0,
)
direct_counts = (
Organization.objects.filter(id=org_id)
.annotate(
users=assignment_count(member_rd),
admins=assignment_count(admin_rd),
)
.values('users', 'admins')
) )
direct_counts = ( if direct_counts:
Organization.objects.filter(id=org_id) org_counts = direct_counts[0]
.annotate( else:
users=assignment_count(member_rd), org_counts = {'users': 0, 'admins': 0}
admins=assignment_count(admin_rd),
)
.values('users', 'admins')
)
if not direct_counts: if not org_counts:
return full_context return full_context
org_counts = direct_counts[0]
org_counts['inventories'] = Inventory.accessible_objects(**access_kwargs).filter(organization__id=org_id).count() org_counts['inventories'] = Inventory.accessible_objects(**access_kwargs).filter(organization__id=org_id).count()
org_counts['teams'] = Team.accessible_objects(**access_kwargs).filter(organization__id=org_id).count() org_counts['teams'] = Team.accessible_objects(**access_kwargs).filter(organization__id=org_id).count()
org_counts['projects'] = Project.accessible_objects(**access_kwargs).filter(organization__id=org_id).count() org_counts['projects'] = Project.accessible_objects(**access_kwargs).filter(organization__id=org_id).count()