def get_permitted_minutes(minutes, request, groupid): groupid = int(groupid) try: group = Group.objects.get(id=groupid) except ObjectDoesNotExist: raise Http404 own_group = request.user.is_superuser or group in request.user.groups.all() # Prefetch group permissions group_checker = ObjectPermissionChecker(group) group_checker.prefetch_perms(minutes) # Prefetch user permissions user_checker = ObjectPermissionChecker(request.user) user_checker.prefetch_perms(minutes) # Prefetch ip group permissions ip_range_group_name = request.user._ip_range_group_name if hasattr(request.user, '_ip_range_group_name') else None if ip_range_group_name: ip_range_group = Group.objects.get(name=ip_range_group_name) ip_range_group_checker = ObjectPermissionChecker(ip_range_group) permitted_minutes = [] for m in minutes: # we show all documents for which the requested group has edit permissions # e.g. if you request FSR minutes, all minutes for which the FSR group has edit rights will be shown if not group_checker.has_perm(m.edit_permission_name, m): continue # we only show documents for which the user has view permissions if not user_checker.has_perm(MinutesDocument.get_view_permission(), m) and (not ip_range_group_name or not ip_range_group_checker.has_perm(MinutesDocument.get_view_permission(), m)): continue permitted_minutes.append(m) return permitted_minutes, own_group
def document_permission_overview(user, document): can_edit = user.has_perm(document.edit_permission_name, document) if not can_edit: return [] main_groups = [ settings.ANONYMOUS_GROUP_NAME, settings.UNIVERSITY_GROUP_NAME, settings.STUDENT_GROUP_NAME, settings.STAFF_GROUP_NAME, ] permissions = [] for group_name in main_groups: group = Group.objects.get(name=group_name) checker = ObjectPermissionChecker(group) checker.prefetch_perms([document]) if checker.has_perm(document.edit_permission_name, document): permissions.append((group.name, "edit")) elif checker.has_perm(document.view_permission_name, document): permissions.append((group.name, "view")) else: permissions.append((group.name, "none")) for group in Group.objects.exclude(name__in=main_groups): checker = ObjectPermissionChecker(group) checker.prefetch_perms([document]) if checker.has_perm(document.edit_permission_name, document): permissions.append((group.name, "edit")) elif checker.has_perm(document.view_permission_name, document): permissions.append((group.name, "view")) return permissions
def bulk_assign_perm(self, perm, user_or_group, queryset): """ Bulk assigns permissions with given ``perm`` for an objects in ``queryset`` and ``user_or_group``. """ ctype = get_content_type(queryset.model) if not isinstance(perm, Permission): permission = Permission.objects.get(content_type=ctype, codename=perm) else: permission = perm checker = ObjectPermissionChecker(user_or_group) checker.prefetch_perms(queryset) assigned_perms = [] for instance in queryset: if not checker.has_perm(permission.codename, instance): kwargs = {'permission': permission, self.user_or_group_field: user_or_group} if self.is_generic(): kwargs['content_type'] = ctype kwargs['object_pk'] = instance.pk else: kwargs['content_object'] = instance assigned_perms.append(self.model(**kwargs)) self.model.objects.bulk_create(assigned_perms) return assigned_perms
def test_copyannotations_command_doesnt_add_permissions( self, AnnotationSet): user_from = AnnotationSet.grader user_to = UserFactory() call_command( "copyannotations", user_from.username, user_to.username, add_permissions=False, stdout=None, # suppress output ) checker = ObjectPermissionChecker(user_to) for model, _ in self.annotations: model_instance = model.objects.get(grader=user_to) children = [] if model == PolygonAnnotationSet: children = model_instance.singlepolygonannotation_set.all() if model == LandmarkAnnotationSet: children = model_instance.singlelandmarkannotation_set.all() perms = checker.get_perms(model_instance) assert len(perms) == 0 if children: checker.prefetch_perms(children) for child in children: perms = checker.get_perms(child) assert len(perms) == 0
def terminator_profile_detail(request, username): user = get_object_or_404(User, username=username) cil_ctype = ContentType.objects.get_for_model(ConceptInLanguage) user_comments = Comment.objects.filter( user=user, content_type=cil_ctype, is_public=True, is_removed=False, ).order_by('-submit_date') paginator = Paginator(user_comments, 10) # Make sure page request is an int. If not, deliver first page. try: page = int(request.GET.get('page', '1')) except ValueError: page = 1 # If page request (9999) is out of range, deliver last page of results. try: comments = paginator.page(page) except (EmptyPage, InvalidPage): comments = paginator.page(paginator.num_pages) prefetch_related_objects( comments.object_list, 'content_object__concept', 'content_object__concept__glossary', ) glossary_list = list(Glossary.objects.all()) user_glossaries = [] checker = ObjectPermissionChecker(user) checker.prefetch_perms(glossary_list) for glossary in glossary_list: if checker.has_perm('owner', glossary): user_glossaries.append({'glossary': glossary, 'role': _(u"owner")}) elif checker.has_perm('terminologist', glossary): user_glossaries.append({ 'glossary': glossary, 'role': _(u"terminologist") }) elif checker.has_perm('specialist', glossary): user_glossaries.append({ 'glossary': glossary, 'role': _(u"specialist") }) ctypes = ContentType.objects.get_for_models(Translation, Definition, ExternalResource).values() recent_changes = process_recent_changes( LogEntry.objects.filter( content_type__in=ctypes, user=user, ).order_by("-action_time")[:10]) context = { 'thisuser': user, 'glossaries': user_glossaries, 'comments': comments, 'search_form': SearchForm(), 'next': request.get_full_path(), 'recent_changes': recent_changes, } return render(request, "profiles/profile_detail.html", context)
def get_classes(user: "******"): """Get the classes whose timetables are allowed to be seen by current user.""" checker = ObjectPermissionChecker(user) classes = (Group.objects.for_current_school_term_or_all().annotate( lessons_count=Count("lessons"), child_lessons_count=Count("child_groups__lessons"), ).filter( Q(lessons_count__gt=0, parent_groups=None) | Q(child_lessons_count__gt=0, parent_groups=None)).order_by( "short_name", "name")) if not check_global_permission(user, "chronos.view_all_group_timetables"): checker.prefetch_perms(classes) wanted_classes = set() for _class in classes: if checker.has_perm("core.view_group_timetable", _class): wanted_classes.add(_class.pk) classes = classes.filter( Q(pk__in=wanted_classes) | Q(members=user.person) | Q(owners=user.person)) if user.person.primary_group: classes = classes.filter(Q(pk=user.person.primary_group.pk)) return classes
def test_copyannotations_command_adds_permissions(self, annotation_set): user_from = annotation_set.grader user_to = UserFactory() call_command( "copyannotations", user_from.username, user_to.username, stdout=None, # suppress output ) checker = ObjectPermissionChecker(user_to) for model, _ in self.annotations: model_instance = model.objects.get(grader=user_to) children = [] if model == PolygonAnnotationSet: children = model_instance.singlepolygonannotation_set.all() if model == LandmarkAnnotationSet: children = model_instance.singlelandmarkannotation_set.all() perms = checker.get_perms(model_instance) for permission_type in model._meta.default_permissions: assert f"{permission_type}_{model._meta.model_name}" in perms if children: checker.prefetch_perms(children) for child in children: perms = checker.get_perms(child) child_model_name = children.first()._meta.model_name for permission_type in child._meta.default_permissions: assert f"{permission_type}_{child_model_name}" in perms
def test_copyannotations_command_doesnt_add_permissions( self, AnnotationSet ): user_from = AnnotationSet.grader user_to = UserFactory() call_command( "copyannotations", user_from.username, user_to.username, add_permissions=False, stdout=None, # suppress output ) checker = ObjectPermissionChecker(user_to) for model, _ in self.annotations: model_instance = model.objects.get(grader=user_to) children = [] if model == PolygonAnnotationSet: children = model_instance.singlepolygonannotation_set.all() if model == LandmarkAnnotationSet: children = model_instance.singlelandmarkannotation_set.all() perms = checker.get_perms(model_instance) assert len(perms) == 0 if children: checker.prefetch_perms(children) for child in children: perms = checker.get_perms(child) assert len(perms) == 0
def test_copyannotations_command_adds_permissions(self, AnnotationSet): user_from = AnnotationSet.grader user_to = UserFactory() call_command( "copyannotations", user_from.username, user_to.username, stdout=None, # suppress output ) checker = ObjectPermissionChecker(user_to) for model, _ in self.annotations: model_instance = model.objects.get(grader=user_to) children = [] if model == PolygonAnnotationSet: children = model_instance.singlepolygonannotation_set.all() if model == LandmarkAnnotationSet: children = model_instance.singlelandmarkannotation_set.all() perms = checker.get_perms(model_instance) for permission_type in model._meta.default_permissions: assert f"{permission_type}_{model._meta.model_name}" in perms if children: checker.prefetch_perms(children) for child in children: perms = checker.get_perms(child) child_model_name = children.first()._meta.model_name for permission_type in child._meta.default_permissions: assert f"{permission_type}_{child_model_name}" in perms
def get_serializer_context(self): context = super().get_serializer_context() queryset = self.get_queryset() if queryset: prefetched_permission_checker = ObjectPermissionChecker(self.request.user) prefetched_permission_checker.prefetch_perms(queryset) context['prefetched_permission_checker'] = prefetched_permission_checker return context
def get_last_minutes_document_for_group(group): minutes = MinutesDocument.objects.all().order_by('-date') group_checker = ObjectPermissionChecker(group) group_checker.prefetch_perms(minutes) for m in minutes: if group_checker.has_perm(m.edit_permission_name, m): return m return None
def get_queryset_for_customer(self): created_time = self.request.query_params.get('created_time', None) if created_time: self.kwargs['created_time__contains'] = created_time queryset = Order.objects.filter(**self.kwargs) checker = ObjectPermissionChecker(self.request.user) checker.prefetch_perms(queryset) return [ query for query in queryset if checker.has_perm('app.view_order', query) ]
class UnitAuthorizationFormSet(forms.BaseInlineFormSet): def __init__(self, *args, **kwargs): self.request = kwargs.pop('request', None) super().__init__(*args, **kwargs) self.permission_checker = ObjectPermissionChecker(kwargs['instance']) self.permission_checker.prefetch_perms( Unit.objects.filter(authorizations__authorized=kwargs['instance'])) def get_form_kwargs(self, index): kwargs = super().get_form_kwargs(index) kwargs['permission_checker'] = self.permission_checker kwargs['request'] = self.request return kwargs
def _preload_permissions(self): units = set() resource_groups = set() checker = ObjectPermissionChecker(self.request.user) for res in self._page: units.add(res.unit) for g in res.groups.all(): resource_groups.add(g) res._permission_checker = checker if units: checker.prefetch_perms(units) if resource_groups: checker.prefetch_perms(resource_groups)
def create_permission_checker(model_or_manager, user): """ Create an :class:`ObjectPermissionChecker` for optimal permission checking of related objects. http://django-guardian.readthedocs.io/en/stable/userguide/performance.html """ model, manager = model_and_manager(model_or_manager) checker = ObjectPermissionChecker(user) try: checker.prefetch_perms(manager) except UnboundLocalError: logger.exception( "https://github.com/django-guardian/django-guardian/issues/519") return checker
def __init__(self, request: HttpRequest, *args, **kwargs): super().__init__(*args, **kwargs) # Disable non-editable fields person_fields = set([field.name for field in Person.syncable_fields() ]).intersection(set(self.fields)) if self.instance: checker = ObjectPermissionChecker(request.user) checker.prefetch_perms([self.instance]) for field in person_fields: if not checker.has_perm(f"core.change_person_field_{field}", self.instance): self.fields[field].disabled = True
def test_prefetch_group_perms(self): settings.DEBUG = True try: from django.db import connection ContentType.objects.clear_cache() new_group = Group.objects.create(name='new-group') assign_perm("change_group", new_group, self.group) assign_perm("change_group", new_group, new_group) checker = ObjectPermissionChecker(new_group) # Prefetch permissions self.assertTrue(checker.prefetch_perms([self.group, new_group])) query_count = len(connection.queries) # Checking cache is filled self.assertEqual(len(checker._obj_perms_cache), 2) # Checking shouldn't spawn any queries checker.has_perm("change_group", self.group) self.assertEqual(len(connection.queries), query_count) # Checking for other permission but for Group object again # shouldn't spawn any query too checker.has_perm("delete_group", self.group) self.assertEqual(len(connection.queries), query_count) # Checking for same model but other instance shouldn't spawn any queries checker.has_perm("change_group", new_group) self.assertEqual(len(connection.queries), query_count) finally: settings.DEBUG = False
def test_checker(self): GroupObjectPermission.objects.assign_perm("delete_contenttype", self.group, self.ctype) checker = ObjectPermissionChecker(self.user) checker.prefetch_perms(Group.objects.all()) template = ''.join(( '{% load guardian_tags %}', '{% get_obj_perms group for contenttype as "obj_perms" checker %}', '{{ obj_perms|join:" " }}', )) context = {'group': self.group, 'contenttype': self.ctype, 'checker': checker} output = render(template, context) self.assertEqual(output, 'delete_contenttype')
def get_user_perms(self, user, object_list): checker = ObjectPermissionChecker(user) checker.prefetch_perms(object_list) perms = [] for obj in object_list: perms.extend([ ':'.join([ perm, str(obj.pk) ]) for perm in checker.get_perms(obj) ]) return perms
def list(request, groupid): groupid = int(groupid) try: group = Group.objects.get(id=groupid) except ObjectDoesNotExist: raise Http404 result = {} own_group = request.user.is_superuser or group in request.user.groups.all() minutes = MinutesDocument.objects.all().prefetch_related( 'labels').order_by('-date') # Prefetch group permissions group_checker = ObjectPermissionChecker(group) group_checker.prefetch_perms(minutes) # Prefetch user permissions user_checker = ObjectPermissionChecker(request.user) user_checker.prefetch_perms(minutes) # Prefetch ip group permissions ip_range_group_name = request.user._ip_range_group_name if hasattr( request.user, '_ip_range_group_name') else None if ip_range_group_name: ip_range_group = Group.objects.get(name=ip_range_group_name) ip_range_group_checker = ObjectPermissionChecker(ip_range_group) for m in minutes: # we show all documents for which the requested group has edit permissions # e.g. if you request FSR minutes, all minutes for which the FSR group has edit rights will be shown if not group_checker.has_perm(m.edit_permission_name, m): continue # we only show documents for which the user has view permissions if not user_checker.has_perm( MinutesDocument.get_view_permission(), m) and (not ip_range_group_name or not ip_range_group_checker.has_perm( MinutesDocument.get_view_permission(), m)): continue if m.date.year not in result: result[m.date.year] = [] result[m.date.year].append(m) return render( request, "minutes_list.html", { 'minutes_list': sorted(result.items(), reverse=True), 'own_group': own_group })
def get_rooms(user: "******"): """Get the rooms whose timetables are allowed to be seen by current user.""" checker = ObjectPermissionChecker(user) rooms = (Room.objects.annotate( lessons_count=Count("lesson_periods")).filter( lessons_count__gt=0).order_by("short_name", "name")) if not check_global_permission(user, "chronos.view_all_room_timetables"): checker.prefetch_perms(rooms) wanted_rooms = set() for room in rooms: if checker.has_perm("chronos.view_room_timetable", room): wanted_rooms.add(room.pk) rooms = rooms.filter(Q(pk__in=wanted_rooms)) return rooms
def user_dashboard(request): joe = User.objects.get(username='******') post = Post.objects.get(id=1) # print(joe.has_perm('post_add', post)) assign_perm('post_add', joe, post) projects = get_objects_for_user(request.user, 'ecommer.post_add') from guardian.core import ObjectPermissionChecker joe = User.objects.get(username='******') projects = Post.objects.all() checker = ObjectPermissionChecker(joe) # Prefetch the permissions checker.prefetch_perms(projects) for project in projects: # No additional lookups needed to check permissions print(checker.has_perm('post_add', project)) return render(request, 'ecommer/user_dashboard.html', {'projects': projects})
def get_teachers(user: "******"): """Get the teachers whose timetables are allowed to be seen by current user.""" checker = ObjectPermissionChecker(user) teachers = (Person.objects.annotate( lessons_count=Count("lessons_as_teacher")).filter( lessons_count__gt=0).order_by("short_name", "last_name")) if not check_global_permission(user, "chronos.view_all_person_timetables"): checker.prefetch_perms(teachers) wanted_teachers = set() for teacher in teachers: if checker.has_perm("core.view_person_timetable", teacher): wanted_teachers.add(teacher.pk) teachers = teachers.filter( Q(pk=user.person.pk) | Q(pk__in=wanted_teachers)) return teachers
def list(request, groupid): groupid = int(groupid) try: group = Group.objects.get(id=groupid) except ObjectDoesNotExist: raise Http404 result = {} own_group = request.user.is_superuser or group in request.user.groups.all() minutes = MinutesDocument.objects.all().prefetch_related('labels').order_by('-date') # Prefetch group permissions group_checker = ObjectPermissionChecker(group) group_checker.prefetch_perms(minutes) # Prefetch user permissions user_checker = ObjectPermissionChecker(request.user) user_checker.prefetch_perms(minutes) # Prefetch ip group permissions ip_range_group_name = request.user._ip_range_group_name if hasattr(request.user, '_ip_range_group_name') else None if ip_range_group_name: ip_range_group = Group.objects.get(name=ip_range_group_name) ip_range_group_checker = ObjectPermissionChecker(ip_range_group) for m in minutes: # we show all documents for which the requested group has edit permissions # e.g. if you request FSR minutes, all minutes for which the FSR group has edit rights will be shown if not group_checker.has_perm(m.edit_permission_name, m): continue # we only show documents for which the user has view permissions if not user_checker.has_perm(MinutesDocument.get_view_permission(), m) and (not ip_range_group_name or not ip_range_group_checker.has_perm(MinutesDocument.get_view_permission(), m)): continue if m.date.year not in result: result[m.date.year] = [] result[m.date.year].append(m) return render(request, "minutes_list.html", { 'minutes_list': sorted(result.items(), reverse=True), 'own_group': own_group })
def list(self, request, *args, **kwargs): # Copy-paste of old implementation queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True) # Add user permissions perms_checker = ObjectPermissionChecker(request.user) perms_checker.prefetch_perms(queryset) response_data = serializer.data for idx, obj in enumerate(queryset): response_data[idx]['permissions'] = perms_checker.get_perms(obj) return Response(response_data)
def get_context_data(self, *, object_list=None, **kwargs): context = super().get_context_data() checker = ObjectPermissionChecker(user_or_group=self.request.user) for qs in [ Archive.objects.only("pk").all(), ReaderStudy.objects.only("pk").all(), Challenge.objects.only("pk").all(), Algorithm.objects.only("pk").all(), ExternalChallenge.objects.only("pk").all(), ]: # Perms can only be prefetched for sets of the same objects checker.prefetch_perms(objects=qs) context.update({ "checker": checker, "num_citations": self.get_queryset().exclude( referenced_by_count__isnull=True).aggregate( Sum("referenced_by_count"))["referenced_by_count__sum"], }) return context
def get_permissions(user_or_group: Union[User, Group], object_list: QuerySet) -> List[ObjectPermission]: permissions = [] perm_checker = ObjectPermissionChecker(user_or_group) perm_checker.prefetch_perms(object_list) opts = object_list.model._meta perm_view = get_permission_codename('view', opts) perm_change = get_permission_codename('change', opts) perm_delete = get_permission_codename('delete', opts) for obj in object_list: permissions.append( ObjectPermission( obj=obj, can_view=perm_checker.has_perm(perm_view, obj), can_change=perm_checker.has_perm(perm_change, obj), can_delete=perm_checker.has_perm(perm_delete, obj), ) ) return permissions
def test_prefetch_group_perms(self): settings.DEBUG = True try: from django.db import connection ContentType.objects.clear_cache() group1 = Group.objects.create(name='group1') group2 = Group.objects.create(name='group2') assign_perm("change_group", group1, self.group) assign_perm("change_group", group1, group1) checker = ObjectPermissionChecker(group1) # Prefetch permissions prefetched_objects = [self.group, group1, group2] self.assertTrue(checker.prefetch_perms(prefetched_objects)) query_count = len(connection.queries) # Checking cache is filled self.assertEqual( len(checker._obj_perms_cache), len(prefetched_objects) ) # Checking shouldn't spawn any queries checker.has_perm("change_group", self.group) self.assertEqual(len(connection.queries), query_count) # Checking for other permission but for Group object again # shouldn't spawn any query too checker.has_perm("delete_group", self.group) self.assertEqual(len(connection.queries), query_count) # Checking for same model but other instance shouldn't spawn any queries checker.has_perm("change_group", group1) self.assertEqual(len(connection.queries), query_count) # Checking for same model but other instance shouldn't spawn any queries # Even though User doesn't have perms on Group2, we still should # not hit DB self.assertFalse(checker.has_perm("change_group", group2)) self.assertEqual(len(connection.queries), query_count) finally: settings.DEBUG = False
def test_prefetch_group_perms_direct_rel(self): settings.DEBUG = True try: from django.db import connection ContentType.objects.clear_cache() group = Group.objects.create(name='new-group') projects = \ [Project.objects.create(name='Project%s' % i) for i in range(3)] assign_perm("change_project", group, projects[0]) assign_perm("change_project", group, projects[1]) checker = ObjectPermissionChecker(group) # Prefetch permissions self.assertTrue(checker.prefetch_perms(projects)) query_count = len(connection.queries) # Checking cache is filled self.assertEqual(len(checker._obj_perms_cache), len(projects)) # Checking shouldn't spawn any queries checker.has_perm("change_project", projects[0]) self.assertEqual(len(connection.queries), query_count) # Checking for other permission but for Group object again # shouldn't spawn any query too checker.has_perm("delete_project", projects[0]) self.assertEqual(len(connection.queries), query_count) # Checking for same model but other instance shouldn't spawn any # queries checker.has_perm("change_project", projects[1]) self.assertEqual(len(connection.queries), query_count) # Checking for same model but other instance shouldn't spawn any queries # Even though User doesn't have perms on projects[2], we still # should not hit DB self.assertFalse(checker.has_perm("change_project", projects[2])) self.assertEqual(len(connection.queries), query_count) finally: settings.DEBUG = False
def test_prefetch_superuser_perms_direct_rel(self): settings.DEBUG = True try: from django.db import connection ContentType.objects.clear_cache() user = User.objects.create(username='******', is_active=True, is_superuser=True) projects = \ [Project.objects.create(name='Project%s' % i) for i in range(2)] for project in projects: assign_perm("change_project", user, project) checker = ObjectPermissionChecker(user) # Prefetch permissions self.assertTrue(checker.prefetch_perms(projects)) query_count = len(connection.queries) # Checking cache is filled self.assertEqual(len(checker._obj_perms_cache), 2) # Checking shouldn't spawn any queries checker.has_perm("change_project", projects[0]) self.assertEqual(len(connection.queries), query_count) # Checking for other permission but for Group object again # shouldn't spawn any query too checker.has_perm("delete_project", projects[0]) self.assertEqual(len(connection.queries), query_count) # Checking for same model but other instance shouldn't spawn any # queries checker.has_perm("change_project", projects[1]) self.assertEqual(len(connection.queries), query_count) finally: settings.DEBUG = False
def test_prefetch_superuser_perms_direct_rel(self): settings.DEBUG = True try: from django.db import connection ContentType.objects.clear_cache() user = User.objects.create( username='******', is_active=True, is_superuser=True) projects = \ [Project.objects.create(name='Project%s' % i) for i in range(2)] for project in projects: assign_perm("change_project", user, project) checker = ObjectPermissionChecker(user) # Prefetch permissions self.assertTrue(checker.prefetch_perms(projects)) query_count = len(connection.queries) # Checking cache is filled self.assertEqual(len(checker._obj_perms_cache), 2) # Checking shouldn't spawn any queries checker.has_perm("change_project", projects[0]) self.assertEqual(len(connection.queries), query_count) # Checking for other permission but for Group object again # shouldn't spawn any query too checker.has_perm("delete_project", projects[0]) self.assertEqual(len(connection.queries), query_count) # Checking for same model but other instance shouldn't spawn any # queries checker.has_perm("change_project", projects[1]) self.assertEqual(len(connection.queries), query_count) finally: settings.DEBUG = False
def test_prefetch_superuser_perms(self): settings.DEBUG = True try: from django.db import connection ContentType.objects.clear_cache() group1 = Group.objects.create(name='group1') user = User.objects.create(username='******', is_superuser=True, is_active=True) assign_perm("change_group", user, self.group) checker = ObjectPermissionChecker(user) # Prefetch permissions prefetched_objects = [self.group, group1] self.assertTrue(checker.prefetch_perms(prefetched_objects)) query_count = len(connection.queries) # Checking cache is filled self.assertEqual( len(checker._obj_perms_cache), len(prefetched_objects) ) # Checking shouldn't spawn any queries checker.has_perm("change_group", self.group) self.assertEqual(len(connection.queries), query_count) # Checking for other permission but for Group object again # shouldn't spawn any query too checker.has_perm("delete_group", self.group) self.assertEqual(len(connection.queries), query_count) # Checking for same model but other instance shouldn't spawn any queries checker.has_perm("change_group", group1) self.assertEqual(len(connection.queries), query_count) finally: settings.DEBUG = False
def get_all_permissions(user, object_list): checker = ObjectPermissionChecker(user) checker.prefetch_perms(object_list) return {obj.pk: checker.get_perms(obj) for obj in object_list}
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) profile_user = context["object"].user profile_groups = profile_user.groups.all() organizations = Organization.objects.filter( Q(members_group__in=profile_groups) | Q(editors_group__in=profile_groups)).distinct() archives = (get_objects_for_user( user=self.request.user, perms="view_archive", klass=Archive, use_groups=True, ).filter( Q(editors_group__in=profile_groups) | Q(uploaders_group__in=profile_groups) | Q(users_group__in=profile_groups)).distinct()) reader_studies = (get_objects_for_user( user=self.request.user, perms="view_readerstudy", klass=ReaderStudy, use_groups=True, ).filter( Q(editors_group__in=profile_groups) | Q(readers_group__in=profile_groups)).distinct()) challenges = Challenge.objects.filter( Q(admins_group__in=profile_groups) | Q(participants_group__in=profile_groups), hidden=False, ).distinct() algorithms = (get_objects_for_user( user=self.request.user, perms="view_algorithm", klass=Algorithm, use_groups=True, ).filter( Q(editors_group__in=profile_groups) | Q(users_group__in=profile_groups)).distinct()) checker = ObjectPermissionChecker(user_or_group=profile_user) for qs in [ archives, reader_studies, challenges, algorithms, ]: # Perms can only be prefetched for sets of the same objects checker.prefetch_perms(objects=qs) object_list = [ *archives, *reader_studies, *challenges, *algorithms, ] role = {} for obj in object_list: obj_perms = checker.get_perms(obj) if f"change_{obj._meta.model_name}" in obj_perms: role[obj] = "editor" elif f"view_{obj._meta.model_name}" in obj_perms: role[obj] = "user" else: role[obj] = "participant" context.update({ "object_list": object_list, "object_role": role, "num_submissions": Submission.objects.filter(creator=profile_user).count(), "num_algorithms_run": Job.objects.filter(creator=profile_user).count(), "organizations": organizations, }) return context