def get_user_sites_queryset(user): """ Returns queryset of all sites available for given user. 1. For superuser always returns all sites. 2. For global user returns all sites he haves in global page permissions together with any sites he is assigned to over an page. 3. For standard user returns just sites he is assigned to over pages. """ qs = Site.objects.all() if user.is_superuser: return qs global_ids = ( GlobalPagePermission.objects.with_user(user) .filter(Q(can_add=True) | Q(can_change=True)) .values_list("id", flat=True) ) query = Q() if global_ids: query = Q(globalpagepermission__id__in=global_ids) # haves some global permissions assigned if not qs.filter(query).exists(): # haves global permissions, but none of sites is specified, # so he haves access to all sites return qs # add some pages if he has permission to add / change them query |= Q( Q(page__pagepermission__user=user) | Q(**{get_user_related_through_group("page__pagepermission__group"): user}) ) & (Q(Q(page__pagepermission__can_add=True) | Q(page__pagepermission__can_change=True))) return qs.filter(query).distinct()
def get_visible_pages(request, pages, site=None): """ This code is basically a many-pages-at-once version of Page.has_view_permission. pages contains all published pages check if there is ANY restriction that needs a permission page visibility calculation """ public_for = get_cms_setting('PUBLIC_FOR') is_setting_public_all = public_for == 'all' is_setting_public_staff = public_for == 'staff' is_auth_user = request.user.is_authenticated() visible_page_ids = [] restricted_pages = defaultdict(list) page_permissions = PagePermission.objects.filter(can_view=True).select_related('page', get_user_related_through_group('group')) for perm in page_permissions: # collect the pages that are affected by permissions if site and perm.page.site_id != site.pk: continue if perm is not None and perm not in restricted_pages[perm.page.pk]: # affective restricted pages gathering # using mptt functions # add the page with the perm itself if perm.grant_on in [ACCESS_PAGE, ACCESS_PAGE_AND_CHILDREN, ACCESS_PAGE_AND_DESCENDANTS]: restricted_pages[perm.page.pk].append(perm) restricted_pages[perm.page.publisher_public_id].append(perm) # add children if perm.grant_on in [ACCESS_CHILDREN, ACCESS_PAGE_AND_CHILDREN]: child_ids = perm.page.get_children().values_list('id', 'publisher_public_id') for id, public_id in child_ids: restricted_pages[id].append(perm) restricted_pages[public_id].append(perm) # add descendants elif perm.grant_on in [ACCESS_DESCENDANTS, ACCESS_PAGE_AND_DESCENDANTS]: child_ids = perm.page.get_descendants().values_list('id', 'publisher_public_id') for id, public_id in child_ids: restricted_pages[id].append(perm) restricted_pages[public_id].append(perm) # anonymous # no restriction applied at all if (not is_auth_user and is_setting_public_all and not restricted_pages): return [page.pk for page in pages] if site is None: site = current_site(request) # authenticated user and global permission if is_auth_user: global_page_perm_q = Q( Q(user=request.user) | Q(**{get_user_related_through_group('group'): request.user}) ) & Q(can_view=True) & Q(Q(sites__in=[site.pk]) | Q(sites__isnull=True)) global_view_perms = GlobalPagePermission.objects.filter(global_page_perm_q).exists() #no page perms edge case - all visible if ((is_setting_public_all or ( is_setting_public_staff and request.user.is_staff)) and not restricted_pages and not global_view_perms): return [page.pk for page in pages] #no page perms edge case - none visible elif (is_setting_public_staff and not request.user.is_staff and not restricted_pages and not global_view_perms): return [] def has_global_perm(): if has_global_perm.cache < 0: has_global_perm.cache = 1 if request.user.has_perm('cms.view_page') else 0 return bool(has_global_perm.cache) has_global_perm.cache = -1 def has_permission_membership(page): """ PagePermission user group membership tests """ user_pk = request.user.pk page_pk = page.pk has_perm = False for perm in restricted_pages[page_pk]: if perm.user_id == user_pk: has_perm = True if not perm.group_id: continue group_user_ids = perm.group.user_set.values_list('pk', flat=True) if user_pk in group_user_ids: has_perm = True return has_perm for page in pages: to_add = False # default to false, showing a restricted page is bad # explicitly check all the conditions # of settings and permissions is_restricted = page.pk in restricted_pages # restricted_pages contains as key any page.pk that is # affected by a permission grant_on if is_auth_user: # a global permission was given to the request's user if global_view_perms: to_add = True # setting based handling of unrestricted pages elif not is_restricted and ( is_setting_public_all or ( is_setting_public_staff and request.user.is_staff) ): # authenticated user, no restriction and public for all # or # authenticated staff user, no restriction and public for staff to_add = True # check group and user memberships to restricted pages elif is_restricted and has_permission_membership(page): to_add = True elif has_global_perm(): to_add = True # anonymous user, no restriction elif not is_restricted and is_setting_public_all: to_add = True # store it if to_add: visible_page_ids.append(page.pk) return visible_page_ids
def with_user(self, user): """Get all objects for given user, also takes look if user is in some group. """ return self.filter(Q(user=user) | Q(**{get_user_related_through_group('group'): user}))