Skip to content

Loading…

View permission performance boost #930

Merged
merged 12 commits into from

2 participants

@ojii

can apparently reduce the query count for menu creation by 50%....

@ojii

writing tests for this atm, so please consider this pull request as a RFC, NOT something to pull yet. Found some strange things in the code and trying to fix that now

Jonas Obrist added some commits
@ojii ojii merged commit 3cffa84 into divio:develop
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 20, 2011
  1. @fivethreeo
  2. @fivethreeo

    less queries comment

    fivethreeo committed
Commits on Aug 2, 2011
  1. Merge branch 'page_menu_lessqueries' of https://github.com/fivethreeo…

    Jonas Obrist committed
    …/django-cms into fivethreeo-page_menu_lessqueries
  2. Use AssertNumQueries

    Jonas Obrist committed
Commits on Aug 5, 2011
  1. Improved the reporting of AssertNumQueries

    Jonas Obrist committed
  2. Improved menu building by getting all view permissions at once for al…

    Jonas Obrist committed
    …l pages in the menu
  3. Merge branch 'develop' of github.com:divio/django-cms into view-permi…

    Jonas Obrist committed
    …ssion-performance-boost
  4. Drastically improved coverage of cms.menu.get_visible_pages and fixed…

    Jonas Obrist committed
    … some bugs in the process
  5. Removed unnecessary import

    Jonas Obrist committed
  6. Added more tests for view permission in menu

    Jonas Obrist committed
    Fixed an issue that PagePermission were not respected in cms.menu.get_visible_pages
Showing with 629 additions and 36 deletions.
  1. +87 −6 cms/menu.py
  2. +18 −19 cms/models/pagemodel.py
  3. +4 −2 cms/test_utils/util/context_managers.py
  4. +339 −4 cms/tests/menu.py
  5. +180 −4 cms/tests/permmod.py
  6. +1 −1 cms/utils/plugins.py
