def assertGrantedVisibility(self, all_pages, expected_granted_pages, username=None): """ helper function to check the expected_granted_pages are not in the restricted_pages list and all visible pages are in the expected_granted_pages """ # log the user in if present user = None if username is not None: if get_user_model().USERNAME_FIELD == 'email': username = username + '@django-cms.org' query = dict() query[get_user_model().USERNAME_FIELD + '__iexact'] = username user = get_user_model().objects.get(**query) request = self.get_request(user) visible_page_ids = [ page.pk for page in get_visible_nodes(request, all_pages, self.site) ] public_page_ids = Page.objects.drafts().filter( title_set__title__in=expected_granted_pages).values_list('id', flat=True) self.assertEqual(len(visible_page_ids), len(expected_granted_pages)) restricted_pages = Page.objects.public().exclude( title_set__title__in=expected_granted_pages).values_list('id', flat=True) self.assertNodeMemberships(visible_page_ids, restricted_pages, public_page_ids)
def test_unauth_non_access(self): request = self.get_request() with self.assertNumQueries(0): self.assertViewNotAllowed(self.page) self.assertEqual(get_visible_nodes(request, [self.page], self.site), [])
def test_normal_basic_auth(self): user = self.get_standard_user() request = self.get_request(user) with self.assertNumQueries(0): self.assertViewAllowed(self.page, user) self.assertEqual(get_visible_nodes(request, [self.page], self.site), [self.page])
def test_unauthed(self): request = self.get_request() with self.assertNumQueries(1): """The queries are: PagePermission query for the affected page (is the page restricted?) """ self.assertViewNotAllowed(self.page) self.assertEqual(get_visible_nodes(request, self.pages, self.site), [])
def test_staff_basic_auth(self): user = self.get_staff_user_with_no_permissions() request = self.get_request(user) with self.assertNumQueries(0): self.assertViewAllowed(self.page, user) self.assertEqual(get_visible_nodes(request, [self.page], self.site), [self.page])
def test_public_pages_anonymous_norestrictions(self): """ All pages are visible to an anonymous user """ all_pages = self._setup_tree_pages() request = self.get_request() visible_pages = get_visible_nodes(request, all_pages, self.site) self.assertEqual(len(all_pages), len(visible_pages)) menu_renderer = menu_pool.get_renderer(request) nodes = menu_renderer.get_nodes() self.assertEqual(len(nodes), len(all_pages))
def test_basic_perm(self): user = self.get_standard_user() user.user_permissions.add(Permission.objects.get(codename='view_page')) request = self.get_request(user) with self.assertNumQueries(3): """ The queries are: PagePermission query (is this page restricted) Generic django permission lookup content type lookup by permission lookup """ self.assertViewAllowed(self.page, user) self.assertEqual(get_visible_nodes(request, self.pages, self.site), self.expected)
def test_normal_denied(self): user = self.get_standard_user() request = self.get_request(user) with self.assertNumQueries(4): """ The queries are: PagePermission query for the affected page (is the page restricted?) GlobalPagePermission query for the page site User permissions query Content type query """ self.assertViewNotAllowed(self.page, user) self.assertEqual(get_visible_nodes(request, [self.page], self.site), [])
def test_global_access(self): user = self.get_standard_user() GlobalPagePermission.objects.create(can_view=True, user=user) request = self.get_request(user) with self.assertNumQueries(4): """The queries are: PagePermission query for the affected page (is the page restricted?) Generic django permission lookup content type lookup by permission lookup GlobalPagePermission query for the page site """ self.assertViewAllowed(self.page, user) self.assertEqual(get_visible_nodes(request, [self.page], self.site), [self.page])
def test_basic_perm_denied(self): user = self.get_staff_user_with_no_permissions() request = self.get_request(user) with self.assertNumQueries(6): """ The queries are: PagePermission query (is this page restricted) content type lookup x2 GlobalpagePermission query for user TreeNode lookup PagePermission query for this user """ self.assertViewNotAllowed(self.page, user) self.assertEqual(get_visible_nodes(request, self.pages, self.site), [])
def test_page_group_permissions(self): user = self.get_standard_user() user.groups.add(self.group) request = self.get_request(user) with self.assertNumQueries(6): """ The queries are: PagePermission query (is this page restricted) content type lookup (x2) GlobalpagePermission query for user TreeNode lookup PagePermission query for user """ self.assertViewAllowed(self.page, user) self.assertEqual(get_visible_nodes(request, self.pages, self.site), self.expected)
def test_page_permissions(self): user = self.get_standard_user() request = self.get_request(user) PagePermission.objects.create(can_view=True, user=user, page=self.page, grant_on=ACCESS_PAGE) with self.assertNumQueries(6): """ The queries are: PagePermission query (is this page restricted) content type lookup (x2) GlobalpagePermission query for user TreeNode lookup PagePermission query for this user """ self.assertViewAllowed(self.page, user) self.assertEqual(get_visible_nodes(request, self.pages, self.site), self.expected)
def get_nodes(self, request): site = self.renderer.site language = self.renderer.request_language pages_qs = get_page_queryset(site).select_related('node') visible_pages_for_user = get_visible_nodes(request, pages_qs, site) if not visible_pages_for_user: return [] cms_extension = apps.get_app_config( 'djangocms_versioning').cms_extension toolbar = get_toolbar_from_request(request) edit_or_preview = toolbar.edit_mode_active or toolbar.preview_mode_active menu_nodes = [] node_id_to_page = {} homepage_content = None # Depending on the toolbar mode, we need to get the correct version. # On edit or preview mode: return DRAFT, # if DRAFT does not exists then return PUBLISHED. # On public mode: return PUBLISHED. if edit_or_preview: states = [constants.DRAFT, constants.PUBLISHED] else: states = [constants.PUBLISHED] versionable_item = cms_extension.versionables_by_grouper[Page] versioned_page_contents = ( versionable_item.content_model._base_manager.filter( language=language, page__in=pages_qs, versions__state__in=states, ).order_by('page__node__path', 'versions__state').select_related( 'page', 'page__node').prefetch_related('versions')) added_pages = [] for page_content in versioned_page_contents: page = page_content.page if page not in visible_pages_for_user: # The page is restricted for the user. # Therefore we avoid adding it to the menu. continue version = page_content.versions.all()[0] if (page.pk in added_pages and edit_or_preview and version.state == constants.PUBLISHED): # Page content is already added. This is the case where you # have both draft and published and in edit/preview mode. # We give priority to draft which is already sorted by the query. # Therefore we ignore the published version. continue page_tree_node = page.node parent_id = node_id_to_page.get(page_tree_node.parent_id) if page_tree_node.parent_id and not parent_id: # If the parent page is not available, # we skip adding the menu node. continue # Construct the url based on the toolbar mode. if edit_or_preview: url = get_object_preview_url(page_content) else: url = page_content.get_absolute_url() # Create the new navigation node. new_node = CMSVersionedNavigationNode( id=page.pk, attr=_get_attrs_for_node(self.renderer, page_content), title=page_content.menu_title or page_content.title, url=url, visible=page_content.in_navigation, ) if not homepage_content: # Set the home page content. homepage_content = page_content if page.is_home else None cut_homepage = homepage_content and not homepage_content.in_navigation if cut_homepage and parent_id == homepage_content.page.pk: # When the homepage is hidden from navigation, # we need to cut all its direct children from it. new_node.parent_id = None else: new_node.parent_id = parent_id node_id_to_page[page_tree_node.pk] = page.pk menu_nodes.append(new_node) added_pages.append(page.pk) return menu_nodes