def get_visible_page_objects(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') can_see_unrestricted = public_for == 'all' or (public_for == 'staff' and request.user.is_staff) is_auth_user = request.user.is_authenticated() restricted_pages = load_view_restrictions(request, pages) if not restricted_pages: if can_see_unrestricted: return pages elif not is_auth_user: return [ ] # Unauth user can't acquire global or user perm to see pages if get_cms_setting('PERMISSION') and not site: site = current_site(request) # avoid one extra query when possible if has_global_page_permission(request, site, can_view=True): return pages has_global_perm = SimpleLazyObject( lambda: request.user.has_perm('cms.view_page')) user_groups = SimpleLazyObject( lambda: set(request.user.groups.values_list('pk', flat=True))) def has_permission_membership(page_id): """ PagePermission user group membership tests """ user_pk = request.user.pk for perm in restricted_pages[page_id]: if perm.user_id == user_pk or perm.group_id in user_groups: return True return False visible_pages = [] for page in pages: to_add = False page_id = page.pk is_restricted = page_id in restricted_pages # restricted_pages contains as key any page.pk that is # affected by a permission grant_on if not is_restricted and can_see_unrestricted: to_add = True elif is_auth_user: # setting based handling of unrestricted pages # check group and user memberships to restricted pages if is_restricted and has_permission_membership( page_id) or has_global_perm: to_add = True if to_add: visible_pages.append(page) return visible_pages
def get_visible_page_objects(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') can_see_unrestricted = public_for == 'all' or ( public_for == 'staff' and request.user.is_staff) is_auth_user = request.user.is_authenticated() restricted_pages = load_view_restrictions(request, pages) if not restricted_pages: if can_see_unrestricted: return pages elif not is_auth_user: return [] # Unauth user can't acquire global or user perm to see pages if get_cms_setting('PERMISSION') and not site: site = current_site(request) # avoid one extra query when possible if has_global_page_permission(request, site, can_view=True): return pages has_global_perm = SimpleLazyObject(lambda: request.user.has_perm('cms.view_page')) user_groups = SimpleLazyObject(lambda: set(request.user.groups.values_list('pk', flat=True))) def has_permission_membership(page_id): """ PagePermission user group membership tests """ user_pk = request.user.pk for perm in restricted_pages[page_id]: if perm.user_id == user_pk or perm.group_id in user_groups: return True return False visible_pages = [] for page in pages: to_add = False page_id = page.pk is_restricted = page_id in restricted_pages # restricted_pages contains as key any page.pk that is # affected by a permission grant_on if not is_restricted and can_see_unrestricted: to_add = True elif is_auth_user: # setting based handling of unrestricted pages # check group and user memberships to restricted pages if is_restricted and has_permission_membership(page_id) or has_global_perm: to_add = True if to_add: visible_pages.append(page) return visible_pages
def set_items(self, request): site = self.current_site() # Get all the pages, ordered by tree ID (it's convenient to build the # tree using a stack now) pages = self.get_query_set(request).drafts().order_by( 'tree_id', 'lft').select_related() # Get lists of page IDs for which the current user has # "permission to..." on the current site. perm_edit_ids = Page.permissions.get_change_id_list(request.user, site) perm_publish_ids = Page.permissions.get_publish_id_list( request.user, site) perm_advanced_settings_ids = Page.permissions.get_advanced_settings_id_list( request.user, site) perm_change_list_ids = Page.permissions.get_change_id_list( request.user, site) if perm_edit_ids and perm_edit_ids != Page.permissions.GRANT_ALL: pages = pages.filter(pk__in=perm_edit_ids) #pages = pages.filter(pk__in=perm_change_list_ids) root_pages = [] # Cache view restrictions for the is_restricted template tag load_view_restrictions(request, pages) pages = list(pages) all_pages = pages[:] # That is, basically, a copy. try: home_pk = Page.objects.drafts().get_home(site).pk except NoHomeFound: home_pk = 0 # page moderator states pm_qs = PageModeratorState.objects.filter( page__in=pages).order_by('page') pm_states = defaultdict(list) for state in pm_qs: pm_states[state.page_id].append(state) public_page_id_set = Page.objects.public().filter( published=True, publisher_public__in=pages).values_list('id', flat=True) # Unfortunately we cannot use the MPTT builtin code for pre-caching # the children here, because MPTT expects the tree to be 'complete' # and otherwise complaints about 'invalid item order' cache_tree_children(pages) ids = dict((page.id, page) for page in pages) for page in pages: children = list(page.get_children()) # If the parent page is not among the nodes shown, this node should # be a "root node". The filtering for this has already been made, so # using the ids dictionary means this check is constant time page.root_node = page.parent_id not in ids if get_cms_setting('PERMISSION'): # caching the permissions page.permission_edit_cache = perm_edit_ids == Page.permissions.GRANT_ALL or page.pk in perm_edit_ids page.permission_publish_cache = perm_publish_ids == Page.permissions.GRANT_ALL or page.pk in perm_publish_ids page.permission_advanced_settings_cache = perm_advanced_settings_ids == Page.permissions.GRANT_ALL or page.pk in perm_advanced_settings_ids page.permission_user_cache = request.user page._moderator_state_cache = pm_states[page.pk] page._public_published_cache = page.publisher_public_id in public_page_id_set if page.root_node or self.is_filtered(): page.last = True if len(children): # TODO: WTF!?! # The last one is not the last... wait, what? # children should NOT be a queryset. If it is, check that # your django-mptt version is 0.5.1 children[-1].last = False page.menu_level = 0 root_pages.append(page) if page.parent_id: page.get_cached_ancestors(ascending=True) else: page.ancestors_ascending = [] page.home_pk_cache = home_pk # Because 'children' is the reverse-FK accessor for the 'parent' # FK from Page->Page, we have to use wrong English here and set # an attribute called 'childrens'. We are aware that this is WRONG # but what should we do? # If the queryset is filtered, do NOT set the 'childrens' attribute # since *ALL* pages will be in the 'root_pages' list and therefore # be displayed. (If the queryset is filtered, the result is not a # tree but rather a flat list). if self.is_filtered(): page.childrens = [] else: page.childrens = children for page in all_pages: page.title_cache = {} page.all_languages = [] titles = Title.objects.filter(page__in=ids) insort = bisect.insort # local copy to avoid globals lookup in the loop for title in titles: page = ids[title.page_id] page.title_cache[title.language] = title if not title.language in page.all_languages: insort(page.all_languages, title.language) self.root_pages = root_pages
def set_items(self, request): site = self.current_site() # Get all the pages, ordered by tree ID (it's convenient to build the # tree using a stack now) pages = self.get_queryset(request).drafts().order_by('path').select_related('publisher_public') # Get lists of page IDs for which the current user has # "permission to..." on the current site. if get_cms_setting('PERMISSION'): perm_edit_ids = Page.permissions.get_change_id_list(request.user, site) perm_publish_ids = Page.permissions.get_publish_id_list(request.user, site) perm_advanced_settings_ids = Page.permissions.get_advanced_settings_id_list(request.user, site) restricted_ids = Page.permissions.get_restricted_id_list(site) if perm_edit_ids and perm_edit_ids != Page.permissions.GRANT_ALL: pages = pages.filter(pk__in=perm_edit_ids) root_pages = [] # Cache view restrictions for the is_restricted template tag load_view_restrictions(request, pages) pages = list(pages) all_pages = pages[:] # That is, basically, a copy. # Unfortunately we cannot use the MPTT builtin code for pre-caching # the children here, because MPTT expects the tree to be 'complete' # and otherwise complaints about 'invalid item order' cache_tree_children(pages) ids = dict((page.id, page) for page in pages) parent_ids = {} for page in pages: if not page.parent_id in parent_ids: parent_ids[page.parent_id] = [] parent_ids[page.parent_id].append(page) for page in pages: children = parent_ids.get(page.pk, []) # If the parent page is not among the nodes shown, this node should # be a "root node". The filtering for this has already been made, so # using the ids dictionary means this check is constant time page.root_node = page.parent_id not in ids if get_cms_setting('PERMISSION'): # caching the permissions page.permission_edit_cache = perm_edit_ids == Page.permissions.GRANT_ALL or page.pk in perm_edit_ids page.permission_publish_cache = perm_publish_ids == Page.permissions.GRANT_ALL or page.pk in perm_publish_ids page.permission_advanced_settings_cache = perm_advanced_settings_ids == Page.permissions.GRANT_ALL or page.pk in perm_advanced_settings_ids page.permission_user_cache = request.user page.permission_restricted = page.pk in restricted_ids if page.root_node or self.is_filtered(): page.last = True if len(children): # TODO: WTF!?! # The last one is not the last... wait, what? # children should NOT be a queryset. If it is, check that # your django-mptt version is 0.5.1 children[-1].last = False page.menu_level = 0 root_pages.append(page) if page.parent_id: page.get_cached_ancestors() else: page.ancestors_ascending = [] # Because 'children' is the reverse-FK accessor for the 'parent' # FK from Page->Page, we have to use wrong English here and set # an attribute called 'childrens'. We are aware that this is WRONG # but what should we do? # If the queryset is filtered, do NOT set the 'childrens' attribute # since *ALL* pages will be in the 'root_pages' list and therefore # be displayed. (If the queryset is filtered, the result is not a # tree but rather a flat list). if self.is_filtered(): page.childrens = [] else: page.childrens = children for page in all_pages: page.title_cache = {} page.all_languages = [] if page.publisher_public_id: page.publisher_public.title_cache = {} page.publisher_public.all_languages = [] ids[page.publisher_public_id] = page.publisher_public titles = Title.objects.filter(page__in=ids) insort = bisect.insort # local copy to avoid globals lookup in the loop for title in titles: page = ids[title.page_id] page.title_cache[title.language] = title if not title.language in page.all_languages: insort(page.all_languages, title.language) site_id = self.current_site() languages = get_language_list(site_id) for page in all_pages: for lang in languages: if not lang in page.title_cache: page.title_cache[lang] = EmptyTitle(lang) self.root_pages = root_pages