View
93 cms/menu.py
@@ -1,13 +1,91 @@
# -*- coding: utf-8 -*-
-from menus.menu_pool import menu_pool
-from menus.base import Menu, NavigationNode, Modifier
+from collections import defaultdict
+from cms.apphook_pool import apphook_pool
+from cms.models.moderatormodels import (ACCESS_DESCENDANTS,
+ ACCESS_PAGE_AND_DESCENDANTS, ACCESS_CHILDREN, ACCESS_PAGE_AND_CHILDREN)
+from cms.models.permissionmodels import PagePermission, GlobalPagePermission
+from cms.models.titlemodels import Title
from cms.utils import get_language_from_request
+from cms.utils.i18n import get_fallback_languages
from cms.utils.moderator import get_page_queryset, get_title_queryset
+from cms.utils.plugins import current_site
from django.conf import settings
from django.contrib.sites.models import Site
-from cms.utils.i18n import get_fallback_languages
-from cms.apphook_pool import apphook_pool
-from cms.models.titlemodels import Title
+from django.db.models.query_utils import Q
+from menus.base import Menu, NavigationNode, Modifier
+from menus.menu_pool import menu_pool
+
+
+def get_visible_pages(request, pages, site=None):
+ # This code is basically a many-pages-at-once version of
+ # Page.has_view_permission, check there to see wtf is going on here.
+ if request.user.is_staff and settings.CMS_PUBLIC_FOR in ('staff', 'all'):
+ return [page.pk for page in pages]
+ page_ids = []
+
+ pages_perms_q = Q()
+ for page in pages:
+ page_q = Q(page__tree_id=page.tree_id) & (
+ Q(page=page)
+ | (Q(page__level__lt=page.level) & (Q(grant_on=ACCESS_DESCENDANTS) | Q(grant_on=ACCESS_PAGE_AND_DESCENDANTS)))
+ | (Q(page__level=page.level - 1) & (Q(grant_on=ACCESS_CHILDREN) | Q(grant_on=ACCESS_PAGE_AND_CHILDREN)))
+ )
+ pages_perms_q |= page_q
+ pages_perms_q &= Q(can_view=True)
+ page_permissions = PagePermission.objects.filter(pages_perms_q).select_related('page', 'group__users')
+
+ restricted_pages = defaultdict(list)
+ for perm in page_permissions:
+ restricted_pages[perm.page.pk].append(perm)
+
+ if site is None:
+ site = current_site(request)
+
+ if request.user.is_authenticated():
+ #return self.filter(Q(user=user) | Q(group__user=user))
+ global_page_perm_q = Q(
+ Q(user=request.user) | Q(group__user=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()
+
+ 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(page):
+ """
+ PagePermission tests
+ """
+ for perm in restricted_pages[page.pk]:
+ if perm.user_id == request.user.pk:
+ return True
+ for perm in restricted_pages[page.pk]:
+ if not perm.group_id:
+ continue
+ if request.user.pk in perm.group.user_set.values_list('id', flat=True):
+ return True
+ return False
+
+ for page in pages:
+ is_restricted = page.pk in restricted_pages
+
+ if request.user.is_authenticated():
+ # a global permission was given to the request's user
+ if global_view_perms:
+ page_ids.append(page.pk)
+ # authenticated user, no restriction and public for all
+ elif settings.CMS_PUBLIC_FOR == 'all':
+ page_ids.append(page.pk)
+ elif has_permission(page):
+ page_ids.append(page.pk)
+ elif has_global_perm():
+ page_ids.append(page.pk)
+ elif not is_restricted and settings.CMS_PUBLIC_FOR == 'all':
+ # anonymous user, no restriction saved in database
+ page_ids.append(page.pk)
+ return page_ids
def page_to_node(page, home, cut):
'''
@@ -97,11 +175,14 @@ def get_nodes(self, request):
home_children = []
home = None
actual_pages = []
+
+ # cache view perms
+ visible_pages = get_visible_pages(request, pages, site)
for page in pages:
# Pages are ordered by tree_id, therefore the first page is the root
# of the page tree (a.k.a "home")
- if not page.has_view_permission(request):
+ if page.pk not in visible_pages:
# Don't include pages the user doesn't have access to
continue
if not home:
View
37 cms/models/pagemodel.py
@@ -1,8 +1,14 @@
# -*- coding: utf-8 -*-
-import copy
+from cms.exceptions import NoHomeFound
+from cms.models.managers import PageManager, PagePermissionsPermissionManager
+from cms.models.metaclasses import PageMetaClass
+from cms.models.placeholdermodel import Placeholder
+from cms.models.pluginmodel import CMSPlugin
+from cms.publisher.errors import MpttPublisherCantPublish
+from cms.utils import i18n, urlutils, page as page_utils
+from cms.utils.copy_plugins import copy_plugins_to
+from cms.utils.helpers import reversion_register
from datetime import datetime
-from os.path import join
-
from django.conf import settings
from django.contrib.sites.models import Site
from django.core.exceptions import ObjectDoesNotExist
@@ -12,20 +18,14 @@
from django.db.models.fields.related import OneToOneRel
from django.shortcuts import get_object_or_404
from django.utils.translation import get_language, ugettext_lazy as _
+from menus.menu_pool import menu_pool
+from mptt.models import MPTTModel
+from os.path import join
+import copy
+
-from cms.exceptions import NoHomeFound
-from cms.models.managers import PageManager, PagePermissionsPermissionManager
-from cms.models.metaclasses import PageMetaClass
-from cms.models.placeholdermodel import Placeholder
-from cms.models.pluginmodel import CMSPlugin
-from cms.publisher.errors import MpttPublisherCantPublish
-from cms.utils.copy_plugins import copy_plugins_to
-from cms.utils.helpers import reversion_register
-from cms.utils import i18n, urlutils, page as page_utils
-from menus.menu_pool import menu_pool
-from mptt.models import MPTTModel
class Page(MPTTModel):
@@ -713,15 +713,14 @@ def has_view_permission(self, request):
if request.user.is_authenticated():
site = current_site(request)
+ global_perms_q = Q(can_view=True) & Q(
+ Q(sites__in=[site]) | Q(sites__isnull=True)
+ )
global_view_perms = GlobalPagePermission.objects.with_user(
- request.user).filter(can_view=True, sites__in=[site]).exists()
+ request.user).filter(global_perms_q).exists()
# a global permission was given to the request's user
if global_view_perms:
return True
- # authenticated user, no restriction and public for all fallback
- if (not is_restricted and not global_view_perms and
- not settings.CMS_PUBLIC_FOR == 'all'):
- return False
# authenticated user, no restriction and public for all
if (not is_restricted and not global_view_perms and
settings.CMS_PUBLIC_FOR == 'all'):
View
6 cms/test_utils/util/context_managers.py
@@ -170,9 +170,11 @@ def __exit__(self, exc_type, exc_value, traceback):
final_queries = len(self.connection.queries)
executed = final_queries - self.starting_queries
+
+ queries = '\n'.join([q['sql'] for q in self.connection.queries[self.starting_queries:]])
self.test_case.assertEqual(
- executed, self.num, "%d queries executed, %d expected" % (
- executed, self.num
+ executed, self.num, "%d queries executed, %d expected. Queries executed:\n%s" % (
+ executed, self.num, queries
)
)
View
343 cms/tests/menu.py
@@ -1,13 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import with_statement
from cms.api import create_page
-from cms.menu import CMSMenu
+from cms.menu import CMSMenu, get_visible_pages
from cms.models import Page
+from cms.models.permissionmodels import GlobalPagePermission, PagePermission
from cms.test_utils.fixtures.menus import (MenusFixture, SubMenusFixture,
SoftrootFixture)
from cms.test_utils.testcases import SettingsOverrideTestCase
+from cms.test_utils.util.context_managers import SettingsOverride
from cms.test_utils.util.mock import AttributeObject
from django.conf import settings
+from django.contrib.auth.models import AnonymousUser, User, Permission, Group
+from django.contrib.contenttypes.models import ContentType
+from django.contrib.sites.models import Site
from django.template import Template
from menus.base import NavigationNode
from menus.menu_pool import menu_pool, _build_nodes_inner_for_one_menu
@@ -16,7 +21,7 @@
class BaseMenuTest(SettingsOverrideTestCase):
settings_overrides = {
- 'CMS_MODERATOR': False
+ 'CMS_MODERATOR': False,
}
def _get_nodes(self, path='/'):
@@ -93,7 +98,21 @@ def test_show_menu(self):
self.assertEqual(nodes[1].get_absolute_url(), self.get_page(4).get_absolute_url())
self.assertEqual(nodes[1].sibling, True)
self.assertEqual(nodes[1].selected, False)
-
+
+ def test_show_menu_num_queries(self):
+ context = self.get_context()
+ # test standard show_menu
+ with self.assertNumQueries(4):
+ """
+ The 4 queries should be:
+ get all pages
+ get all page permissions
+ get all titles
+ set the menu cache key
+ """
+ tpl = Template("{% load menu_tags %}{% show_menu %}")
+ tpl.render(context)
+
def test_only_active_tree(self):
context = self.get_context()
# test standard show_menu
@@ -463,7 +482,7 @@ def test_build_nodes_inner_for_worst_case_menu(self):
self.assertEqual(node3.children, [node2])
self.assertEqual(node4.children, [node3])
self.assertEqual(node5.children, [node4])
-
+
def test_build_nodes_inner_for_circular_menu(self):
'''
TODO:
@@ -720,6 +739,20 @@ def test_show_submenu(self):
self.assertEqual(len(nodes), 1)
self.assertEqual(nodes[0].id, 8)
+ def test_show_submenu_num_queries(self):
+ page = Page.objects.get(title_set__title='P6')
+ context = self.get_context(page.get_absolute_url())
+ # test standard show_menu
+ with self.assertNumQueries(4):
+ """
+ The 4 queries should be:
+ get all pages
+ get all page permissions
+ get all titles
+ set the menu cache key
+ """
+ tpl = Template("{% load menu_tags %}{% show_sub_menu %}")
+ tpl.render(context)
class ShowMenuBelowIdTests(BaseMenuTest):
def test_not_in_navigation(self):
@@ -752,3 +785,305 @@ def test_not_in_navigation(self):
self.assertEqual(len(children), 1, repr(children))
child = children[0]
self.assertEqual(child.id, c.id)
+
+ def test_not_in_navigation_num_queries(self):
+ """
+ Test for issue 521
+
+ Build the following tree:
+
+ A
+ |-B
+ |-C
+ \-D (not in nav)
+ """
+ a = create_page('A', 'nav_playground.html', 'en', published=True,
+ in_navigation=True, reverse_id='a')
+ b =create_page('B', 'nav_playground.html', 'en', parent=a,
+ published=True, in_navigation=True)
+ c = create_page('C', 'nav_playground.html', 'en', parent=b,
+ published=True, in_navigation=True)
+ create_page('D', 'nav_playground.html', 'en', parent=self.reload(b),
+ published=True, in_navigation=False)
+ context = self.get_context(a.get_absolute_url())
+ with self.assertNumQueries(4):
+ """
+ The 4 queries should be:
+ get all pages
+ get all page permissions
+ get all titles
+ set the menu cache key
+ """
+ tpl = Template("{% load menu_tags %}{% show_menu_below_id 'a' 0 100 100 100 %}")
+ tpl.render(context)
+
+
+class ViewPermissionMenuTests(SettingsOverrideTestCase):
+ settings_overrides = {
+ 'CMS_MODERATOR': False,
+ 'CMS_PERMISSION': True,
+ 'CMS_PUBLIC_FOR': 'all',
+ }
+
+ def get_request(self, user=None):
+ attrs = {
+ 'user': user or AnonymousUser(),
+ 'REQUEST': {},
+ 'session': {},
+ }
+ return type('Request', (object,), attrs)
+
+ def test_public_for_all_staff(self):
+ request = self.get_request()
+ request.user.is_staff = True
+ page = Page()
+ page.pk = 1
+ pages = [page]
+ result = get_visible_pages(request, pages)
+ self.assertEqual(result, [1])
+
+ def test_public_for_all_staff_assert_num_queries(self):
+ request = self.get_request()
+ request.user.is_staff = True
+ page = Page()
+ page.pk = 1
+ pages = [page]
+ with self.assertNumQueries(0):
+ get_visible_pages(request, pages)
+
+ def test_public_for_all(self):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ request = self.get_request(user)
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ pages = [page]
+ result = get_visible_pages(request, pages)
+ self.assertEqual(result, [1])
+
+ def test_public_for_all_num_queries(self):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ request = self.get_request(user)
+ site = Site()
+ site.pk = 1
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ pages = [page]
+ with self.assertNumQueries(2):
+ """
+ The queries are:
+ PagePermission query for affected pages
+ GlobalpagePermission query for user
+ """
+ get_visible_pages(request, pages, site)
+
+ def test_unauthed(self):
+ request = self.get_request()
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ pages = [page]
+ result = get_visible_pages(request, pages)
+ self.assertEqual(result, [1])
+
+ def test_unauthed_num_queries(self):
+ request = self.get_request()
+ site = Site()
+ site.pk = 1
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ pages = [page]
+ with self.assertNumQueries(1):
+ """
+ The query is:
+ PagePermission query for affected pages
+
+ global is not executed because it's lazy
+ """
+ get_visible_pages(request, pages, site)
+
+ def test_authed_basic_perm(self):
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ user.user_permissions.add(Permission.objects.get(codename='view_page'))
+ request = self.get_request(user)
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ pages = [page]
+ result = get_visible_pages(request, pages)
+ self.assertEqual(result, [1])
+
+ def test_authed_basic_perm_num_queries(self):
+ site = Site()
+ site.pk = 1
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ user.user_permissions.add(Permission.objects.get(codename='view_page'))
+ request = self.get_request(user)
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ pages = [page]
+ with self.assertNumQueries(4):
+ """
+ The queries are:
+ PagePermission query for affected pages
+ GlobalpagePermission query for user
+ Generic django permission lookup
+ content type lookup by permission lookup
+ """
+ get_visible_pages(request, pages, site)
+
+ def test_authed_no_access(self):
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ request = self.get_request(user)
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ pages = [page]
+ result = get_visible_pages(request, pages)
+ self.assertEqual(result, [])
+
+ def test_authed_no_access_num_queries(self):
+ site = Site()
+ site.pk = 1
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ request = self.get_request(user)
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ pages = [page]
+ with self.assertNumQueries(4):
+ """
+ The queries are:
+ PagePermission query for affected pages
+ GlobalpagePermission query for user
+ Generic django permission lookup
+ content type lookup by permission lookup
+ """
+ get_visible_pages(request, pages, site)
+
+ def test_unauthed_no_access(self):
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ request = self.get_request()
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ pages = [page]
+ result = get_visible_pages(request, pages)
+ self.assertEqual(result, [])
+
+ def test_unauthed_no_access_num_queries(self):
+ site = Site()
+ site.pk = 1
+ request = self.get_request()
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ pages = [page]
+ with self.assertNumQueries(1):
+ get_visible_pages(request, pages, site)
+
+ def test_page_permissions(self):
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ request = self.get_request(user)
+ page = create_page('A', 'nav_playground.html', 'en')
+ PagePermission.objects.create(can_view=True, user=user, page=page)
+ pages = [page]
+ result = get_visible_pages(request, pages)
+ self.assertEqual(result, [1])
+
+ def test_page_permissions_num_queries(self):
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ request = self.get_request(user)
+ page = create_page('A', 'nav_playground.html', 'en')
+ PagePermission.objects.create(can_view=True, user=user, page=page)
+ pages = [page]
+ with self.assertNumQueries(2):
+ """
+ The queries are:
+ PagePermission query for affected pages
+ GlobalpagePermission query for user
+ """
+ get_visible_pages(request, pages)
+
+ def test_page_permissions_view_groups(self):
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ group = Group.objects.create(name='testgroup')
+ group.user_set.add(user)
+ request = self.get_request(user)
+ page = create_page('A', 'nav_playground.html', 'en')
+ PagePermission.objects.create(can_view=True, group=group, page=page)
+ pages = [page]
+ result = get_visible_pages(request, pages)
+ self.assertEqual(result, [1])
+
+ def test_page_permissions_view_groups_num_queries(self):
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ group = Group.objects.create(name='testgroup')
+ group.user_set.add(user)
+ request = self.get_request(user)
+ page = create_page('A', 'nav_playground.html', 'en')
+ PagePermission.objects.create(can_view=True, group=group, page=page)
+ pages = [page]
+ with self.assertNumQueries(3):
+ """
+ The queries are:
+ PagePermission query for affected pages
+ GlobalpagePermission query for user
+ Group query via PagePermission
+ """
+ get_visible_pages(request, pages)
+
+ def test_global_permission(self):
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ GlobalPagePermission.objects.create(can_view=True, user=user)
+ request = self.get_request(user)
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ pages = [page]
+ result = get_visible_pages(request, pages)
+ self.assertEqual(result, [1])
+
+ def test_global_permission_num_queries(self):
+ site = Site()
+ site.pk = 1
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ GlobalPagePermission.objects.create(can_view=True, user=user)
+ request = self.get_request(user)
+ site = Site()
+ site.pk = 1
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ pages = [page]
+ with self.assertNumQueries(2):
+ """
+ The queries are:
+ PagePermission query for affected pages
+ GlobalpagePermission query for user
+ """
+ get_visible_pages(request, pages, site)
View
184 cms/tests/permmod.py
@@ -1,19 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import with_statement
-from cms.api import create_page, publish_page, approve_page, add_plugin, \
- create_page_user, assign_user_to_page
+from cms.api import (create_page, publish_page, approve_page, add_plugin,
+ create_page_user, assign_user_to_page)
from cms.models import Page, CMSPlugin
from cms.models.moderatormodels import (ACCESS_DESCENDANTS,
ACCESS_PAGE_AND_DESCENDANTS)
+from cms.models.permissionmodels import PagePermission, GlobalPagePermission
from cms.test_utils.testcases import (URL_CMS_PAGE_ADD, URL_CMS_PLUGIN_REMOVE,
SettingsOverrideTestCase, URL_CMS_PLUGIN_ADD, CMSTestCase)
-
from cms.test_utils.util.context_managers import SettingsOverride
from cms.utils.page_resolver import get_page_from_path
from cms.utils.permissions import has_generic_permission
-from django.contrib.auth.models import User, Permission
+from django.contrib.auth.models import User, Permission, AnonymousUser, Group
+from django.contrib.sites.models import Site
from django.core.management import call_command
+
class PermissionModeratorTests(SettingsOverrideTestCase):
"""Permissions and moderator together
@@ -806,3 +808,177 @@ def test_switch_moderator_off(self):
with SettingsOverride(CMS_MODERATOR=False):
page2 = get_page_from_path(page1.get_absolute_url().strip('/'))
self.assertEqual(page1.get_absolute_url(), page2.get_absolute_url())
+
+
+class ViewPermissionTests(SettingsOverrideTestCase):
+ settings_overrides = {
+ 'CMS_MODERATOR': False,
+ 'CMS_PERMISSION': True,
+ 'CMS_PUBLIC_FOR': 'all',
+ }
+
+
+ def get_request(self, user=None):
+ attrs = {
+ 'user': user or AnonymousUser(),
+ 'REQUEST': {},
+ 'session': {},
+ }
+ return type('Request', (object,), attrs)
+
+ def test_public_for_all_staff(self):
+ request = self.get_request()
+ request.user.is_staff = True
+ page = Page()
+ page.pk = 1
+ self.assertTrue(page.has_view_permission(request))
+
+ def test_public_for_all_staff_assert_num_queries(self):
+ request = self.get_request()
+ request.user.is_staff = True
+ page = Page()
+ page.pk = 1
+ with self.assertNumQueries(0):
+ page.has_view_permission(request)
+
+ def test_public_for_all(self):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ request = self.get_request(user)
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ self.assertTrue(page.has_view_permission(request))
+
+ def test_public_for_all_num_queries(self):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ request = self.get_request(user)
+ site = Site()
+ site.pk = 1
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ with self.assertNumQueries(3):
+ """
+ The queries are:
+ The current Site
+ PagePermission query for affected pages
+ GlobalpagePermission query for user
+ """
+ page.has_view_permission(request)
+
+ def test_unauthed(self):
+ request = self.get_request()
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ self.assertTrue(page.has_view_permission(request))
+
+ def test_unauthed_num_queries(self):
+ request = self.get_request()
+ site = Site()
+ site.pk = 1
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ with self.assertNumQueries(1):
+ """
+ The query is:
+ PagePermission query for affected pages
+ """
+ page.has_view_permission(request)
+
+ def test_authed_basic_perm(self):
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ user.user_permissions.add(Permission.objects.get(codename='view_page'))
+ request = self.get_request(user)
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ self.assertTrue(page.has_view_permission(request))
+
+ def test_authed_basic_perm_num_queries(self):
+ site = Site()
+ site.pk = 1
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ user.user_permissions.add(Permission.objects.get(codename='view_page'))
+ request = self.get_request(user)
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ with self.assertNumQueries(5):
+ """
+ The queries are:
+ The site
+ PagePermission query for affected pages
+ GlobalpagePermission query for user
+ Generic django permission lookup
+ content type lookup by permission lookup
+ """
+ page.has_view_permission(request)
+
+ def test_authed_no_access(self):
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ request = self.get_request(user)
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ self.assertFalse(page.has_view_permission(request))
+
+ def test_unauthed_no_access(self):
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ request = self.get_request()
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ self.assertFalse(page.has_view_permission(request))
+
+ def test_unauthed_no_access_num_queries(self):
+ site = Site()
+ site.pk = 1
+ request = self.get_request()
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ with self.assertNumQueries(1):
+ page.has_view_permission(request)
+
+ def test_page_permissions(self):
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ request = self.get_request(user)
+ page = create_page('A', 'nav_playground.html', 'en')
+ PagePermission.objects.create(can_view=True, user=user, page=page)
+ self.assertTrue(page.has_view_permission(request))
+
+ def test_page_permissions_view_groups(self):
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ group = Group.objects.create(name='testgroup')
+ group.user_set.add(user)
+ request = self.get_request(user)
+ page = create_page('A', 'nav_playground.html', 'en')
+ PagePermission.objects.create(can_view=True, group=group, page=page)
+ self.assertTrue(page.has_view_permission(request))
+
+ def test_global_permission(self):
+ with SettingsOverride(CMS_PUBLIC_FOR='staff'):
+ user = User.objects.create_user('user', 'user@domain.com', 'user')
+ GlobalPagePermission.objects.create(can_view=True, user=user)
+ request = self.get_request(user)
+ page = Page()
+ page.pk = 1
+ page.level = 0
+ page.tree_id = 1
+ self.assertTrue(page.has_view_permission(request))
View
2 cms/utils/plugins.py
@@ -131,4 +131,4 @@ def current_site(request):
except Site.DoesNotExist:
return None
else:
- return Site.objects.get_current()
+ return Site.objects.get_current()
Something went wrong with that request. Please try again.