forked from ungleich-public/dynamicweb
5522 lines
226 KiB
Python
5522 lines
226 KiB
Python
import datetime
|
|
import json
|
|
import re
|
|
import sys
|
|
from unittest import skipUnless
|
|
from unittest.mock import patch
|
|
|
|
from django.conf import settings
|
|
from django.contrib import admin
|
|
from django.contrib.sites.models import Site
|
|
from django.core.cache import cache
|
|
from django.db import IntegrityError, connection, transaction
|
|
from django.forms.models import model_to_dict
|
|
from django.http import HttpRequest, HttpResponse
|
|
from django.test.html import HTMLParseError, Parser
|
|
from django.test.utils import CaptureQueriesContext, override_settings
|
|
from django.urls import clear_url_caches
|
|
from django.utils.encoding import force_str
|
|
from django.utils.timezone import now as tz_now
|
|
from django.utils.translation import override as force_language
|
|
from djangocms_text.models import Text
|
|
|
|
from cms import constants
|
|
from cms.admin.pageadmin import PAGE_SMART_LINK_MAX_RESULTS, PageContentAdmin
|
|
from cms.api import add_plugin, create_page, create_page_content
|
|
from cms.appresolver import clear_app_resolvers
|
|
from cms.cache.permissions import get_permission_cache, set_permission_cache
|
|
from cms.middleware.user import CurrentUserMiddleware
|
|
from cms.models import PageContent
|
|
from cms.models.pagemodel import Page, PageUrl
|
|
from cms.models.permissionmodels import PagePermission
|
|
from cms.models.pluginmodel import CMSPlugin
|
|
from cms.test_utils.project.sampleapp.models import SampleAppConfig
|
|
from cms.test_utils.testcases import URL_CMS_PAGE_MOVE, CMSTestCase
|
|
from cms.test_utils.util.context_managers import (
|
|
LanguageOverride,
|
|
UserLoginContext,
|
|
override_placeholder_conf,
|
|
)
|
|
from cms.toolbar.utils import get_object_edit_url
|
|
from cms.utils.compat.dj import installed_apps
|
|
from cms.utils.conf import get_cms_setting
|
|
from cms.utils.page import get_page_from_request
|
|
from cms.utils.urlutils import admin_reverse
|
|
|
|
|
|
class PageTreeLiParser(Parser):
|
|
def handle_starttag(self, tag, attrs):
|
|
# We have to strip out attributes from the <li>
|
|
# tags in order to compare the values only
|
|
# Otherwise we'd have to include all attributes
|
|
# which in this case is not optimal because there's too many
|
|
# and would require us to hardcode a bunch of stuff here
|
|
if tag == "li":
|
|
attrs = []
|
|
Parser.handle_starttag(self, tag, attrs)
|
|
|
|
|
|
class PageTreeOptionsParser(Parser):
|
|
def handle_starttag(self, tag, attrs):
|
|
# This parser only cares about the options on the right side
|
|
# of the page tree for each page.
|
|
if tag == "li" and attrs and attrs[-1][0] == "data-coloptions":
|
|
attrs = [attrs[-1]]
|
|
Parser.handle_starttag(self, tag, attrs)
|
|
|
|
|
|
class PageTestBase(CMSTestCase):
|
|
"""
|
|
The purpose of this class is to provide some basic functionality
|
|
to test methods of the Page admin.
|
|
"""
|
|
|
|
placeholderconf = {
|
|
"body": {
|
|
"limits": {
|
|
"global": 2,
|
|
"TextPlugin": 1,
|
|
}
|
|
}
|
|
}
|
|
|
|
def _add_plugin_to_page(self, page, plugin_type="LinkPlugin", language="en", publish=True):
|
|
plugin_data = {
|
|
"TextPlugin": {"body": "<p>text</p>"},
|
|
"LinkPlugin": {"name": "A Link", "external_link": "https://www.django-cms.org"},
|
|
}
|
|
placeholder = page.get_placeholders(language).get(slot="body")
|
|
plugin = add_plugin(placeholder, plugin_type, language, **plugin_data[plugin_type])
|
|
return plugin
|
|
|
|
def _translation_exists(self, slug=None, title=None):
|
|
if not slug:
|
|
slug = "permissions-de"
|
|
|
|
lookup = PageContent.objects.filter(page__urls__slug=slug)
|
|
|
|
if title:
|
|
lookup = lookup.filter(title=title)
|
|
return lookup.exists()
|
|
|
|
def _get_add_plugin_uri(self, page, language="en"):
|
|
placeholder = page.get_placeholders(language).get(slot="body")
|
|
uri = self.get_add_plugin_uri(
|
|
placeholder=placeholder,
|
|
plugin_type="LinkPlugin",
|
|
language=language,
|
|
)
|
|
return uri
|
|
|
|
def _get_page_data(self, **kwargs):
|
|
site = Site.objects.get_current()
|
|
data = {
|
|
"title": "permissions",
|
|
"slug": "permissions",
|
|
"language": "en",
|
|
"site": site.pk,
|
|
"template": "nav_playground.html",
|
|
}
|
|
data.update(**kwargs)
|
|
return data
|
|
|
|
def _get_move_data(self, plugin, position, placeholder=None, parent=None):
|
|
try:
|
|
placeholder_id = placeholder.pk
|
|
except AttributeError:
|
|
placeholder_id = ""
|
|
|
|
try:
|
|
parent_id = parent.pk
|
|
except AttributeError:
|
|
parent_id = ""
|
|
|
|
data = {
|
|
"placeholder_id": placeholder_id,
|
|
"target_language": "en",
|
|
"target_position": position,
|
|
"plugin_id": plugin.pk,
|
|
"plugin_parent": parent_id,
|
|
}
|
|
return data
|
|
|
|
def get_page(self, parent=None, site=None, language=None, template="nav_playground.html"):
|
|
page_data = self.get_new_page_data_dbfields()
|
|
return create_page(**page_data)
|
|
|
|
def get_post_request(self, data):
|
|
return self.get_request(post_data=data)
|
|
|
|
def create_page(self, title=None, **kwargs):
|
|
return create_page(title or self._testMethodName, "nav_playground.html", "en", **kwargs)
|
|
|
|
|
|
class PageTest(PageTestBase):
|
|
def tearDown(self):
|
|
cache.clear()
|
|
|
|
def test_add_page(self):
|
|
"""
|
|
Test that the add admin page could be displayed via the admin
|
|
"""
|
|
superuser = self.get_superuser()
|
|
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(self.get_page_add_uri("en"))
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, "<title>Add a page</title>", html=True)
|
|
|
|
def test_add_page_different_site(self):
|
|
"""
|
|
Test that the add admin page could be displayed via the admin
|
|
"""
|
|
superuser = self.get_superuser()
|
|
Site.objects.create(id=2, name="example-2.com", domain="example-2.com")
|
|
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(self.get_page_add_uri("en", site_id=2))
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, "<title>Add a page</title>", html=True)
|
|
self.assertContains(response, "&site=2")
|
|
|
|
def test_create_page_admin(self):
|
|
"""
|
|
Test that a page can be created via the admin
|
|
"""
|
|
page_data = self.get_new_page_data()
|
|
|
|
superuser = self.get_superuser()
|
|
with self.login_user_context(superuser):
|
|
self.assertEqual(PageContent.objects.all().count(), 0)
|
|
self.assertEqual(Page.objects.all().count(), 0)
|
|
# create home
|
|
response = self.client.post(self.get_page_add_uri("en"), page_data)
|
|
self.assertRedirects(response, self.get_pages_admin_list_uri("en"))
|
|
|
|
page_url = PageUrl.objects.get(slug=page_data["slug"])
|
|
self.assertEqual(page_url.page.get_title(), page_data["title"])
|
|
self.assertEqual(page_url.page.get_slug("en"), page_data["slug"])
|
|
self.assertEqual(page_url.page.get_placeholders("en").count(), 2)
|
|
|
|
def test_create_page_admin_different_site(self):
|
|
"""
|
|
Test that a page can be created via the admin
|
|
"""
|
|
Site.objects.create(id=2, name="example-2.com", domain="example-2.com")
|
|
with self.settings(CMS_LANGUAGES={2: [{"code": "en", "name": "English"}]}):
|
|
page_data = self.get_new_page_data()
|
|
|
|
superuser = self.get_superuser()
|
|
with self.login_user_context(superuser):
|
|
self.assertEqual(PageContent.objects.all().count(), 0)
|
|
self.assertEqual(Page.objects.all().count(), 0)
|
|
# create home
|
|
response = self.client.post(self.get_page_add_uri("en", site_id=2), page_data)
|
|
self.assertRedirects(response, self.get_pages_admin_list_uri("en", site_id=2))
|
|
|
|
page_url = PageUrl.objects.get(slug=page_data["slug"])
|
|
self.assertEqual(page_url.page.site_id, 2)
|
|
self.assertEqual(page_url.page.get_title(), page_data["title"])
|
|
self.assertEqual(page_url.page.get_slug("en"), page_data["slug"])
|
|
self.assertEqual(page_url.page.get_placeholders("en").count(), 2)
|
|
|
|
def test_create_page_with_unconfigured_language(self):
|
|
"""
|
|
Test that a page can be created via the admin
|
|
with the request language pointing to a language
|
|
not configured for the current site
|
|
"""
|
|
from django.contrib.auth import get_user_model
|
|
from django.test import Client
|
|
|
|
client = Client()
|
|
superuser = self.get_superuser()
|
|
Site.objects.create(id=2, name="example-2.com", domain="example-2.com")
|
|
client.login(
|
|
username=getattr(superuser, get_user_model().USERNAME_FIELD),
|
|
password=getattr(superuser, get_user_model().USERNAME_FIELD),
|
|
)
|
|
self.assertEqual(PageContent.objects.all().count(), 0)
|
|
self.assertEqual(Page.objects.all().count(), 0)
|
|
# create home
|
|
with self.settings(SITE_ID=2):
|
|
endpoint = self.get_page_add_uri("en")
|
|
# url uses "en" as the request language
|
|
# but the site is configured to use "de" and "fr"
|
|
response = client.post(endpoint, self.get_new_page_data())
|
|
self.assertRedirects(response, self.get_pages_admin_list_uri("de"))
|
|
self.assertEqual(Page.objects.filter(site=2).count(), 1)
|
|
self.assertEqual(PageContent.objects.filter(language="de").count(), 1)
|
|
|
|
# The user is on site #1 but switches to using site #2.
|
|
# url uses "en" as the request language
|
|
# but the site is configured to use "de" and "fr"
|
|
endpoint = self.get_page_add_uri("en", site_id=2)
|
|
response = client.post(endpoint, self.get_new_page_data())
|
|
self.assertRedirects(response, self.get_pages_admin_list_uri("de", site_id=2))
|
|
self.assertEqual(Page.objects.filter(site=2).count(), 2)
|
|
self.assertEqual(PageContent.objects.filter(language="de").count(), 2)
|
|
|
|
Site.objects.clear_cache()
|
|
client.logout()
|
|
|
|
def test_create_tree_admin(self):
|
|
"""
|
|
Test that a tree can be created via the admin
|
|
"""
|
|
page_1 = self.get_new_page_data()
|
|
|
|
superuser = self.get_superuser()
|
|
with self.login_user_context(superuser):
|
|
# create home and auto publish
|
|
response = self.client.post(self.get_page_add_uri("en"), page_1)
|
|
self.assertRedirects(response, self.get_pages_admin_list_uri("en"))
|
|
|
|
home_url = PageUrl.objects.get(slug=page_1["slug"])
|
|
|
|
page_2 = self.get_new_page_data(parent_id=home_url.page.pk)
|
|
page_3 = self.get_new_page_data(parent_id=home_url.page.pk)
|
|
page_4 = self.get_new_page_data(parent_id=home_url.page.pk)
|
|
|
|
response = self.client.post(self.get_page_add_uri("en"), page_2)
|
|
self.assertRedirects(response, self.get_pages_admin_list_uri("en"))
|
|
response = self.client.post(self.get_page_add_uri("en"), page_3)
|
|
self.assertRedirects(response, self.get_pages_admin_list_uri("en"))
|
|
|
|
page2_url = PageUrl.objects.get(slug=page_2["slug"])
|
|
|
|
add_endpoint = self.get_page_add_uri("en")
|
|
response = self.client.post(add_endpoint + "&target=%s&position=right" % page2_url.page.pk, page_4)
|
|
self.assertRedirects(response, self.get_pages_admin_list_uri("en"))
|
|
|
|
def test_slug_collision(self):
|
|
"""
|
|
Test a slug collision
|
|
"""
|
|
page_data = self.get_new_page_data()
|
|
# create first page
|
|
superuser = self.get_superuser()
|
|
with self.login_user_context(superuser):
|
|
add_endpoint = self.get_page_add_uri("en")
|
|
# Home
|
|
response = self.client.post(add_endpoint, page_data)
|
|
self.assertRedirects(response, self.get_pages_admin_list_uri("en"))
|
|
# Second root
|
|
response = self.client.post(add_endpoint, page_data)
|
|
self.assertRedirects(response, self.get_pages_admin_list_uri("en"))
|
|
|
|
response = self.client.post(add_endpoint, page_data)
|
|
new_page = Page.objects.only("id").latest("id")
|
|
expected_error = (
|
|
'<ul class="errorlist" id="id_slug_error"><li>Page '
|
|
'<a href="{}" target="_blank">test page 1</a> '
|
|
"has the same url 'test-page-1' as current page.</li></ul>"
|
|
).format(self.get_page_change_uri("en", new_page))
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, expected_error)
|
|
|
|
def test_child_slug_collision(self):
|
|
"""
|
|
Test a slug collision
|
|
"""
|
|
root = create_page("home", "nav_playground.html", "en")
|
|
page = create_page("page", "nav_playground.html", "en")
|
|
sub_page = create_page("subpage", "nav_playground.html", "en", parent=page)
|
|
child_page = create_page("child-page", "nav_playground.html", "en", parent=root)
|
|
root.set_as_homepage()
|
|
superuser = self.get_superuser()
|
|
add_endpoint = self.get_page_add_uri("en")
|
|
with self.login_user_context(superuser):
|
|
with self.subTest("Slug collision between two child pages of the same node"):
|
|
page_data = self.get_new_page_data(page.pk)
|
|
page_data["slug"] = "subpage"
|
|
response = self.client.post(add_endpoint, page_data)
|
|
expected_markup = (
|
|
'<ul class="errorlist" id="id_slug_error">'
|
|
'<li>Page <a href="{}" target="_blank">subpage</a> '
|
|
"has the same url 'page/subpage' as current page.</li></ul>"
|
|
).format(self.get_page_change_uri("en", sub_page))
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, expected_markup)
|
|
|
|
with self.subTest("Slug collision between page with no parent and a child page of home-page"):
|
|
page_data = self.get_new_page_data()
|
|
page_data["slug"] = "child-page"
|
|
response = self.client.post(add_endpoint, page_data)
|
|
expected_markup = (
|
|
'<ul class="errorlist" id="id_slug_error">'
|
|
'<li>Page <a href="{}" target="_blank">child-page</a> '
|
|
"has the same url 'child-page' as current page.</li></ul>"
|
|
).format(self.get_page_change_uri("en", child_page))
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, expected_markup)
|
|
|
|
with self.subTest("Slug collision between two top-level pages"):
|
|
page_data = self.get_new_page_data()
|
|
page_data["slug"] = "page"
|
|
response = self.client.post(add_endpoint, page_data)
|
|
expected_markup = (
|
|
'<ul class="errorlist" id="id_slug_error">'
|
|
'<li>Page <a href="{}" target="_blank">page</a> '
|
|
"has the same url 'page' as current page.</li></ul>"
|
|
).format(self.get_page_change_uri("en", page))
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, expected_markup)
|
|
|
|
def test_change_child_slug_to_sibling_slug(self):
|
|
"""Changing a child page's slug to a sibling's slug is rejected (#8902)"""
|
|
parent = create_page("parent", "nav_playground.html", "en")
|
|
create_page("a", "nav_playground.html", "en", parent=parent, slug="a")
|
|
page_b = create_page("b", "nav_playground.html", "en", parent=parent, slug="b")
|
|
superuser = self.get_superuser()
|
|
page_data = self.get_new_page_data()
|
|
page_data.update({"title": "b", "slug": "a", "template": page_b.get_template("en")})
|
|
|
|
with self.login_user_context(superuser):
|
|
response = self.client.post(self.get_page_change_uri("en", page_b), page_data)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, "has the same url 'parent/a'")
|
|
self.assertEqual(PageUrl.objects.get(page=page_b, language="en").path, "parent/b")
|
|
|
|
def test_edit_page(self):
|
|
"""
|
|
Test that a page can edited via the admin
|
|
"""
|
|
superuser = self.get_superuser()
|
|
with self.login_user_context(superuser):
|
|
page_data = self.get_new_page_data()
|
|
endpoint = self.get_page_add_uri("en")
|
|
self.client.post(endpoint, page_data)
|
|
page = Page.objects.get(urls__slug=page_data["slug"])
|
|
response = self.client.get(self.get_page_change_uri("en", page))
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, "<title>Change a page</title>", html=True)
|
|
page_data["title"] = "changed title"
|
|
page_data["template"] = page.get_template("en")
|
|
response = self.client.post(self.get_page_change_uri("en", page), page_data)
|
|
page._clear_internal_cache()
|
|
self.assertRedirects(response, self.get_pages_admin_list_uri("en"))
|
|
self.assertEqual(page.get_title(), "changed title")
|
|
|
|
def test_page_redirect_field_validation(self):
|
|
superuser = self.get_superuser()
|
|
data = self.get_new_page_data()
|
|
|
|
with self.login_user_context(superuser):
|
|
self.client.post(self.get_page_add_uri("en"), data)
|
|
|
|
page = Page.objects.get(urls__slug=data["slug"])
|
|
data["template"] = page.template
|
|
endpoint = self.get_page_change_uri("en", page)
|
|
redirect_to = self.get_pages_admin_list_uri("en")
|
|
validation_error = '<ul class="errorlist" id="id_redirect_error"><li>Enter a valid URL.</li></ul>'
|
|
# Values carrying markup are rejected by ``validate_url()`` itself, before it picks
|
|
# the relative or the absolute branch, so they carry its own message.
|
|
markup_error = (
|
|
'<ul class="errorlist" id="id_redirect_error">'
|
|
"<li>Enter a valid relative or absolute URL.</li></ul>"
|
|
)
|
|
|
|
with self.subTest("Test that a redirect to the root page (valid)"):
|
|
with self.login_user_context(superuser):
|
|
data["redirect"] = "/"
|
|
response = self.client.post(endpoint, data)
|
|
self.assertRedirects(response, redirect_to)
|
|
|
|
with self.subTest("Test that a redirect to a page with an absolute URL (valid)"):
|
|
with self.login_user_context(superuser):
|
|
data["redirect"] = "/hello"
|
|
response = self.client.post(endpoint, data)
|
|
self.assertRedirects(response, redirect_to)
|
|
|
|
with self.subTest("Test that a redirect to a page with an absolute URL ending with a slash (valid)"):
|
|
with self.login_user_context(superuser):
|
|
data["redirect"] = "/hello/"
|
|
response = self.client.post(endpoint, data)
|
|
self.assertRedirects(response, redirect_to)
|
|
|
|
with self.subTest("Test that a redirect to a page with a relative URL (valid)"):
|
|
with self.login_user_context(superuser):
|
|
data["redirect"] = "../hello"
|
|
response = self.client.post(endpoint, data)
|
|
self.assertRedirects(response, redirect_to)
|
|
|
|
with self.subTest("Test that a redirect to a page with a relative URL ending with a slash (valid)"):
|
|
with self.login_user_context(superuser):
|
|
data["redirect"] = "../hello/"
|
|
response = self.client.post(endpoint, data)
|
|
self.assertRedirects(response, redirect_to)
|
|
|
|
with self.subTest("Test that a redirect to a page with a javascript: URL (invalid)"):
|
|
with self.login_user_context(superuser):
|
|
data["redirect"] = "javascript:alert(1)"
|
|
# Asserts users can't insert javascript call
|
|
response = self.client.post(endpoint, data)
|
|
self.assertContains(response, validation_error, html=True)
|
|
|
|
with self.subTest("Test that a redirect to a page with script tag as URL (invalid)"):
|
|
with self.login_user_context(superuser):
|
|
data["redirect"] = '<script>alert("test")</script>'
|
|
# Asserts users can't insert javascript call
|
|
response = self.client.post(endpoint, data)
|
|
self.assertContains(response, markup_error, html=True)
|
|
|
|
def test_meta_description_fields_from_admin(self):
|
|
"""
|
|
Test that description and keywords tags can be set via the admin
|
|
"""
|
|
superuser = self.get_superuser()
|
|
with self.login_user_context(superuser):
|
|
page_data = self.get_new_page_data()
|
|
page_data["meta_description"] = "I am a page"
|
|
self.client.post(self.get_page_add_uri("en"), page_data)
|
|
page = Page.objects.get(urls__slug=page_data["slug"])
|
|
response = self.client.get(self.get_page_change_uri("en", page))
|
|
self.assertEqual(response.status_code, 200)
|
|
page_data["template"] = page.get_template("en")
|
|
page_data["meta_description"] = "I am a duck"
|
|
response = self.client.post(self.get_page_change_uri("en", page), page_data)
|
|
self.assertRedirects(response, self.get_pages_admin_list_uri("en"))
|
|
page = Page.objects.get(urls__slug=page_data["slug"])
|
|
self.assertEqual(page.get_meta_description(), "I am a duck")
|
|
|
|
def test_meta_description_from_template_tags(self):
|
|
from django import template
|
|
|
|
superuser = self.get_superuser()
|
|
with self.login_user_context(superuser):
|
|
page_data = self.get_new_page_data()
|
|
page_data["title"] = "Hello"
|
|
page_data["meta_description"] = "I am a page"
|
|
self.client.post(self.get_page_add_uri("en"), page_data)
|
|
page = Page.objects.get(urls__slug=page_data["slug"])
|
|
self.client.post(self.get_page_change_uri("en", page), page_data)
|
|
t = template.Template(
|
|
"{% load cms_tags %}{% page_attribute title %} {% page_attribute meta_description %}"
|
|
)
|
|
req = HttpRequest()
|
|
page.save()
|
|
req.current_page = page
|
|
req.GET = {}
|
|
self.assertEqual(t.render(template.Context({"request": req})), "Hello I am a page")
|
|
|
|
def test_page_obj_change_data_from_template_tags(self):
|
|
from django import template
|
|
|
|
superuser = self.get_superuser()
|
|
with self.login_user_context(superuser):
|
|
page_data = self.get_new_page_data()
|
|
change_user = str(superuser)
|
|
# some databases don't store microseconds, so move the start flag
|
|
# back by 1 second
|
|
before_change = tz_now() + datetime.timedelta(seconds=-1)
|
|
self.client.post(self.get_page_add_uri("en"), page_data)
|
|
page = Page.objects.get(urls__slug=page_data["slug"])
|
|
self.client.post(self.get_page_change_uri("en", page), page_data)
|
|
t = template.Template(
|
|
"{% load cms_tags %}{% page_attribute changed_by %} changed "
|
|
"on {% page_attribute changed_date as page_change %}"
|
|
"{{ page_change|date:'Y-m-d\\TH:i:s' }}"
|
|
)
|
|
req = HttpRequest()
|
|
page.save()
|
|
after_change = tz_now()
|
|
req.current_page = page
|
|
req.GET = {}
|
|
|
|
actual_result = t.render(template.Context({"request": req}))
|
|
desired_result = f"{change_user} changed on {actual_result[-19:]}"
|
|
save_time = datetime.datetime.strptime(actual_result[-19:], "%Y-%m-%dT%H:%M:%S").replace(
|
|
tzinfo=datetime.timezone.utc if settings.USE_TZ else None
|
|
)
|
|
|
|
self.assertEqual(actual_result, desired_result)
|
|
# direct time comparisons are flaky, so we just check if the
|
|
# page's changed_date is within the time range taken by this test
|
|
self.assertLessEqual(before_change, save_time)
|
|
self.assertLessEqual(save_time, after_change)
|
|
|
|
def test_delete_page_confirmation(self):
|
|
superuser = self.get_superuser()
|
|
page_a = create_page("page_a", "nav_playground.html", "en")
|
|
create_page("page_a_a", "nav_playground.html", "en", parent=page_a)
|
|
page_a_b = create_page("page_a_b", "nav_playground.html", "en", parent=page_a)
|
|
create_page("page_a_b_a", "nav_playground.html", "en", parent=page_a_b)
|
|
endpoint = self.get_admin_url(Page, "delete", page_a.pk)
|
|
|
|
page_tree = [page_a] + list(page_a.get_descendant_pages())
|
|
row_markup = "<li>%s</li>"
|
|
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(endpoint)
|
|
for page in page_tree:
|
|
page_url = page.urls.filter(language="en").first()
|
|
page_markup = row_markup % str(page_url)
|
|
self.assertContains(response, page_markup, html=True)
|
|
|
|
def test_delete_page_confirmation_escapes_related_objects(self):
|
|
"""The confirmation screen lists page titles and page urls. Both are author-controlled
|
|
(a page url can be set verbatim through "Overwrite URL"), so neither may reach the
|
|
response as markup (CWE-79)."""
|
|
superuser = self.get_superuser()
|
|
homepage = create_page("home", "nav_playground.html", "en")
|
|
homepage.set_as_homepage()
|
|
page = create_page("<script>alert('title')</script>", "nav_playground.html", "en", parent=homepage)
|
|
|
|
# An overwrite url without a "/" bypasses ``validate_url`` and is stored verbatim
|
|
content = page.get_content_obj("en")
|
|
content.overwrite_url = "<img src=x onerror=alert('url')>"
|
|
content.save()
|
|
page.update_urls_from_content("en")
|
|
page._clear_internal_cache()
|
|
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(self.get_admin_url(Page, "delete", page.pk))
|
|
|
|
self.assertContains(response, "<img src=x onerror=alert('url')> (en)")
|
|
self.assertContains(response, "<script>alert('title')</script>")
|
|
self.assertNotContains(response, "<img src=x")
|
|
self.assertNotContains(response, "<script>alert(")
|
|
|
|
def test_homepage_with_children(self):
|
|
homepage = create_page("home", "nav_playground.html", "en")
|
|
homepage.set_as_homepage()
|
|
pending_child_1 = create_page(
|
|
"child-1",
|
|
"nav_playground.html",
|
|
language="en",
|
|
parent=homepage,
|
|
)
|
|
pending_child_2 = create_page(
|
|
"child-2",
|
|
"nav_playground.html",
|
|
language="en",
|
|
parent=homepage,
|
|
)
|
|
expected_tree = [
|
|
(homepage, ""),
|
|
(pending_child_1, "child-1"),
|
|
(pending_child_2, "child-2"),
|
|
]
|
|
|
|
for page, url_path in expected_tree:
|
|
page._clear_internal_cache()
|
|
self.assertEqual(page.get_path("en"), url_path)
|
|
|
|
def test_copy_page(self):
|
|
"""
|
|
Test that a page can be copied via the admin
|
|
"""
|
|
page_a = create_page("page_a", "nav_playground.html", "en")
|
|
page_a_a = create_page("page_a_a", "nav_playground.html", "en", parent=page_a, reverse_id="hello")
|
|
create_page("page_a_a_a", "nav_playground.html", "en", parent=page_a_a)
|
|
|
|
page_b = create_page("page_b", "nav_playground.html", "en")
|
|
page_b_a = create_page("page_b_b", "nav_playground.html", "en", parent=page_b)
|
|
|
|
count = Page.objects.count()
|
|
|
|
superuser = self.get_superuser()
|
|
with self.login_user_context(superuser):
|
|
self.copy_page(page_a, page_b_a)
|
|
|
|
self.assertEqual(Page.objects.count() - count, 3)
|
|
|
|
def test_copy_page_preserves_login_required(self):
|
|
source = create_page("source", "nav_playground.html", "en", login_required=True)
|
|
source_child = create_page("source-child", "nav_playground.html", "en", parent=source, login_required=True)
|
|
target = create_page("target", "nav_playground.html", "en")
|
|
|
|
with self.login_user_context(self.get_superuser()):
|
|
copied_root = self.copy_page(source, target)
|
|
|
|
copied_root.refresh_from_db()
|
|
copied_child = copied_root.get_child_pages().get()
|
|
copied_child.refresh_from_db()
|
|
|
|
self.assertTrue(copied_root.login_required)
|
|
self.assertTrue(copied_child.login_required)
|
|
self.assertTrue(source_child.login_required)
|
|
|
|
def test_copy_page_under_home(self):
|
|
"""
|
|
Users should be able to copy a page and paste under the home page.
|
|
"""
|
|
homepage = create_page("home", "nav_playground.html", "en")
|
|
homepage.set_as_homepage()
|
|
|
|
root_page_a = create_page("root-a", "nav_playground.html", "en")
|
|
|
|
with self.login_user_context(self.get_superuser()):
|
|
self.copy_page(root_page_a, homepage)
|
|
|
|
def test_copy_page_with_plugins(self):
|
|
"""
|
|
Copying a page with plugins should copy all plugins for the translation
|
|
being copied into the respective translation in the new page.
|
|
"""
|
|
cms_page = create_page("page_a_en", "nav_playground.html", "en")
|
|
placeholder = cms_page.get_placeholders("en").get(slot="body")
|
|
add_plugin(
|
|
placeholder,
|
|
plugin_type="LinkPlugin",
|
|
language="en",
|
|
name="Link {}".format("en"),
|
|
external_link="https://www.django-cms.org",
|
|
)
|
|
|
|
with self.login_user_context(self.get_superuser()):
|
|
new_page = self.copy_page(cms_page, cms_page, position=1)
|
|
new_placeholder = new_page.get_placeholders("en").get(slot="body")
|
|
self.assertTrue(new_placeholder.get_plugins("en").exists())
|
|
plugin = new_placeholder.get_plugins("en")[0].get_bound_plugin()
|
|
self.assertEqual(plugin.name, "Link en")
|
|
|
|
def test_copy_page_to_root(self):
|
|
"""
|
|
When a page is copied and its slug matches that of another page,
|
|
add "-copy-2" at the end.
|
|
"""
|
|
data = {
|
|
"position": 2,
|
|
"copy_permissions": "on",
|
|
"copy_moderation": "on",
|
|
}
|
|
superuser = self.get_superuser()
|
|
cms_page = create_page("page_a", "nav_playground.html", "en")
|
|
|
|
with self.login_user_context(superuser):
|
|
endpoint = self.get_admin_url(Page, "copy_page", cms_page.pk)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
new_slug = cms_page.get_path("en") + "-copy-2"
|
|
new_path = cms_page.get_slug("en") + "-copy-2"
|
|
|
|
self.assertEqual(
|
|
PageUrl.objects.filter(slug=new_slug, path=new_path).count(),
|
|
1,
|
|
)
|
|
|
|
def test_copy_page_to_different_site(self):
|
|
superuser = self.get_superuser()
|
|
site_2 = Site.objects.create(id=2, domain="example-2.com", name="example-2.com")
|
|
site_1_root = create_page("site 1 root", "nav_playground.html", "de")
|
|
site_2_parent = create_page("parent", "nav_playground.html", "de", site=site_2)
|
|
child_0002 = create_page(
|
|
"child-0002",
|
|
template="nav_playground.html",
|
|
language="de",
|
|
parent=site_2_parent,
|
|
site=site_2,
|
|
)
|
|
child_0003 = create_page(
|
|
"child-0003",
|
|
template="nav_playground.html",
|
|
language="de",
|
|
parent=site_2_parent,
|
|
site=site_2,
|
|
)
|
|
child_0005 = create_page(
|
|
"child-0005",
|
|
template="nav_playground.html",
|
|
language="de",
|
|
parent=site_2_parent,
|
|
site=site_2,
|
|
)
|
|
|
|
with self.login_user_context(superuser):
|
|
# Copy the root page from site 1 and insert it as first child
|
|
# of the site 2 parent.
|
|
child_0001 = self.copy_page(site_1_root, site_2_parent, position=0)
|
|
|
|
with self.login_user_context(superuser):
|
|
# Copy the root page from site 1 and insert it as fourth child
|
|
# of the site 2 parent.
|
|
child_0004 = self.copy_page(site_1_root, site_2_parent, position=3)
|
|
|
|
tree = (
|
|
(site_2_parent, "0002"),
|
|
(child_0001, "00020001"),
|
|
(child_0002, "00020002"),
|
|
(child_0003, "00020003"),
|
|
(child_0004, "00020004"),
|
|
(child_0005, "00020005"),
|
|
)
|
|
|
|
for page, path in tree:
|
|
page.refresh_from_db()
|
|
self.assertEqual(page.path, path)
|
|
self.assertEqual(page.site_id, 2)
|
|
|
|
def test_copy_page_to_different_site_fails_with_untranslated_page(self):
|
|
data = {
|
|
"position": 0,
|
|
"copy_permissions": "on",
|
|
"copy_moderation": "on",
|
|
}
|
|
superuser = self.get_superuser()
|
|
site_2 = Site.objects.create(id=2, domain="example-2.com", name="example-2.com")
|
|
site_1_root = create_page("site 1 root", "nav_playground.html", "en")
|
|
expected_response = {
|
|
"status": 400,
|
|
"content": "Error! The page you're pasting is not translated in "
|
|
"any of the languages configured by the target site.",
|
|
}
|
|
|
|
with self.settings(SITE_ID=2):
|
|
with self.login_user_context(superuser):
|
|
# Simulate the copy-dialog
|
|
endpoint = self.get_admin_url(Page, "get_copy_dialog", site_1_root.pk)
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
# Copy the root page from site 1 and insert it as the first root page
|
|
# on site 2.
|
|
endpoint = self.get_admin_url(Page, "copy_page", site_1_root.pk)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertObjectDoesNotExist(Page.objects.all(), site=site_2)
|
|
self.assertEqual(
|
|
json.loads(response.content.decode("utf8")),
|
|
expected_response,
|
|
)
|
|
|
|
def test_copy_page_to_different_site_with_no_pages(self):
|
|
data = {
|
|
"position": 0,
|
|
"copy_permissions": "on",
|
|
"copy_moderation": "on",
|
|
}
|
|
superuser = self.get_superuser()
|
|
site_2 = Site.objects.create(id=2, domain="example-2.com", name="example-2.com")
|
|
site_1_root = create_page("site 1 root", "nav_playground.html", "de")
|
|
|
|
with self.settings(SITE_ID=2):
|
|
with self.login_user_context(superuser):
|
|
# Simulate the copy-dialog
|
|
endpoint = self.get_admin_url(Page, "get_copy_dialog", site_1_root.pk)
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
# Copy the root page from site 1 and insert it as the first root page
|
|
# on site 2.
|
|
endpoint = self.get_admin_url(Page, "copy_page", site_1_root.pk)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
site_2_root = self.assertObjectExist(Page.objects.all(), site=site_2)
|
|
|
|
tree = (
|
|
(site_1_root, "0001"),
|
|
(site_2_root, "0002"),
|
|
)
|
|
|
|
for page, path in tree:
|
|
page.refresh_from_db()
|
|
self.assertEqual(page.path, path)
|
|
|
|
def test_copy_page_to_explicit_position(self):
|
|
"""
|
|
User should be able to copy a single page and paste it
|
|
in a specific location on another page tree.
|
|
"""
|
|
superuser = self.get_superuser()
|
|
parent = create_page("parent", "nav_playground.html", "en")
|
|
child_0002 = create_page("child-0002", "nav_playground.html", "en", parent=parent)
|
|
child_0003 = create_page("child-0003", "nav_playground.html", "en", parent=parent)
|
|
child_0005 = create_page("child-0005", "nav_playground.html", "en", parent=parent)
|
|
child_0004 = create_page("child-0004", "nav_playground.html", "en")
|
|
|
|
with self.login_user_context(superuser):
|
|
# Copy the 0005 page and insert it as first child of parent
|
|
child_0001 = self.copy_page(child_0005, parent, position=0)
|
|
|
|
with self.login_user_context(superuser):
|
|
# Copy the 0004 page and insert it as fourth child of parent
|
|
child_0004 = self.copy_page(child_0004, parent, position=3)
|
|
|
|
tree = (
|
|
(parent, "0001"),
|
|
(child_0001, "00010001"),
|
|
(child_0002, "00010002"),
|
|
(child_0003, "00010003"),
|
|
(child_0004, "00010004"),
|
|
(child_0005, "00010005"),
|
|
)
|
|
|
|
for page, path in tree:
|
|
page.refresh_from_db()
|
|
self.assertEqual(page.path, path)
|
|
|
|
def test_copy_page_tree_to_explicit_position(self):
|
|
"""
|
|
User should be able to copy a page with descendants and paste it
|
|
in a specific location on another page tree.
|
|
"""
|
|
superuser = self.get_superuser()
|
|
parent = create_page("parent", "nav_playground.html", "en")
|
|
child_0002 = create_page("child-0002", "nav_playground.html", "en", parent=parent)
|
|
child_0003 = create_page("child-0003", "nav_playground.html", "en", parent=parent)
|
|
child_0005 = create_page("child-0005", "nav_playground.html", "en", parent=parent)
|
|
create_page("child-00050001", "nav_playground.html", "en", parent=child_0005)
|
|
create_page("child-00050002", "nav_playground.html", "en", parent=child_0005)
|
|
create_page("child-00050003", "nav_playground.html", "en", parent=child_0005)
|
|
child_0004 = create_page("child-0004", "nav_playground.html", "en")
|
|
create_page("child-00040001", "nav_playground.html", "en", parent=child_0004)
|
|
create_page("child-00040002", "nav_playground.html", "en", parent=child_0004)
|
|
create_page("child-00040003", "nav_playground.html", "en", parent=child_0004)
|
|
|
|
with self.login_user_context(superuser):
|
|
# Copy the 0005 page and insert it as first child of parent
|
|
child_0001 = self.copy_page(child_0005, parent, position=0)
|
|
child_pages = list(child_0001.get_child_pages())
|
|
child_00010001 = child_pages[0]
|
|
child_00010002 = child_pages[1]
|
|
child_00010003 = child_pages[2]
|
|
|
|
with self.login_user_context(superuser):
|
|
# Copy the 0004 page and insert it as fourth child of parent
|
|
child_0004 = self.copy_page(child_0004, parent, position=3)
|
|
child_pages = list(child_0004.get_child_pages())
|
|
child_00040001 = child_pages[0]
|
|
child_00040002 = child_pages[1]
|
|
child_00040003 = child_pages[2]
|
|
|
|
tree = (
|
|
(parent, "0001"),
|
|
(child_0001, "00010001"),
|
|
(child_00010001, "000100010001"),
|
|
(child_00010002, "000100010002"),
|
|
(child_00010003, "000100010003"),
|
|
(child_0002, "00010002"),
|
|
(child_0003, "00010003"),
|
|
(child_0004, "00010004"),
|
|
(child_00040001, "000100040001"),
|
|
(child_00040002, "000100040002"),
|
|
(child_00040003, "000100040003"),
|
|
(child_0005, "00010005"),
|
|
)
|
|
|
|
for page, path in tree:
|
|
page.refresh_from_db()
|
|
self.assertEqual(page.path, path)
|
|
|
|
def test_copy_self_page(self):
|
|
"""
|
|
Test that a page can be copied via the admin
|
|
"""
|
|
page_a = create_page("page_a", "nav_playground.html", "en")
|
|
page_b = create_page("page_b", "nav_playground.html", "en", parent=page_a)
|
|
page_c = create_page("page_c", "nav_playground.html", "en", parent=page_b)
|
|
with self.login_user_context(self.get_superuser()):
|
|
self.copy_page(page_b, page_b, position=1)
|
|
self.assertEqual(Page.objects.all().count(), 5)
|
|
self.assertEqual(page_b.get_child_pages().count(), 2)
|
|
page_d = page_b.get_child_pages()[1]
|
|
page_e = page_d.get_child_pages()[0]
|
|
self.assertEqual(page_d.path, "000100010002")
|
|
self.assertEqual(page_e.path, "0001000100020001")
|
|
page_e.delete()
|
|
page_d.delete()
|
|
with self.login_user_context(self.get_superuser()):
|
|
self.copy_page(page_b, page_c)
|
|
page_c.refresh_from_db()
|
|
self.assertEqual(page_c.get_child_pages().count(), 1)
|
|
self.assertEqual(page_b.get_child_pages().count(), 1)
|
|
page_ids = list(page_c.get_descendant_pages().values_list("pk", flat=True))
|
|
page_c.get_descendant_pages().delete()
|
|
Page.objects.filter(pk__in=page_ids).delete()
|
|
self.assertEqual(Page.objects.all().count(), 3)
|
|
page_b = page_b.reload()
|
|
page_c = page_c.reload()
|
|
with self.login_user_context(self.get_superuser()):
|
|
self.copy_page(page_b, page_c, position=0)
|
|
|
|
def test_copy_page_tree_with_apphook(self):
|
|
"""
|
|
Regression test for issue #5899.
|
|
Copying a page tree where a page has an apphook should succeed,
|
|
with the apphook fields cleared on the copied pages.
|
|
"""
|
|
root_page = create_page("root", "nav_playground.html", "en")
|
|
child_with_apphook = create_page(
|
|
"child_with_apphook",
|
|
"nav_playground.html",
|
|
"en",
|
|
parent=root_page,
|
|
)
|
|
create_page(
|
|
"grandchild",
|
|
"nav_playground.html",
|
|
"en",
|
|
parent=child_with_apphook,
|
|
)
|
|
|
|
child_with_apphook.application_urls = "SampleApp"
|
|
child_with_apphook.application_namespace = "sample_app_instance"
|
|
child_with_apphook.save()
|
|
|
|
target_page = create_page("target", "nav_playground.html", "en")
|
|
|
|
initial_count = Page.objects.count()
|
|
|
|
superuser = self.get_superuser()
|
|
with self.login_user_context(superuser):
|
|
copied_root = self.copy_page(root_page, target_page, position=0)
|
|
|
|
self.assertEqual(Page.objects.count(), initial_count + 3)
|
|
|
|
copied_children = list(copied_root.get_child_pages())
|
|
self.assertEqual(len(copied_children), 1)
|
|
copied_child = copied_children[0]
|
|
|
|
self.assertIsNone(copied_child.application_urls)
|
|
self.assertIsNone(copied_child.application_namespace)
|
|
self.assertIsNone(copied_child.navigation_extenders)
|
|
|
|
child_with_apphook.refresh_from_db()
|
|
self.assertEqual(child_with_apphook.application_urls, "SampleApp")
|
|
self.assertEqual(child_with_apphook.application_namespace, "sample_app_instance")
|
|
|
|
def test_move_page(self):
|
|
superuser = self.get_superuser()
|
|
add_endpoint = self.get_page_add_uri("en")
|
|
with self.login_user_context(superuser):
|
|
page_home = self.get_new_page_data()
|
|
self.client.post(add_endpoint, page_home)
|
|
page_data1 = self.get_new_page_data()
|
|
self.client.post(add_endpoint, page_data1)
|
|
page_data2 = self.get_new_page_data()
|
|
self.client.post(add_endpoint, page_data2)
|
|
page_data3 = self.get_new_page_data()
|
|
self.client.post(add_endpoint, page_data3)
|
|
pages = list(Page.objects.order_by("path"))
|
|
home = pages[0]
|
|
page1 = pages[1]
|
|
page2 = pages[2]
|
|
page3 = pages[3]
|
|
|
|
# move pages
|
|
response = self.client.post(URL_CMS_PAGE_MOVE % page3.pk, {"target": page2.pk, "position": "0"})
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
page3 = Page.objects.get(pk=page3.pk)
|
|
response = self.client.post(URL_CMS_PAGE_MOVE % page2.pk, {"target": page1.pk, "position": "0"})
|
|
self.assertEqual(response.status_code, 200)
|
|
# check page2 path and url
|
|
page2 = Page.objects.get(pk=page2.pk)
|
|
self.assertEqual(page2.get_path("en"), page_data1["slug"] + "/" + page_data2["slug"])
|
|
self.assertEqual(
|
|
page2.get_absolute_url(), self.get_pages_root() + page_data1["slug"] + "/" + page_data2["slug"] + "/"
|
|
)
|
|
# check page3 path and url
|
|
page3 = Page.objects.get(pk=page3.pk)
|
|
self.assertEqual(
|
|
page3.get_path("en"), page_data1["slug"] + "/" + page_data2["slug"] + "/" + page_data3["slug"]
|
|
)
|
|
self.assertEqual(
|
|
page3.get_absolute_url(),
|
|
self.get_pages_root() + page_data1["slug"] + "/" + page_data2["slug"] + "/" + page_data3["slug"] + "/",
|
|
)
|
|
|
|
# Remove home page
|
|
home.delete()
|
|
|
|
# Promote page1 to be the new homepage
|
|
page1.set_as_homepage()
|
|
self.assertEqual(page1.get_path("en"), "")
|
|
# check that page2 and page3 url have changed
|
|
page2 = Page.objects.get(pk=page2.pk)
|
|
page3 = Page.objects.get(pk=page3.pk)
|
|
# set page2 as root and check path of 1 and 3
|
|
response = self.client.post(URL_CMS_PAGE_MOVE % page2.pk, {"position": "0"})
|
|
self.assertEqual(response.status_code, 200)
|
|
page1 = Page.objects.get(pk=page1.pk)
|
|
self.assertEqual(page1.get_path("en"), "")
|
|
page2 = Page.objects.get(pk=page2.pk)
|
|
self.assertFalse(page2.is_home)
|
|
self.assertEqual(page2.get_path("en"), page_data2["slug"])
|
|
page3 = Page.objects.get(pk=page3.pk)
|
|
self.assertEqual(page3.get_path("en"), page_data2["slug"] + "/" + page_data3["slug"])
|
|
|
|
def test_user_cant_nest_home_page(self):
|
|
"""
|
|
Users should not be able to move the home-page
|
|
inside another node of the tree.
|
|
"""
|
|
homepage = create_page("home", "nav_playground.html", "en")
|
|
homepage.set_as_homepage()
|
|
home_sibling_1 = create_page("root-1", "nav_playground.html", "en")
|
|
|
|
payload = {"id": homepage.pk, "position": 0, "target": home_sibling_1}
|
|
|
|
with self.login_user_context(self.get_superuser()):
|
|
endpoint = self.get_admin_url(Page, "move_page", homepage.pk)
|
|
response = self.client.post(endpoint, payload)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.json().get("status", 400), 400)
|
|
|
|
def test_move_home_page(self):
|
|
"""
|
|
Users should be able to move the home-page
|
|
anywhere on the root of the tree.
|
|
"""
|
|
homepage = create_page("home", "nav_playground.html", "en")
|
|
homepage.set_as_homepage()
|
|
home_child_1 = create_page(
|
|
"child-1",
|
|
"nav_playground.html",
|
|
language="en",
|
|
parent=homepage,
|
|
)
|
|
home_child_2 = create_page(
|
|
"child-2",
|
|
"nav_playground.html",
|
|
language="en",
|
|
parent=homepage,
|
|
)
|
|
home_sibling_1 = create_page("root-1", "nav_playground.html", "en")
|
|
|
|
expected_tree = [
|
|
# Sadly treebeard doesn't switch the paths
|
|
(home_sibling_1, "0002", "root-1"),
|
|
(homepage, "0003", ""),
|
|
(home_child_1, "00030001", "child-1"),
|
|
(home_child_2, "00030002", "child-2"),
|
|
]
|
|
|
|
with self.login_user_context(self.get_superuser()):
|
|
# Moves the homepage to the second position in the tree
|
|
data = {"id": homepage.pk, "position": 1}
|
|
endpoint = self.get_admin_url(Page, "move_page", homepage.pk)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
for page, page_path, url_path in expected_tree:
|
|
page._clear_internal_cache()
|
|
page.refresh_from_db()
|
|
self.assertEqual(page.path, page_path)
|
|
self.assertEqual(page.get_path("en"), url_path)
|
|
|
|
def test_move_page_integrity(self):
|
|
superuser = self.get_superuser()
|
|
with self.login_user_context(superuser):
|
|
page_home = self.get_new_page_data()
|
|
self.client.post(self.get_page_add_uri("en"), page_home)
|
|
|
|
# Create parent page
|
|
page_root = create_page("Parent", "col_three.html", "en")
|
|
|
|
# Create child pages
|
|
create_page(
|
|
"Child 1",
|
|
template=constants.TEMPLATE_INHERITANCE_MAGIC,
|
|
language="en",
|
|
parent=page_root,
|
|
)
|
|
|
|
create_page(
|
|
"Child 2",
|
|
template=constants.TEMPLATE_INHERITANCE_MAGIC,
|
|
language="en",
|
|
parent=page_root,
|
|
)
|
|
|
|
# Create two root pages that ware meant as child pages
|
|
page_child_3 = create_page("Child 3", "col_three.html", "en")
|
|
page_child_4 = create_page("Child 4", "col_three.html", "en")
|
|
|
|
# Correct our mistake.
|
|
# Move page_child_3 to be child of parent page
|
|
data = {
|
|
"id": page_child_3.pk,
|
|
"target": page_root.pk,
|
|
"position": "0",
|
|
}
|
|
response = self.client.post(
|
|
URL_CMS_PAGE_MOVE % page_child_3.pk,
|
|
data,
|
|
)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
# Move page_child_4 to be child of parent page
|
|
data = {
|
|
"id": page_child_4.pk,
|
|
"target": page_root.pk,
|
|
"position": "0",
|
|
}
|
|
response = self.client.post(
|
|
URL_CMS_PAGE_MOVE % page_child_4.pk,
|
|
data,
|
|
)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
page_root = page_root.reload()
|
|
page_child_4 = page_child_4.reload()
|
|
|
|
# Ensure move worked
|
|
self.assertEqual(page_root.get_descendants().count(), 4)
|
|
|
|
def test_edit_page_other_site_and_language(self):
|
|
"""
|
|
Test that a page can edited via the admin when your current site is
|
|
different from the site you are editing and the language isn't available
|
|
for the current site.
|
|
"""
|
|
self.assertEqual(Site.objects.all().count(), 1)
|
|
site = Site.objects.create(domain="otherlang", name="otherlang", pk=2)
|
|
# Change site for this session
|
|
page_data = self.get_new_page_data()
|
|
page_data["title"] = "changed title"
|
|
self.assertEqual(site.pk, 2)
|
|
TESTLANG = get_cms_setting("LANGUAGES")[site.pk][0]["code"]
|
|
TESTSITE = site.pk
|
|
page_data["language"] = TESTLANG
|
|
page_data["site"] = TESTSITE
|
|
superuser = self.get_superuser()
|
|
with self.login_user_context(superuser):
|
|
response = self.client.post(self.get_page_add_uri("en"), page_data)
|
|
self.assertRedirects(response, self.get_pages_admin_list_uri(TESTLANG, site_id=TESTSITE))
|
|
page = Page.objects.get(urls__slug=page_data["slug"])
|
|
with LanguageOverride(TESTLANG):
|
|
self.assertEqual(page.get_title(), "changed title")
|
|
|
|
def test_get_page_from_request_cached(self):
|
|
mock_page = "hello world"
|
|
request = self.get_request(admin_reverse("sampleapp_category_change", args=(1,)))
|
|
request._current_page_cache = mock_page
|
|
page = get_page_from_request(request)
|
|
self.assertEqual(page, mock_page)
|
|
|
|
@override_settings(CMS_PERMISSION=False)
|
|
def test_set_overwrite_url(self):
|
|
superuser = self.get_superuser()
|
|
cms_page = create_page("page", "nav_playground.html", "en")
|
|
translation = cms_page.get_content_obj("en", fallback=False)
|
|
expected = (
|
|
'<input type="text" name="overwrite_url" value="new-url" '
|
|
'maxlength="255" aria-describedby="id_overwrite_url_helptext" '
|
|
'id="id_overwrite_url">'
|
|
)
|
|
changelist = self.get_pages_admin_list_uri()
|
|
endpoint = self.get_page_change_uri("en", cms_page)
|
|
|
|
with self.login_user_context(superuser):
|
|
page_data = {
|
|
"title": translation.title,
|
|
"slug": cms_page.get_slug("en"),
|
|
"overwrite_url": "/new-url/",
|
|
"template": translation.template,
|
|
}
|
|
response = self.client.post(endpoint, page_data)
|
|
self.assertRedirects(response, changelist)
|
|
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(endpoint)
|
|
self.assertContains(response, expected, html=True)
|
|
|
|
@override_settings(CMS_PERMISSION=False)
|
|
def test_set_existing_overwrite_url(self):
|
|
superuser = self.get_superuser()
|
|
|
|
create_page("home", "nav_playground.html", "en")
|
|
boo = create_page("boo", "nav_playground.html", "en")
|
|
hoo = create_page("hoo", "nav_playground.html", "en")
|
|
translation = hoo.get_content_obj("en", fallback=False)
|
|
expected_error = (
|
|
'<ul class="errorlist" id="id_overwrite_url_error"><li>Page '
|
|
'<a href="{}" target="_blank">boo</a> '
|
|
"has the same url 'boo' as current page \"hoo\".</li></ul>"
|
|
).format(self.get_page_change_uri("en", boo))
|
|
|
|
with self.login_user_context(superuser):
|
|
endpoint = self.get_page_change_uri("en", hoo)
|
|
page_data = {
|
|
"title": translation.title,
|
|
"slug": hoo.get_slug("en"),
|
|
"overwrite_url": "/boo/",
|
|
"template": translation.template,
|
|
}
|
|
response = self.client.post(endpoint, page_data)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, expected_error, html=True)
|
|
|
|
@override_settings(CMS_PERMISSION=False)
|
|
def test_remove_overwrite_url(self):
|
|
superuser = self.get_superuser()
|
|
cms_page = create_page(
|
|
"page",
|
|
"nav_playground.html",
|
|
language="en",
|
|
overwrite_url="/new-url/",
|
|
)
|
|
translation = cms_page.get_content_obj("en", fallback=False)
|
|
expected = (
|
|
'<input type="text" name="overwrite_url" maxlength="255" '
|
|
'aria-describedby="id_overwrite_url_helptext" id="id_overwrite_url">'
|
|
)
|
|
changelist = self.get_pages_admin_list_uri()
|
|
endpoint = self.get_page_change_uri("en", cms_page)
|
|
|
|
# control test
|
|
self.assertTrue(cms_page.urls.filter(path="new-url").exists())
|
|
|
|
with self.login_user_context(superuser):
|
|
page_data = {
|
|
"title": translation.title,
|
|
"slug": cms_page.get_slug("en"),
|
|
"overwrite_url": "",
|
|
"template": translation.template,
|
|
}
|
|
response = self.client.post(endpoint, page_data)
|
|
self.assertRedirects(response, changelist)
|
|
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(endpoint)
|
|
self.assertContains(response, expected, html=True)
|
|
|
|
@override_settings(CMS_PERMISSION=False)
|
|
def test_slug_stored_on_page_content(self):
|
|
# The slug and overwrite URL are authored on the PageContent object;
|
|
# the PageUrl is derived from it.
|
|
superuser = self.get_superuser()
|
|
cms_page = create_page("page", "nav_playground.html", "en")
|
|
translation = cms_page.get_content_obj("en", fallback=False)
|
|
changelist = self.get_pages_admin_list_uri()
|
|
endpoint = self.get_page_change_uri("en", cms_page)
|
|
|
|
self.assertEqual(translation.slug, "page")
|
|
|
|
with self.login_user_context(superuser):
|
|
page_data = {
|
|
"title": translation.title,
|
|
"slug": "new-slug",
|
|
"overwrite_url": "",
|
|
"template": translation.template,
|
|
}
|
|
response = self.client.post(endpoint, page_data)
|
|
self.assertRedirects(response, changelist)
|
|
|
|
translation.refresh_from_db()
|
|
self.assertEqual(translation.slug, "new-slug")
|
|
# The content is public (no versioning package), so the URL follows.
|
|
self.assertEqual(cms_page.reload().get_slug("en"), "new-slug")
|
|
|
|
@override_settings(CMS_PERMISSION=False)
|
|
def test_url_not_synced_for_non_public_content(self):
|
|
# When the edited content is not publicly visible (as with a draft
|
|
# version created by a versioning package), saving a new slug is stored
|
|
# on the content but must not touch the page's published URL.
|
|
superuser = self.get_superuser()
|
|
cms_page = create_page("page", "nav_playground.html", "en")
|
|
translation = cms_page.get_content_obj("en", fallback=False)
|
|
changelist = self.get_pages_admin_list_uri()
|
|
endpoint = self.get_page_change_uri("en", cms_page)
|
|
|
|
with self.login_user_context(superuser):
|
|
page_data = {
|
|
"title": "A new title",
|
|
"slug": "a-changed-slug",
|
|
"overwrite_url": "",
|
|
"template": translation.template,
|
|
}
|
|
with patch.object(PageContent, "is_public", return_value=False):
|
|
response = self.client.post(endpoint, page_data)
|
|
self.assertRedirects(response, changelist)
|
|
|
|
# The published URL is untouched ...
|
|
self.assertEqual(cms_page.get_slug("en"), "page")
|
|
self.assertFalse(cms_page.urls.filter(slug="a-changed-slug").exists())
|
|
# ... while the content carries the new slug and other saved fields.
|
|
translation.refresh_from_db()
|
|
self.assertEqual(translation.slug, "a-changed-slug")
|
|
self.assertEqual(translation.title, "A new title")
|
|
|
|
@override_settings(CMS_PERMISSION=False)
|
|
def test_update_urls_from_content(self):
|
|
# The publish-time hook of versioning packages: derives the PageUrl
|
|
# from the publicly visible content and updates descendant paths.
|
|
cms_page = create_page("page", "nav_playground.html", "en", slug="page")
|
|
child = create_page("child", "nav_playground.html", "en", parent=cms_page, slug="child")
|
|
translation = cms_page.get_content_obj("en", fallback=False)
|
|
|
|
translation.update(slug="renamed")
|
|
cms_page.update_urls_from_content("en")
|
|
|
|
self.assertEqual(cms_page.reload().get_slug("en"), "renamed")
|
|
self.assertEqual(child.reload().get_path("en"), "renamed/child")
|
|
|
|
# An overwrite URL on the content wins over the derived path.
|
|
translation.update(overwrite_url="somewhere/else")
|
|
cms_page.update_urls_from_content("en")
|
|
|
|
url = cms_page.reload().get_url("en")
|
|
self.assertEqual(url.path, "somewhere/else")
|
|
self.assertFalse(url.managed)
|
|
|
|
@override_settings(CMS_PERMISSION=False)
|
|
def test_update_urls_from_content_without_public_content(self):
|
|
# Without publicly visible content the path is invalidated so the page
|
|
# stops resolving, but the slug stays reserved.
|
|
cms_page = create_page("page", "nav_playground.html", "en", slug="page")
|
|
|
|
with patch.object(PageContent.objects, "filter", return_value=PageContent.objects.none()):
|
|
cms_page.update_urls_from_content("en")
|
|
|
|
url = cms_page.urls.get(language="en")
|
|
self.assertIsNone(url.path)
|
|
self.assertEqual(url.slug, "page")
|
|
|
|
@override_settings(CMS_PERMISSION=False)
|
|
def test_update_urls_from_content_updates_deep_descendants(self):
|
|
# The level-based descendant update covers the whole subtree; pages
|
|
# below an overwritten URL derive from its fixed path.
|
|
cms_page = create_page("page", "nav_playground.html", "en", slug="page")
|
|
child = create_page("child", "nav_playground.html", "en", parent=cms_page, slug="child")
|
|
grandchild = create_page("grandchild", "nav_playground.html", "en", parent=child, slug="grandchild")
|
|
overwritten = create_page(
|
|
"fixed", "nav_playground.html", "en", parent=child, slug="fixed", overwrite_url="fixed/url"
|
|
)
|
|
under_overwritten = create_page("leaf", "nav_playground.html", "en", parent=overwritten, slug="leaf")
|
|
|
|
cms_page.get_content_obj("en", fallback=False).update(slug="renamed")
|
|
cms_page.update_urls_from_content("en")
|
|
|
|
self.assertEqual(child.reload().get_path("en"), "renamed/child")
|
|
self.assertEqual(grandchild.reload().get_path("en"), "renamed/child/grandchild")
|
|
self.assertEqual(overwritten.reload().get_path("en"), "fixed/url")
|
|
self.assertEqual(under_overwritten.reload().get_path("en"), "fixed/url/leaf")
|
|
|
|
@override_settings(CMS_PERMISSION=False)
|
|
def test_page_url_path_unique_per_site_in_database(self):
|
|
# The database enforces path uniqueness per site and language ...
|
|
create_page("page", "nav_playground.html", "en", slug="page")
|
|
other = create_page("other", "nav_playground.html", "en", slug="other")
|
|
|
|
with self.assertRaises(IntegrityError), transaction.atomic():
|
|
# a queryset update bypasses the application-level checks
|
|
other.urls.filter(language="en").update(path="page")
|
|
|
|
# ... while any number of unreachable pages (path=None) may coexist
|
|
third = create_page("third", "nav_playground.html", "en", slug="third")
|
|
other.urls.filter(language="en").update(path=None)
|
|
third.urls.filter(language="en").update(path=None)
|
|
self.assertEqual(PageUrl.objects.filter(path__isnull=True, language="en").count(), 2)
|
|
|
|
@override_settings(CMS_PERMISSION=False)
|
|
def test_unpublished_parent_invalidates_child_urls(self):
|
|
# When a parent loses its path (e.g. it is unpublished), its children
|
|
# become unreachable too: their paths are invalidated and
|
|
# get_absolute_url returns None instead of a fabricated slug-only url.
|
|
parent = create_page("parent", "nav_playground.html", "en", slug="parent")
|
|
child = create_page("child", "nav_playground.html", "en", parent=parent, slug="child")
|
|
|
|
with patch.object(PageContent.objects, "filter", return_value=PageContent.objects.none()):
|
|
parent.update_urls_from_content("en")
|
|
|
|
child = child.reload()
|
|
url = child.urls.get(language="en")
|
|
self.assertIsNone(url.path)
|
|
self.assertEqual(url.slug, "child")
|
|
self.assertIsNone(child.get_absolute_url("en"))
|
|
|
|
# Saving or publishing the child while the parent has no path keeps
|
|
# the child unreachable instead of exposing it at a slug-only path.
|
|
child.update_urls_from_content("en")
|
|
|
|
url = child.urls.get(language="en")
|
|
self.assertIsNone(url.path)
|
|
self.assertIsNone(child.get_absolute_url("en"))
|
|
|
|
@override_settings(CMS_PERMISSION=False)
|
|
def test_advanced_settings_form_apphook(self):
|
|
superuser = self.get_superuser()
|
|
cms_page = create_page("app", "nav_playground.html", "en")
|
|
cms_pages = Page.objects.filter(pk=cms_page.pk)
|
|
redirect_to = self.get_pages_admin_list_uri(site_id=cms_page.site_id)
|
|
endpoint = self.get_admin_url(Page, "advanced", cms_page.pk)
|
|
page_data = {
|
|
"reverse_id": "",
|
|
"navigation_extenders": "",
|
|
"application_urls": "SampleApp",
|
|
"application_namespace": "sampleapp",
|
|
}
|
|
|
|
with self.login_user_context(superuser):
|
|
# set the apphook
|
|
response = self.client.post(endpoint, page_data)
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertEqual(
|
|
cms_pages.filter(
|
|
application_urls="SampleApp",
|
|
application_namespace="sampleapp",
|
|
).count(),
|
|
1,
|
|
)
|
|
|
|
with self.login_user_context(superuser):
|
|
# remove the apphook
|
|
page_data["application_urls"] = ""
|
|
page_data["application_namespace"] = ""
|
|
response = self.client.post(endpoint, page_data)
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertEqual(
|
|
cms_pages.filter(
|
|
application_urls="",
|
|
application_namespace=None,
|
|
).count(),
|
|
1,
|
|
)
|
|
|
|
@override_settings(
|
|
CMS_APPHOOKS=[
|
|
"cms.test_utils.project.sampleapp.cms_apps.SampleApp",
|
|
"cms.test_utils.project.sampleapp.cms_apps.SampleAppWithConfig",
|
|
],
|
|
CMS_PERMISSION=False,
|
|
)
|
|
def test_advanced_settings_form_apphook_config(self):
|
|
clear_app_resolvers()
|
|
clear_url_caches()
|
|
|
|
if "cms.test_utils.project.sampleapp.cms_apps" in sys.modules:
|
|
del sys.modules["cms.test_utils.project.sampleapp.cms_apps"]
|
|
|
|
self.apphook_clear()
|
|
|
|
superuser = self.get_superuser()
|
|
app_config = SampleAppConfig.objects.create(namespace="sample")
|
|
cms_page = create_page("app", "nav_playground.html", "en")
|
|
cms_pages = Page.objects.filter(pk=cms_page.pk)
|
|
redirect_to = self.get_pages_admin_list_uri(site_id=cms_page.site_id)
|
|
endpoint = self.get_admin_url(Page, "advanced", cms_page.pk)
|
|
page_data = {
|
|
"reverse_id": "",
|
|
"navigation_extenders": "",
|
|
"application_urls": "SampleAppWithConfig",
|
|
"application_configs": app_config.pk,
|
|
"application_namespace": "sampleapp",
|
|
}
|
|
|
|
with self.login_user_context(superuser):
|
|
# set the apphook config
|
|
response = self.client.post(endpoint, page_data)
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertEqual(
|
|
cms_pages.filter(
|
|
application_urls="SampleAppWithConfig",
|
|
application_namespace=app_config.namespace,
|
|
).count(),
|
|
1,
|
|
)
|
|
|
|
with self.login_user_context(superuser):
|
|
# change from apphook with config to normal apphook
|
|
page_data["application_urls"] = "SampleApp"
|
|
page_data["application_namespace"] = "sampleapp"
|
|
response = self.client.post(endpoint, page_data)
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertEqual(
|
|
cms_pages.filter(
|
|
application_urls="SampleApp",
|
|
application_namespace="sampleapp",
|
|
).count(),
|
|
1,
|
|
)
|
|
|
|
with self.login_user_context(superuser):
|
|
# set the apphook config again
|
|
page_data["application_urls"] = "SampleAppWithConfig"
|
|
page_data["application_namespace"] = "sampleapp"
|
|
response = self.client.post(endpoint, page_data)
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertEqual(
|
|
cms_pages.filter(
|
|
application_urls="SampleAppWithConfig",
|
|
application_namespace=app_config.namespace,
|
|
).count(),
|
|
1,
|
|
)
|
|
|
|
with self.login_user_context(superuser):
|
|
# change the apphook config to an invalid value
|
|
expected_error = '<ul class="errorlist"><li>Invalid application config value</li></ul>'
|
|
page_data["application_configs"] = "2"
|
|
response = self.client.post(endpoint, page_data)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, expected_error)
|
|
self.assertEqual(
|
|
cms_pages.filter(
|
|
application_urls="SampleAppWithConfig",
|
|
application_namespace=app_config.namespace,
|
|
).count(),
|
|
1,
|
|
)
|
|
|
|
with self.login_user_context(superuser):
|
|
# remove the apphook
|
|
page_data["application_urls"] = ""
|
|
page_data["application_namespace"] = ""
|
|
response = self.client.post(endpoint, page_data)
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertEqual(
|
|
cms_pages.filter(
|
|
application_urls="",
|
|
application_namespace=None,
|
|
).count(),
|
|
1,
|
|
)
|
|
clear_app_resolvers()
|
|
clear_url_caches()
|
|
|
|
if "cms.test_utils.project.sampleapp.cms_apps" in sys.modules:
|
|
del sys.modules["cms.test_utils.project.sampleapp.cms_apps"]
|
|
self.apphook_clear()
|
|
|
|
def test_advanced_settings_view_on_site(self):
|
|
"""Advanced Page Settings `View on Site` object tool links to the Page's current language
|
|
content preview url"""
|
|
|
|
superuser = self.get_superuser()
|
|
cms_page = create_page("app", "nav_playground.html", "en")
|
|
cms_page_content = cms_page.get_content_obj(language="en")
|
|
endpoint = self.get_admin_url(Page, "advanced", cms_page.pk)
|
|
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(endpoint)
|
|
|
|
self.assertContains(response, get_object_edit_url(cms_page_content, language="en"))
|
|
|
|
def test_form_url_page_change(self):
|
|
superuser = self.get_superuser()
|
|
with self.login_user_context(superuser):
|
|
content_admin = PageContentAdmin(PageContent, admin.site)
|
|
page = self.get_page()
|
|
content = self.get_pagecontent_obj(page, "en")
|
|
form_url = self.get_page_change_uri("en", page)
|
|
# Middleware is needed to correctly setup the environment for the admin
|
|
request = self.get_request()
|
|
middleware = CurrentUserMiddleware(lambda req: HttpResponse(""))
|
|
middleware(request)
|
|
response = content_admin.change_view(
|
|
request,
|
|
str(content.pk),
|
|
form_url=form_url,
|
|
)
|
|
self.assertTrue("form_url" in response.context_data)
|
|
self.assertEqual(response.context_data["form_url"], form_url)
|
|
|
|
def test_pagecontent_slug_needs_no_extra_queries(self):
|
|
# slug and overwrite_url live on the PageContent object itself, so
|
|
# read-only admin rendering needs no PageUrl lookups.
|
|
page1 = self.get_page()
|
|
content1 = self.get_pagecontent_obj(page1, "en")
|
|
page2 = self.get_page()
|
|
content2 = self.get_pagecontent_obj(page2, "en")
|
|
|
|
with self.assertNumQueries(0):
|
|
self.assertNotEqual(content1.slug, content2.slug)
|
|
self.assertIsNone(content1.overwrite_url)
|
|
|
|
def test_change_view_shows_language_tabs_for_latest_content(self):
|
|
"""The page content change view offers the language selector for the latest content."""
|
|
superuser = self.get_superuser()
|
|
page = self.get_page()
|
|
content = self.get_pagecontent_obj(page, "en")
|
|
change_url = admin_reverse("cms_pagecontent_change", args=(content.pk,))
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(change_url)
|
|
self.assertContains(response, 'id="page_form_lang_tabs"')
|
|
|
|
def test_change_view_drops_language_tabs_for_non_latest_content(self):
|
|
"""The page content change view drops the language selector when an older (non-latest)
|
|
content object is shown. Switching languages back and forth would otherwise silently bring
|
|
up the latest content instead - confusing UX."""
|
|
superuser = self.get_superuser()
|
|
page = self.get_page()
|
|
content = self.get_pagecontent_obj(page, "en")
|
|
change_url = admin_reverse("cms_pagecontent_change", args=(content.pk,))
|
|
# Simulate a versioning package: the latest content for this language differs from the
|
|
# content object being shown.
|
|
fake_latest = type("FakeContent", (), {"pk": content.pk + 1000})()
|
|
with patch("cms.models.pagemodel.Page.get_admin_content", return_value=fake_latest):
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(change_url)
|
|
self.assertNotContains(response, 'id="page_form_lang_tabs"')
|
|
|
|
def _parse_page_tree(self, response, parser_class):
|
|
content = response.content
|
|
content = content.decode(response.charset)
|
|
|
|
def _parse_html(html):
|
|
parser = parser_class()
|
|
parser.feed(html)
|
|
parser.close()
|
|
document = parser.root
|
|
document.finalize()
|
|
# Removing ROOT element if it's not necessary
|
|
if len(document.children) == 1:
|
|
if not isinstance(document.children[0], str):
|
|
document = document.children[0]
|
|
return document
|
|
|
|
try:
|
|
dom = _parse_html(content)
|
|
except HTMLParseError as e:
|
|
standardMsg = "{}\n{}".format("Response's content is not valid HTML", e.msg)
|
|
self.fail(self._formatMessage(None, standardMsg))
|
|
return dom
|
|
|
|
def test_page_tree_regression_5892(self):
|
|
# ref: https://github.com/divio/django-cms/issues/5892
|
|
# Tests the escaping of characters for a german translation
|
|
# in the page tree.
|
|
superuser = self.get_superuser()
|
|
|
|
create_page("Home", "nav_playground.html", "en")
|
|
alpha = create_page("Alpha", "nav_playground.html", "en")
|
|
create_page("Beta", "nav_playground.html", "en", parent=alpha)
|
|
create_page("Gamma", "nav_playground.html", "en")
|
|
|
|
with self.login_user_context(superuser):
|
|
with force_language("de"):
|
|
endpoint = self.get_admin_url(PageContent, "get_tree")
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 200)
|
|
parsed = self._parse_page_tree(response, parser_class=PageTreeOptionsParser)
|
|
content = force_str(parsed)
|
|
self.assertIn("(Shift-Klick für erweiterte Einstellungen)", content)
|
|
|
|
def test_page_get_tree_endpoint_flat(self):
|
|
superuser = self.get_superuser()
|
|
endpoint = self.get_admin_url(PageContent, "get_tree")
|
|
|
|
create_page("Home", "nav_playground.html", "en")
|
|
alpha = create_page("Alpha", "nav_playground.html", "en")
|
|
create_page("Beta", "nav_playground.html", "en", parent=alpha)
|
|
create_page("Gamma", "nav_playground.html", "en")
|
|
|
|
tree = "<li>\nHome\n</li>" "<li>\nAlpha\n</li>" "<li>\nGamma\n</li>"
|
|
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 200)
|
|
parsed = self._parse_page_tree(response, parser_class=PageTreeLiParser)
|
|
content = force_str(parsed)
|
|
self.assertIn(tree, content)
|
|
self.assertNotIn("<li>\nBeta\n</li>", content)
|
|
|
|
def test_page_get_tree_different_site(self):
|
|
superuser = self.get_superuser()
|
|
site = Site.objects.create(id=2, domain="example-2.com", name="example-2.com")
|
|
|
|
with self.settings(CMS_LANGUAGES={2: [{"code": "en", "name": "English"}]}):
|
|
create_page("Home", "nav_playground.html", "en", site=site)
|
|
alpha = create_page("Alpha", "nav_playground.html", "en", site=site)
|
|
create_page("Beta", "nav_playground.html", "en", parent=alpha)
|
|
create_page("Gamma", "nav_playground.html", "en", site=site)
|
|
|
|
tree = "<li>\nHome\n</li>" "<li>\nAlpha\n</li>" "<li>\nGamma\n</li>"
|
|
endpoint_default = self.get_admin_url(PageContent, "get_tree")
|
|
endpoint_site = self.get_admin_url(PageContent, "get_tree") + "?site=2"
|
|
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(endpoint_default)
|
|
self.assertEqual(response.status_code, 200)
|
|
parsed = self._parse_page_tree(response, parser_class=PageTreeLiParser)
|
|
content = force_str(parsed)
|
|
self.assertNotIn(tree, content)
|
|
|
|
response = self.client.get(endpoint_site)
|
|
self.assertEqual(response.status_code, 200)
|
|
parsed = self._parse_page_tree(response, parser_class=PageTreeLiParser)
|
|
content = force_str(parsed)
|
|
self.assertIn(tree, content)
|
|
|
|
def test_page_get_tree_endpoint_nested(self):
|
|
superuser = self.get_superuser()
|
|
endpoint = self.get_admin_url(PageContent, "get_tree")
|
|
|
|
create_page("Home", "nav_playground.html", "en")
|
|
alpha = create_page("Alpha", "nav_playground.html", "en")
|
|
create_page("Beta", "nav_playground.html", "en", parent=alpha)
|
|
gamma = create_page("Gamma", "nav_playground.html", "en")
|
|
create_page("Delta", "nav_playground.html", "en", parent=gamma)
|
|
create_page("Theta", "nav_playground.html", "en")
|
|
|
|
tree = (
|
|
"<li>\nHome\n</li>"
|
|
"<li>\nAlpha"
|
|
"<ul>\n<li>\nBeta\n</li>\n</ul>\n</li>"
|
|
"<li>\nGamma"
|
|
"<ul>\n<li>\nDelta\n</li>\n</ul>\n</li>"
|
|
"<li>\nTheta\n</li>"
|
|
)
|
|
|
|
data = {"openNodes[]": [alpha.pk, gamma.pk]}
|
|
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(endpoint, data=data)
|
|
self.assertEqual(response.status_code, 200)
|
|
parsed = self._parse_page_tree(response, parser_class=PageTreeLiParser)
|
|
content = force_str(parsed)
|
|
self.assertIn(tree, content)
|
|
|
|
def test_page_tree_prefetches_page_urls(self):
|
|
"""
|
|
Regression test: the page tree endpoints must fetch the ``PageUrl``
|
|
objects of all pages in bulk instead of issuing one query per page
|
|
row (triggered by ``Page.get_url_obj`` filling ``urls_cache`` from
|
|
``self.urls.all()`` for every rendered row).
|
|
"""
|
|
superuser = self.get_superuser()
|
|
|
|
create_page("Home", "nav_playground.html", "en")
|
|
for index in range(4):
|
|
create_page(f"Page {index}", "nav_playground.html", "en")
|
|
|
|
endpoints = (
|
|
self.get_admin_url(PageContent, "get_tree"),
|
|
self.get_admin_url(PageContent, "changelist"),
|
|
)
|
|
|
|
with self.login_user_context(superuser):
|
|
for endpoint in endpoints:
|
|
with self.subTest(endpoint=endpoint):
|
|
with CaptureQueriesContext(connection) as queries:
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 200)
|
|
page_url_queries = [
|
|
query["sql"] for query in queries.captured_queries if '"cms_pageurl"' in query["sql"]
|
|
]
|
|
self.assertLessEqual(
|
|
len(page_url_queries),
|
|
1,
|
|
"The page tree issued one PageUrl query per page instead "
|
|
"of prefetching them:\n" + "\n".join(page_url_queries),
|
|
)
|
|
|
|
def test_page_tree_does_not_requery_content_less_pages(self):
|
|
"""
|
|
Regression test: pages without any (filtered) translations must not
|
|
trigger a fresh ``set_admin_content_cache`` query per row. An empty
|
|
admin content cache used to be indistinguishable from an unpopulated
|
|
one, so ``get_admin_content`` / ``get_languages`` re-queried the
|
|
database for every content-less page in the tree.
|
|
"""
|
|
superuser = self.get_superuser()
|
|
endpoint = self.get_admin_url(PageContent, "get_tree")
|
|
|
|
def add_content_less_pages(count, prefix):
|
|
for index in range(count):
|
|
page = create_page(f"{prefix}-{index}", "nav_playground.html", "en")
|
|
PageContent.admin_manager.filter(page=page).delete()
|
|
|
|
create_page("Home", "nav_playground.html", "en")
|
|
add_content_less_pages(2, "empty-a")
|
|
|
|
with self.login_user_context(superuser):
|
|
self.client.get(endpoint) # warm up caches (content types, permissions, ...)
|
|
with CaptureQueriesContext(connection) as first:
|
|
self.assertEqual(self.client.get(endpoint).status_code, 200)
|
|
|
|
add_content_less_pages(3, "empty-b")
|
|
with CaptureQueriesContext(connection) as second:
|
|
self.assertEqual(self.client.get(endpoint).status_code, 200)
|
|
|
|
self.assertEqual(
|
|
len(second.captured_queries),
|
|
len(first.captured_queries),
|
|
"The page tree issued extra queries for content-less pages:\n"
|
|
+ "\n".join(query["sql"] for query in second.captured_queries),
|
|
)
|
|
|
|
def test_page_tree_redirect_icon_display(self):
|
|
"""Test that redirect icon is displayed in page tree when page has redirect"""
|
|
superuser = self.get_superuser()
|
|
endpoint = self.get_admin_url(PageContent, "get_tree")
|
|
|
|
# Create pages
|
|
create_page("Home", "nav_playground.html", "en")
|
|
page_with_redirect = create_page("About", "nav_playground.html", "en")
|
|
create_page("Contact", "nav_playground.html", "en")
|
|
|
|
# Set redirect on one page
|
|
page_content = page_with_redirect.get_content_obj(language="en")
|
|
page_content.redirect = "/home/"
|
|
page_content.save()
|
|
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 200)
|
|
content = response.content.decode("utf-8")
|
|
|
|
# Check that redirect icon is present for page with redirect
|
|
# The icon should have the class "cms-icon-redirect"
|
|
self.assertIn("cms-icon-redirect", content)
|
|
|
|
# Verify the icon is in the correct part of the page tree
|
|
# by checking for the redirect tooltip text
|
|
self.assertIn("data-cms-tooltip", content)
|
|
self.assertIn("redirect", content.lower())
|
|
|
|
def test_page_tree_redirect_icon_click_opens_edit(self):
|
|
"""Test that clicking redirect icon in tree opens the page edit view"""
|
|
superuser = self.get_superuser()
|
|
|
|
# Create a page with redirect
|
|
page = create_page("About", "nav_playground.html", "en")
|
|
page_content = page.get_content_obj(language="en")
|
|
page_content.redirect = "/home/"
|
|
page_content.save()
|
|
|
|
endpoint = self.get_admin_url(PageContent, "get_tree")
|
|
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 200)
|
|
content = response.content.decode("utf-8")
|
|
|
|
# The redirect icon should link to the page edit URL
|
|
# The link uses the PageContent change admin URL
|
|
admin_url = self.get_admin_url(PageContent, "change", page_content.pk)
|
|
self.assertIn(admin_url, content)
|
|
|
|
# Verify the link wraps the redirect icon
|
|
# by checking for the pattern: <a href="..."><span class="cms-icon cms-icon-redirect"></span></a>
|
|
self.assertRegex(
|
|
content, rf'<a href="{re.escape(admin_url)}"[^>]*>\s*<span class="cms-icon cms-icon-redirect">'
|
|
)
|
|
|
|
def test_page_tree_no_redirect_icon_for_normal_pages(self):
|
|
"""Test that pages without redirects don't show redirect icon"""
|
|
superuser = self.get_superuser()
|
|
endpoint = self.get_admin_url(PageContent, "get_tree")
|
|
|
|
# Create a page without redirect
|
|
create_page("Home", "nav_playground.html", "en")
|
|
create_page("About", "nav_playground.html", "en")
|
|
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
# Parse the response and verify structure
|
|
# We expect the redirect icon section to not be present
|
|
# for pages without redirects
|
|
parsed = self._parse_page_tree(response, parser_class=PageTreeLiParser)
|
|
content = force_str(parsed)
|
|
|
|
# The response should contain page structure
|
|
self.assertIn("Home", content)
|
|
self.assertIn("About", content)
|
|
self.assertNotIn("cms-icon-redirect", content)
|
|
|
|
def test_page_changelist_search(self):
|
|
superuser = self.get_superuser()
|
|
endpoint = self.get_pages_admin_list_uri()
|
|
|
|
create_page("Home", "nav_playground.html", "en")
|
|
alpha = create_page("Alpha", "nav_playground.html", "en")
|
|
create_page("Beta", "nav_playground.html", "en", parent=alpha)
|
|
create_page("Gamma", "nav_playground.html", "en")
|
|
|
|
with self.login_user_context(superuser):
|
|
response = self.client.get(endpoint, data={"q": "alpha"})
|
|
self.assertEqual(response.status_code, 200)
|
|
parsed = self._parse_page_tree(response, parser_class=PageTreeLiParser)
|
|
content = force_str(parsed)
|
|
self.assertIn("<li>\nAlpha\n</li>", content)
|
|
self.assertNotIn("<li>\nHome\n</li>", content)
|
|
self.assertNotIn("<li>\nBeta\n</li>", content)
|
|
self.assertNotIn("<li>\nGamma\n</li>", content)
|
|
|
|
def test_global_limit_on_plugin_move(self):
|
|
superuser = self.get_superuser()
|
|
cms_page = self.get_page()
|
|
source_placeholder = cms_page.get_placeholders("en").get(slot="right-column")
|
|
target_placeholder = cms_page.get_placeholders("en").get(slot="body")
|
|
data = {
|
|
"placeholder": source_placeholder,
|
|
"plugin_type": "LinkPlugin",
|
|
"language": "en",
|
|
}
|
|
plugin_1 = add_plugin(**data)
|
|
plugin_2 = add_plugin(**data)
|
|
plugin_3 = add_plugin(**data)
|
|
with UserLoginContext(self, superuser):
|
|
with override_placeholder_conf(self.placeholderconf):
|
|
data = self._get_move_data(plugin_1, position=1, placeholder=target_placeholder)
|
|
endpoint = self.get_move_plugin_uri(plugin_1)
|
|
response = self.client.post(endpoint, data) # first
|
|
self.assertEqual(response.status_code, 200)
|
|
data = self._get_move_data(plugin_2, position=2, placeholder=target_placeholder)
|
|
endpoint = self.get_move_plugin_uri(plugin_2)
|
|
response = self.client.post(endpoint, data) # second
|
|
self.assertEqual(response.status_code, 200)
|
|
data = self._get_move_data(plugin_3, position=3, placeholder=target_placeholder)
|
|
endpoint = self.get_move_plugin_uri(plugin_3)
|
|
response = self.client.post(endpoint, data) # third
|
|
self.assertEqual(response.status_code, 400)
|
|
self.assertEqual(response.content, b"This placeholder already has the maximum number of plugins (2).")
|
|
|
|
def test_type_limit_on_plugin_move(self):
|
|
superuser = self.get_superuser()
|
|
cms_page = self.get_page()
|
|
source_placeholder = cms_page.get_placeholders("en").get(slot="right-column")
|
|
target_placeholder = cms_page.get_placeholders("en").get(slot="body")
|
|
data = {
|
|
"placeholder": source_placeholder,
|
|
"plugin_type": "TextPlugin",
|
|
"language": "en",
|
|
}
|
|
plugin_1 = add_plugin(**data)
|
|
plugin_2 = add_plugin(**data)
|
|
with UserLoginContext(self, superuser):
|
|
with override_placeholder_conf(self.placeholderconf):
|
|
data = self._get_move_data(plugin_1, position=1, placeholder=target_placeholder)
|
|
endpoint = self.get_move_plugin_uri(plugin_1)
|
|
response = self.client.post(endpoint, data) # first
|
|
self.assertEqual(response.status_code, 200)
|
|
data = self._get_move_data(plugin_2, position=2, placeholder=target_placeholder)
|
|
endpoint = self.get_move_plugin_uri(plugin_1)
|
|
response = self.client.post(endpoint, data) # second
|
|
self.assertEqual(response.status_code, 400)
|
|
self.assertEqual(
|
|
response.content, b"This placeholder already has the maximum number (1) of allowed Text plugins."
|
|
)
|
|
|
|
@skipUnless(
|
|
"sqlite" in settings.DATABASES.get("default").get("ENGINE").lower(),
|
|
"This test only works in SQLITE",
|
|
)
|
|
@override_settings(USE_THOUSAND_SEPARATOR=True, USE_L10N=True)
|
|
def test_page_tree_render_localized_page_ids(self):
|
|
from django.db import connection
|
|
|
|
# Artificially increment the sequence number on cms_page (below)
|
|
# to be > 1000, to trigger a THOUSAND_SEPARATOR localization in the
|
|
# rendered template
|
|
|
|
admin_user = self.get_superuser()
|
|
root = create_page(
|
|
"home",
|
|
"nav_playground.html",
|
|
"fr",
|
|
created_by=admin_user,
|
|
)
|
|
with connection.cursor() as c:
|
|
c.execute('UPDATE SQLITE_SEQUENCE SET seq = 1001 WHERE name="cms_page"')
|
|
|
|
page = create_page(
|
|
"child-page",
|
|
"nav_playground.html",
|
|
"fr",
|
|
created_by=admin_user,
|
|
parent=root,
|
|
slug="child-page",
|
|
)
|
|
|
|
sub_page = create_page(
|
|
"grand-child-page",
|
|
"nav_playground.html",
|
|
"fr",
|
|
created_by=admin_user,
|
|
parent=page,
|
|
slug="grand-child-page",
|
|
)
|
|
self.assertTrue(page.id > 1000)
|
|
self.assertTrue(sub_page.id > 1000)
|
|
|
|
self.assertTrue(page.id > 1000)
|
|
self.assertTrue(sub_page.id > 1000)
|
|
|
|
# make sure the rendered page tree doesn't
|
|
# localize page or node ids
|
|
with self.login_user_context(admin_user):
|
|
data = {"openNodes[]": [root.pk, page.pk], "language": "fr"}
|
|
|
|
endpoint = self.get_admin_url(PageContent, "get_tree")
|
|
response = self.client.get(endpoint, data=data)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertNotContains(response, f"page={page.pk:,}")
|
|
self.assertContains(response, f"parent_page={page.pk}")
|
|
|
|
# if per chance we have localized node ids in our localstorage,
|
|
# make sure DjangoCMS doesn't choke on them when they are passed
|
|
# into the view
|
|
with self.login_user_context(admin_user):
|
|
data = {"openNodes[]": [root.pk, f"{page.pk:,}"], "language": "fr"}
|
|
endpoint = self.get_admin_url(PageContent, "get_tree")
|
|
response = self.client.get(endpoint, data=data)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
|
class PageActionsTestCase(PageTestBase):
|
|
def setUp(self):
|
|
self.admin = self.get_superuser()
|
|
self.site = Site.objects.get(pk=1)
|
|
self.page = create_page(
|
|
"My Page", "nav_playground.html", "en", slug="ok", site=self.site, created_by=self.admin
|
|
)
|
|
|
|
def test_add_page_redirect(self):
|
|
"""When adding the edit parameter to the add page form, the user should be redirected to the edit endpoint
|
|
of the new page."""
|
|
with self.login_user_context(self.admin):
|
|
# add page
|
|
page_data = {
|
|
"title": "another page",
|
|
"slug": "type1",
|
|
"template": "nav_playground.html",
|
|
"language": "en",
|
|
"edit": 1,
|
|
}
|
|
self.assertEqual(Page.objects.all().count(), 1)
|
|
response = self.client.post(
|
|
self.get_admin_url(PageContent, "add"),
|
|
data=page_data,
|
|
)
|
|
redirect_url = get_object_edit_url(PageContent.objects.get(title="another page"))
|
|
self.assertContains(response, f'href="{redirect_url}"')
|
|
self.assertEqual(Page.objects.all().count(), 2)
|
|
|
|
def test_add_page_no_redirect(self):
|
|
with self.login_user_context(self.admin):
|
|
# add page
|
|
page_data = {
|
|
"title": "another page",
|
|
"slug": "type1",
|
|
"template": "nav_playground.html",
|
|
"language": "en",
|
|
"edit": 0,
|
|
}
|
|
self.assertEqual(Page.objects.all().count(), 1)
|
|
response = self.client.post(
|
|
self.get_admin_url(PageContent, "add"),
|
|
data=page_data,
|
|
)
|
|
redirect_url = self.get_admin_url(PageContent, "changelist") + "?language=en"
|
|
self.assertRedirects(response, redirect_url)
|
|
self.assertEqual(Page.objects.all().count(), 2)
|
|
|
|
def test_get_list_is_scoped_to_requested_site(self):
|
|
site2 = Site.objects.create(id=2, name="example-2.com", domain="example-2.com")
|
|
create_page(
|
|
"Bravo Site 1",
|
|
"nav_playground.html",
|
|
"en",
|
|
site=self.site,
|
|
slug="bravo-site-1",
|
|
created_by=self.admin,
|
|
)
|
|
with self.settings(CMS_LANGUAGES={2: [{"code": "en", "name": "English"}]}):
|
|
create_page(
|
|
"Bravo Site 2",
|
|
"nav_playground.html",
|
|
"en",
|
|
site=site2,
|
|
slug="bravo-site-2",
|
|
created_by=self.admin,
|
|
)
|
|
|
|
endpoint = admin_reverse("cms_page_get_list")
|
|
with self.login_user_context(self.admin):
|
|
response = self.client.get(
|
|
endpoint,
|
|
data={"site": self.site.pk, "q": "Bravo", "language_code": "en"},
|
|
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
results = json.loads(response.content.decode("utf-8"))
|
|
titles = {result["title"] for result in results}
|
|
self.assertIn("Bravo Site 1", titles)
|
|
self.assertNotIn("Bravo Site 2", titles)
|
|
|
|
def test_get_list_ignores_an_empty_query(self):
|
|
"""``icontains`` matches everything for an empty term, so an empty query
|
|
would turn the autocomplete into a listing of every page on the site."""
|
|
create_page("Bravo", "nav_playground.html", "en", site=self.site, created_by=self.admin)
|
|
|
|
endpoint = admin_reverse("cms_page_get_list")
|
|
with self.login_user_context(self.admin):
|
|
response = self.client.get(
|
|
endpoint,
|
|
data={"site": self.site.pk, "q": "", "language_code": "en"},
|
|
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(json.loads(response.content.decode("utf-8")), [])
|
|
|
|
def test_get_list_excludes_page_types(self):
|
|
"""Page types are blueprints for new pages, not link targets."""
|
|
create_page("Bravo page", "nav_playground.html", "en", site=self.site, created_by=self.admin)
|
|
root = create_page(
|
|
"Page Types", "nav_playground.html", "en", site=self.site, reverse_id=constants.PAGE_TYPES_ID
|
|
)
|
|
page_type = create_page("Bravo type", "nav_playground.html", "en", site=self.site, parent=root)
|
|
Page.objects.filter(pk__in=(root.pk, page_type.pk)).update(is_page_type=True)
|
|
|
|
endpoint = admin_reverse("cms_page_get_list")
|
|
with self.login_user_context(self.admin):
|
|
response = self.client.get(
|
|
endpoint,
|
|
data={"site": self.site.pk, "q": "Bravo", "language_code": "en"},
|
|
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
results = json.loads(response.content.decode("utf-8"))
|
|
self.assertEqual({result["title"] for result in results}, {"Bravo page"})
|
|
|
|
def test_get_list_caps_the_number_of_results(self):
|
|
for index in range(PAGE_SMART_LINK_MAX_RESULTS + 5):
|
|
create_page(
|
|
f"Bravo {index}",
|
|
"nav_playground.html",
|
|
"en",
|
|
site=self.site,
|
|
slug=f"bravo-{index}",
|
|
created_by=self.admin,
|
|
)
|
|
|
|
endpoint = admin_reverse("cms_page_get_list")
|
|
with self.login_user_context(self.admin):
|
|
response = self.client.get(
|
|
endpoint,
|
|
data={"site": self.site.pk, "q": "Bravo", "language_code": "en"},
|
|
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(
|
|
len(json.loads(response.content.decode("utf-8"))), PAGE_SMART_LINK_MAX_RESULTS
|
|
)
|
|
|
|
def test_get_list_prefetches_page_urls(self):
|
|
"""
|
|
Regression test: the smart-link autocomplete endpoint resolves the
|
|
path/title/URL of every matching page. It must prefetch ``urls`` (and
|
|
``pagecontent_set``) in bulk instead of issuing one ``PageUrl`` query
|
|
per matched page.
|
|
"""
|
|
for index in range(4):
|
|
create_page(
|
|
f"Bravo {index}",
|
|
"nav_playground.html",
|
|
"en",
|
|
site=self.site,
|
|
slug=f"bravo-{index}",
|
|
created_by=self.admin,
|
|
)
|
|
|
|
endpoint = admin_reverse("cms_page_get_list")
|
|
with self.login_user_context(self.admin):
|
|
with CaptureQueriesContext(connection) as queries:
|
|
response = self.client.get(
|
|
endpoint,
|
|
data={"site": self.site.pk, "q": "Bravo", "language_code": "en"},
|
|
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(len(json.loads(response.content.decode("utf-8"))), 4)
|
|
page_url_queries = [
|
|
query["sql"] for query in queries.captured_queries if 'FROM "cms_pageurl"' in query["sql"]
|
|
]
|
|
self.assertLessEqual(
|
|
len(page_url_queries),
|
|
1,
|
|
"The smart-link endpoint issued one PageUrl query per matched page:\n"
|
|
+ "\n".join(page_url_queries),
|
|
)
|
|
|
|
def test_actions_menu_superuser(self):
|
|
"""Test actions_menu view returns correct context for superuser"""
|
|
with self.login_user_context(self.admin):
|
|
url = admin_reverse("cms_page_actions_menu", args=[self.page.pk])
|
|
response = self.client.get(url)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTemplateUsed(response, "admin/cms/page/tree/actions_dropdown.html")
|
|
|
|
# Check context contains expected keys
|
|
self.assertIn("page", response.context)
|
|
self.assertIn("site", response.context)
|
|
self.assertIn("opts", response.context)
|
|
self.assertIn("paste_enabled", response.context)
|
|
self.assertIn("page_is_restricted", response.context)
|
|
|
|
# Check permissions for superuser
|
|
self.assertEqual(response.context["page"], self.page)
|
|
self.assertEqual(response.context["site"], self.site)
|
|
self.assertTrue(response.context["has_add_permission"])
|
|
self.assertTrue(response.context["has_copy_page_permission"])
|
|
self.assertTrue(response.context["has_change_permission"])
|
|
self.assertTrue(response.context["has_change_advanced_settings_permission"])
|
|
self.assertTrue(response.context["has_change_permissions_permission"])
|
|
self.assertTrue(response.context["has_move_page_permission"])
|
|
self.assertTrue(response.context["has_delete_permission"])
|
|
|
|
def test_actions_menu_paste_enabled(self):
|
|
"""Test paste_enabled flag is set correctly from GET parameters"""
|
|
with self.login_user_context(self.admin):
|
|
url = admin_reverse("cms_page_actions_menu", args=[self.page.pk])
|
|
|
|
# Test with has_copy parameter
|
|
response = self.client.get(url, {"has_copy": "1"})
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTrue(response.context["paste_enabled"])
|
|
|
|
# Test with has_cut parameter
|
|
response = self.client.get(url, {"has_cut": "1"})
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTrue(response.context["paste_enabled"])
|
|
|
|
# Test without parameters
|
|
response = self.client.get(url)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertFalse(response.context["paste_enabled"])
|
|
|
|
def test_actions_menu_nonexistent_page(self):
|
|
"""Test actions_menu raises 404 for non-existent page"""
|
|
with self.login_user_context(self.admin):
|
|
url = admin_reverse("cms_page_actions_menu", args=[999999])
|
|
response = self.client.get(url)
|
|
self.assertEqual(response.status_code, 404)
|
|
|
|
def test_actions_menu_extra_context(self):
|
|
"""Test that extra_context is merged into the response context"""
|
|
# This test verifies the extra_context parameter functionality
|
|
# Since we can't directly call the method with extra_context via URL,
|
|
# we'll test it by directly calling the admin method
|
|
from django.contrib.admin.sites import AdminSite
|
|
|
|
from cms.admin.pageadmin import PageAdmin
|
|
|
|
page_admin = PageAdmin(Page, AdminSite())
|
|
request = self.get_page_request(self.page, self.admin, "/")
|
|
request.GET = {}
|
|
|
|
extra = {"custom_key": "custom_value"}
|
|
response = page_admin.actions_menu(request, self.page.pk, extra_context=extra)
|
|
|
|
# The response should be an HttpResponse with rendered template
|
|
self.assertEqual(response.status_code, 200)
|
|
# Note: We can't easily check context on the rendered response,
|
|
# but we've verified the method accepts and processes extra_context
|
|
|
|
@override_settings(CMS_PERMISSION=False)
|
|
def test_actions_menu_cms_permission_setting(self):
|
|
"""Test CMS_PERMISSION setting is passed to context"""
|
|
with self.login_user_context(self.admin):
|
|
url = admin_reverse("cms_page_actions_menu", args=[self.page.pk])
|
|
response = self.client.get(url)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertFalse(response.context["CMS_PERMISSION"])
|
|
|
|
@override_settings(CMS_PERMISSION=True)
|
|
def test_get_copy_dialog_permission_denied_source(self):
|
|
"""Test: Permission denied for source page (user cannot view source page)"""
|
|
from django.contrib.auth import get_user_model
|
|
|
|
User = get_user_model()
|
|
user = User.objects.create_user(username="noperm", password="noperm", is_staff=True)
|
|
page = create_page("Secret", "nav_playground.html", "en", site=self.site, created_by=self.admin)
|
|
with self.login_user_context(user):
|
|
url = admin_reverse("cms_page_get_copy_dialog", args=[page.pk])
|
|
response = self.client.get(url, {"source_site": self.site.pk})
|
|
self.assertEqual(response.status_code, 403)
|
|
|
|
@override_settings(CMS_PERMISSION=True)
|
|
def test_get_copy_dialog_permission_denied_target(self):
|
|
"""Test: Permission denied for target page (user cannot add subpage under target)"""
|
|
from django.contrib.auth import get_user_model
|
|
|
|
User = get_user_model()
|
|
user = User.objects.create_user(username="noperm2", password="noperm2", is_staff=True)
|
|
source_page = create_page("Source", "nav_playground.html", "en", site=self.site, created_by=self.admin)
|
|
target_page = create_page("Target", "nav_playground.html", "en", site=self.site, created_by=self.admin)
|
|
with self.login_user_context(user):
|
|
url = admin_reverse("cms_page_get_copy_dialog", args=[source_page.pk])
|
|
response = self.client.get(url, {"source_site": self.site.pk, "target": target_page.pk})
|
|
self.assertEqual(response.status_code, 403)
|
|
|
|
|
|
class PermissionsTestCase(PageTestBase):
|
|
def assertContainsPermissions(self, response):
|
|
try:
|
|
# Django >= 5.1
|
|
self.assertContains(
|
|
response,
|
|
'<h2 id="pagepermission_set-2-heading" class="inline-heading">Page permissions</h2>',
|
|
html=True,
|
|
)
|
|
except AssertionError:
|
|
# Django < 5.1
|
|
self.assertContains(response, "<h2>Page permissions</h2>", html=True)
|
|
|
|
def assertNotContainsPermissions(self, response):
|
|
try:
|
|
# Django >= 5.1
|
|
self.assertNotContains(
|
|
response,
|
|
'<h2 id="pagepermission_set-1-heading" class="inline-heading">Page permissions</h2>',
|
|
html=True,
|
|
)
|
|
except AssertionError:
|
|
# Django < 5.1
|
|
self.assertNotContains(response, "<h2>Page permissions</h2>", html=True)
|
|
|
|
def _add_translation_to_page(self, page):
|
|
translation = create_page_content(
|
|
"de",
|
|
"permissions-de",
|
|
page.reload(),
|
|
slug="permissions-de",
|
|
template="nav_playground.html",
|
|
)
|
|
return translation
|
|
|
|
def _page_exists(self, reverse_id=None):
|
|
if not reverse_id:
|
|
reverse_id = "permissions"
|
|
return Page.objects.filter(reverse_id=reverse_id).exists()
|
|
|
|
def _page_permission_exists(self, **kwargs):
|
|
return PagePermission.objects.filter(**kwargs).exists()
|
|
|
|
def _get_page_permissions_data(self, **kwargs):
|
|
if "id" in kwargs:
|
|
initial = 1
|
|
else:
|
|
initial = 0
|
|
|
|
data = {
|
|
"language": "en",
|
|
"limit_visibility_in_menu": "",
|
|
"pagepermission_set-TOTAL_FORMS": 0,
|
|
"pagepermission_set-INITIAL_FORMS": 0,
|
|
"pagepermission_set-MAX_NUM_FORMS": 0,
|
|
"pagepermission_set-2-TOTAL_FORMS": 1,
|
|
"pagepermission_set-2-INITIAL_FORMS": initial,
|
|
"pagepermission_set-2-MIN_NUM_FORMS": 0,
|
|
"pagepermission_set-2-MAX_NUM_FORMS": 1000,
|
|
"pagepermission_set-2-0-id": "",
|
|
"pagepermission_set-2-0-page": "",
|
|
"pagepermission_set-2-0-user": "",
|
|
"pagepermission_set-2-0-group": "",
|
|
"pagepermission_set-2-0-can_change": "on",
|
|
"pagepermission_set-2-0-can_change_permissions": "on",
|
|
"pagepermission_set-2-0-grant_on": 5,
|
|
}
|
|
|
|
non_inline = ("language", "limit_visibility_in_menu")
|
|
|
|
for attr, value in kwargs.items():
|
|
if attr not in non_inline:
|
|
attr = f"pagepermission_set-2-0-{attr}"
|
|
data[attr] = value
|
|
return data
|
|
|
|
def _get_page_view_restrictions_data(self, **kwargs):
|
|
if "id" in kwargs:
|
|
initial = 1
|
|
else:
|
|
initial = 0
|
|
|
|
data = {
|
|
"language": "en",
|
|
"limit_visibility_in_menu": "",
|
|
"pagepermission_set-TOTAL_FORMS": 1,
|
|
"pagepermission_set-INITIAL_FORMS": initial,
|
|
"pagepermission_set-MIN_NUM_FORMS": 0,
|
|
"pagepermission_set-MAX_NUM_FORMS": 1000,
|
|
"pagepermission_set-0-id": "",
|
|
"pagepermission_set-0-page": "",
|
|
"pagepermission_set-0-user": "",
|
|
"pagepermission_set-0-group": "",
|
|
"pagepermission_set-0-can_view": "on",
|
|
"pagepermission_set-0-grant_on": 5,
|
|
"pagepermission_set-2-TOTAL_FORMS": 0,
|
|
"pagepermission_set-2-INITIAL_FORMS": 0,
|
|
"pagepermission_set-2-MIN_NUM_FORMS": 0,
|
|
"pagepermission_set-2-MAX_NUM_FORMS": 1000,
|
|
}
|
|
|
|
non_inline = ("language", "limit_visibility_in_menu")
|
|
|
|
for attr, value in kwargs.items():
|
|
if attr not in non_inline:
|
|
attr = f"pagepermission_set-0-{attr}"
|
|
data[attr] = value
|
|
return data
|
|
|
|
|
|
@override_settings(CMS_PERMISSION=True)
|
|
class PermissionsOnGlobalTest(PermissionsTestCase):
|
|
"""
|
|
Tests all user interactions with the page admin
|
|
while permissions are set to True and user has
|
|
global permissions.
|
|
"""
|
|
|
|
def test_pages_in_admin_index(self):
|
|
"""
|
|
User can see the "Pages" section the admin
|
|
if he has change permissions on the Page model
|
|
and he has global change permissions.
|
|
"""
|
|
endpoint = admin_reverse("app_list", args=["cms"])
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(staff_user, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(
|
|
response,
|
|
'<a href="/en/admin/cms/pagecontent/">Page contents</a>',
|
|
html=True,
|
|
)
|
|
|
|
endpoint = self.get_pages_admin_list_uri()
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_pages_not_in_admin_index(self):
|
|
"""
|
|
User can't see the "Pages" section the admin
|
|
if he does not have change permissions on the Page model
|
|
and/or does not have global change permissions.
|
|
"""
|
|
endpoint = admin_reverse("app_list", args=["cms"])
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(staff_user, can_change=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 404)
|
|
|
|
endpoint = self.get_pages_admin_list_uri()
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 403)
|
|
|
|
def test_user_can_edit_page_settings(self):
|
|
"""
|
|
User can edit page settings if he has change permissions
|
|
on the Page model and and he has global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_page_change_uri("en", page)
|
|
redirect_to = self.get_pages_admin_list_uri()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
data = self._get_page_data(slug="permissions-2")
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(staff_user, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertTrue(self._translation_exists(slug="permissions-2"))
|
|
|
|
def test_user_cant_edit_page_settings(self):
|
|
"""
|
|
User can't edit page settings if he does not
|
|
have change permissions on the Page model and/or
|
|
does not have global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_page_change_uri("en", page)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
data = self._get_page_data(slug="permissions-2")
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
gp = self.add_global_permission(staff_user, can_change=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertFalse(self._translation_exists(slug="permissions-2"))
|
|
|
|
self.remove_permission(staff_user, "change_page")
|
|
gp.can_change = True
|
|
gp.save(update_fields=["can_change"])
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertFalse(self._translation_exists(slug="permissions-2"))
|
|
|
|
def test_user_can_edit_advanced_page_settings(self):
|
|
"""
|
|
User can edit advanced page settings if he has change permissions
|
|
on the Page model, global change permissions and
|
|
global change advanced settings permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk)
|
|
redirect_to = self.get_pages_admin_list_uri(site_id=page.site_id)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
data = self._get_page_data(reverse_id="permissions-2")
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(
|
|
staff_user,
|
|
can_change=True,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertTrue(self._page_exists(reverse_id="permissions-2"))
|
|
|
|
def test_user_cant_edit_advanced_page_settings(self):
|
|
"""
|
|
User can't edit advanced page settings if he does not
|
|
have change permissions on the Page model,
|
|
does not have global change permissions and/or
|
|
does not have global change advanced settings permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
data = self._get_page_data(reverse_id="permissions-2")
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
gp = self.add_global_permission(
|
|
staff_user,
|
|
can_change=True,
|
|
can_change_advanced_settings=False,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertFalse(self._page_exists(reverse_id="permissions-2"))
|
|
|
|
self.remove_permission(staff_user, "change_page")
|
|
gp.can_change = True
|
|
gp.save(update_fields=["can_change"])
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertFalse(self._page_exists(reverse_id="permissions-2"))
|
|
|
|
def test_user_can_delete_empty_page(self):
|
|
"""
|
|
User can delete an empty page if he has delete & change permissions
|
|
on the Page model and he has global delete & change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "delete", page.pk)
|
|
redirect_to = self.get_pages_admin_list_uri()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_page")
|
|
self.add_global_permission(staff_user, can_change=True, can_delete=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": "yes"}
|
|
response = self.client.post(endpoint, data, follow=True)
|
|
# follow=True, since page changelist redirects to page content changelist
|
|
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertFalse(self._page_exists())
|
|
|
|
def test_user_cant_delete_empty_page(self):
|
|
"""
|
|
User can't delete an empty page if he does not
|
|
have delete permissions on the Page model and/or
|
|
does not have global delete permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "delete", page.pk)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "delete_page")
|
|
gp = self.add_global_permission(staff_user, can_change=True, can_delete=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": "yes"}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(self._page_exists())
|
|
|
|
self.remove_permission(staff_user, "delete_page")
|
|
gp.can_delete = True
|
|
gp.save(update_fields=["can_delete"])
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": "yes"}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(self._page_exists())
|
|
|
|
def test_user_can_delete_non_empty_page(self):
|
|
"""
|
|
User can delete a page with plugins if he has delete & change permissions
|
|
on the Page model, delete permissions on the plugins in the page
|
|
translations and global delete & change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "delete", page.pk)
|
|
redirect_to = self.get_pages_admin_list_uri()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self._add_plugin_to_page(page)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_page")
|
|
self.add_permission(staff_user, "delete_link")
|
|
self.add_global_permission(staff_user, can_change=True, can_delete=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": "yes"}
|
|
response = self.client.post(endpoint, data, follow=True)
|
|
# follow=True, since page changelist redirects to page content changelist
|
|
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertFalse(self._page_exists())
|
|
|
|
def test_user_cant_delete_non_empty_page(self):
|
|
"""
|
|
User can't delete a page with plugins if he
|
|
does not have delete permissions on the Page model,
|
|
does not have delete permissions on the plugins
|
|
in the page translations, and/or does not have
|
|
global delete permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "delete", page.pk)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self._add_plugin_to_page(page)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.remove_permission(staff_user, "delete_page")
|
|
gp = self.add_global_permission(staff_user, can_change=True, can_delete=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": "yes"}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(self._page_exists())
|
|
|
|
self.remove_permission(staff_user, "delete_page")
|
|
gp.can_delete = True
|
|
gp.save(update_fields=["can_delete"])
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": "yes"}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(self._page_exists())
|
|
|
|
def test_user_can_delete_empty_translation(self):
|
|
"""
|
|
User can delete an empty translation if he has
|
|
delete & change permissions on the Page model and he has
|
|
global delete & change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_admin_url(PageContent, "delete", translation.pk)
|
|
redirect_to = self.get_pages_admin_list_uri()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_page")
|
|
self.add_global_permission(staff_user, can_change=True, can_delete=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"language": translation.language}
|
|
response = self.client.post(endpoint, data)
|
|
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertFalse(self._translation_exists())
|
|
|
|
def test_user_cant_delete_empty_translation(self):
|
|
"""
|
|
User can't delete an empty translation if he does not
|
|
have delete permissions on the Page model and/or
|
|
does not have global delete permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_admin_url(PageContent, "delete", translation.pk)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_page")
|
|
gp = self.add_global_permission(staff_user, can_change=True, can_delete=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"language": translation.language}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(self._translation_exists())
|
|
|
|
self.remove_permission(staff_user, "delete_page")
|
|
gp.can_delete = True
|
|
gp.save(update_fields=["can_delete"])
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"language": translation.language}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(self._translation_exists())
|
|
|
|
def test_user_can_delete_non_empty_translation(self):
|
|
"""
|
|
User can delete a translation with plugins if he has delete & change permissions
|
|
on the Page model, delete permissions on the plugins in the translation
|
|
and global delete & change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_admin_url(PageContent, "delete", translation.pk)
|
|
redirect_to = self.get_pages_admin_list_uri()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self._add_plugin_to_page(page, language=translation.language)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_page")
|
|
self.add_permission(staff_user, "delete_link")
|
|
self.add_global_permission(staff_user, can_change=True, can_delete=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"language": translation.language}
|
|
response = self.client.post(endpoint, data)
|
|
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertFalse(self._translation_exists())
|
|
|
|
def test_user_cant_delete_non_empty_translation(self):
|
|
"""
|
|
User can't delete a translation with plugins if he
|
|
does not have delete permissions on the Page model,
|
|
does not have delete permissions on the plugins in the translation,
|
|
and/or does not have global delete permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_admin_url(PageContent, "delete", translation.pk)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self._add_plugin_to_page(page, language=translation.language)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.remove_permission(staff_user, "delete_page")
|
|
self.add_global_permission(staff_user, can_change=True, can_delete=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"language": translation.language}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(self._translation_exists())
|
|
|
|
def test_user_can_change_template(self):
|
|
"""
|
|
The template lives on the page content, so changing it needs the change
|
|
permission on the page -- not the *change advanced settings* one.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
endpoint = self.get_page_change_template_uri("en", page)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(staff_user, can_change=True, can_change_advanced_settings=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
page._clear_internal_cache()
|
|
data = {"template": "simple.html"}
|
|
response = self.client.post(endpoint, data)
|
|
self.assertContains(response, "The template was successfully changed")
|
|
self.assertEqual(page.get_template(), "simple.html")
|
|
|
|
def test_user_cant_change_template(self):
|
|
"""
|
|
User can't change a page's template without the change permission on
|
|
the Page model or without global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
endpoint = self.get_page_change_template_uri("en", page)
|
|
|
|
self.add_global_permission(staff_user, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"template": "simple.html"}
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertEqual(page.get_template(), "nav_playground.html")
|
|
|
|
def test_user_can_change_template_on_change_form(self):
|
|
"""
|
|
The template field of the page content change form is governed by the
|
|
change permission, like every other field of that form.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
translation = page.get_admin_content("en")
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
endpoint = self.get_admin_url(PageContent, "change", translation.pk) + "?language=en"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(staff_user, can_change=True, can_change_advanced_settings=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
self.assertContains(self.client.get(endpoint), 'name="template"')
|
|
response = self.client.post(endpoint, self._get_page_data(template="simple.html"))
|
|
|
|
self.assertEqual(response.status_code, 302)
|
|
translation.refresh_from_db()
|
|
self.assertEqual(translation.template, "simple.html")
|
|
|
|
def test_user_can_view_page_permissions_summary(self):
|
|
"""
|
|
All staff users can see the permissions summary for a page.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "get_permissions", page.pk)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(staff_user, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": "true"}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(
|
|
response,
|
|
'<td class="user">staff</td>',
|
|
html=True,
|
|
)
|
|
|
|
def test_user_cant_view_page_permissions_summary(self):
|
|
"""
|
|
Non staff users can't see the permissions summary for a page.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "get_permissions", page.pk)
|
|
non_staff_user = self.get_standard_user()
|
|
|
|
with self.login_user_context(non_staff_user):
|
|
data = {"post": "true"}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertRedirects(response, "/en/admin/login/?next=%s" % endpoint)
|
|
|
|
def test_user_can_add_page_permissions(self):
|
|
"""
|
|
User can add page permissions if he has
|
|
change permissions on the Page model,
|
|
add permissions on the PagePermission model,
|
|
global change permission and global change permissions permission.
|
|
"""
|
|
admin = self.get_superuser()
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=admin)
|
|
|
|
data = self._get_page_permissions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_pagepermission")
|
|
self.add_global_permission(
|
|
staff_user,
|
|
can_change=True,
|
|
can_change_permissions=True,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertContainsPermissions(response)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertRedirects(response, endpoint)
|
|
self.assertTrue(self._page_permission_exists(user=staff_user_2))
|
|
|
|
def test_user_cant_add_page_permissions(self):
|
|
"""
|
|
User can't add page permissions if he
|
|
does not have change permissions on the Page model,
|
|
does not have add permissions on the PagePermission model,
|
|
does not have global change permission,
|
|
and/or does not have global change permissions permission.
|
|
"""
|
|
admin = self.get_superuser()
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=admin)
|
|
|
|
data = self._get_page_permissions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_pagepermission")
|
|
self.add_global_permission(
|
|
staff_user,
|
|
can_change=True,
|
|
can_change_permissions=False,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertNotContainsPermissions(response)
|
|
self.client.post(endpoint, data)
|
|
self.assertFalse(self._page_permission_exists(user=staff_user_2))
|
|
|
|
def test_user_can_edit_page_permissions(self):
|
|
"""
|
|
User can edit page permissions if he has
|
|
change permissions on the Page model,
|
|
change permissions on the PagePermission model,
|
|
global change permission and global change permissions permission.
|
|
"""
|
|
admin = self.get_superuser()
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=admin)
|
|
|
|
permission = self.add_page_permission(user=staff_user_2, page=page, can_change_permissions=True)
|
|
|
|
data = self._get_page_permissions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
id=permission.pk,
|
|
can_change_permissions=False,
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_pagepermission")
|
|
self.add_global_permission(
|
|
staff_user,
|
|
can_change=True,
|
|
can_change_permissions=True,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertContainsPermissions(response)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertRedirects(response, endpoint)
|
|
self.assertTrue(
|
|
self._page_permission_exists(
|
|
user=staff_user_2,
|
|
can_change_permissions=False,
|
|
)
|
|
)
|
|
|
|
def test_user_cant_edit_page_permissions(self):
|
|
"""
|
|
User can't edit page permissions if he
|
|
does not have change permissions on the Page model,
|
|
does not have change permissions on the PagePermission model,
|
|
does not have global change permission,
|
|
and/or does not have global change permissions permission.
|
|
"""
|
|
admin = self.get_superuser()
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=admin)
|
|
|
|
permission = self.add_page_permission(user=staff_user_2, page=page, can_change_permissions=True)
|
|
|
|
data = self._get_page_permissions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
id=permission.pk,
|
|
can_change_permissions=False,
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_pagepermission")
|
|
self.add_global_permission(
|
|
staff_user,
|
|
can_change=True,
|
|
can_change_permissions=False,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertNotContainsPermissions(response)
|
|
self.client.post(endpoint, data)
|
|
self.assertFalse(
|
|
self._page_permission_exists(
|
|
user=staff_user_2,
|
|
can_change_permissions=False,
|
|
)
|
|
)
|
|
|
|
def test_user_can_delete_page_permissions(self):
|
|
"""
|
|
User can delete page permissions if he has
|
|
change permissions on the Page model,
|
|
delete permissions on the PagePermission model,
|
|
global change permission and global change permissions permission.
|
|
"""
|
|
admin = self.get_superuser()
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=admin)
|
|
permission = self.add_page_permission(user=staff_user_2, page=page)
|
|
|
|
data = self._get_page_permissions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
id=permission.pk,
|
|
DELETE="on",
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_pagepermission")
|
|
self.add_global_permission(
|
|
staff_user,
|
|
can_change=True,
|
|
can_change_permissions=True,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertContainsPermissions(response)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertRedirects(response, endpoint)
|
|
self.assertFalse(self._page_permission_exists(user=staff_user_2))
|
|
|
|
def test_user_cant_delete_page_permissions(self):
|
|
"""
|
|
User can't delete page permissions if he
|
|
does not have change permissions on the Page model,
|
|
does not have delete permissions on the PagePermission model,
|
|
does not have global change permission,
|
|
and/or does not have global change permissions permission.
|
|
"""
|
|
admin = self.get_superuser()
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=admin)
|
|
permission = self.add_page_permission(user=staff_user_2, page=page)
|
|
|
|
data = self._get_page_permissions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
id=permission.pk,
|
|
DELETE="on",
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_pagepermission")
|
|
self.add_global_permission(
|
|
staff_user,
|
|
can_change=True,
|
|
can_change_permissions=False,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertNotContainsPermissions(response)
|
|
self.client.post(endpoint, data)
|
|
self.assertTrue(self._page_permission_exists(user=staff_user_2))
|
|
|
|
def test_user_can_add_page_view_restrictions(self):
|
|
"""
|
|
User can add page view restrictions if he has
|
|
change permissions on the Page model,
|
|
add permissions on the PagePermission model,
|
|
global change permission and global change permissions permission.
|
|
"""
|
|
admin = self.get_superuser()
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=admin)
|
|
|
|
data = self._get_page_view_restrictions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_pagepermission")
|
|
self.add_global_permission(
|
|
staff_user,
|
|
can_change=True,
|
|
can_change_permissions=True,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertContainsPermissions(response)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertRedirects(response, endpoint)
|
|
self.assertTrue(self._page_permission_exists(user=staff_user_2, can_view=True))
|
|
|
|
def test_user_cant_add_page_view_restrictions(self):
|
|
"""
|
|
User can't add page view restrictions if he
|
|
does not have change permissions on the Page model,
|
|
does not have add permissions on the PagePermission model,
|
|
does not have global change permission,
|
|
and/or does not have global change permissions permission.
|
|
"""
|
|
admin = self.get_superuser()
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=admin)
|
|
|
|
data = self._get_page_view_restrictions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_pagepermission")
|
|
self.add_global_permission(
|
|
staff_user,
|
|
can_change=True,
|
|
can_change_permissions=False,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertNotContainsPermissions(response)
|
|
self.client.post(endpoint, data)
|
|
self.assertFalse(self._page_permission_exists(user=staff_user_2, can_view=True))
|
|
|
|
def test_user_can_edit_page_view_restrictions(self):
|
|
"""
|
|
User can edit page view restrictions if he has
|
|
change permissions on the Page model,
|
|
change permissions on the PagePermission model,
|
|
global change permission and global change permissions permission.
|
|
"""
|
|
admin = self.get_superuser()
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=admin)
|
|
|
|
permission = self.add_page_permission(
|
|
user=staff_user_2,
|
|
page=page,
|
|
can_view=True,
|
|
grant_on=1,
|
|
)
|
|
|
|
data = model_to_dict(permission, exclude=["group"])
|
|
data["grant_on"] = 5
|
|
|
|
data = self._get_page_view_restrictions_data(**data)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_pagepermission")
|
|
self.add_global_permission(
|
|
staff_user,
|
|
can_change=True,
|
|
can_change_permissions=True,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertContainsPermissions(response)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertRedirects(response, endpoint)
|
|
self.assertTrue(
|
|
self._page_permission_exists(
|
|
user=staff_user_2,
|
|
grant_on=5,
|
|
)
|
|
)
|
|
|
|
def test_user_cant_edit_page_view_restrictions(self):
|
|
"""
|
|
User can't edit page view restrictions if he
|
|
does not have change permissions on the Page model,
|
|
does not have change permissions on the PagePermission model,
|
|
does not have global change permission,
|
|
and/or does not have global change permissions permission.
|
|
"""
|
|
admin = self.get_superuser()
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=admin)
|
|
permission = self.add_page_permission(
|
|
user=staff_user_2,
|
|
page=page,
|
|
can_view=True,
|
|
grant_on=1,
|
|
)
|
|
|
|
data = model_to_dict(permission, exclude=["group"])
|
|
data["grant_on"] = 5
|
|
|
|
data = self._get_page_view_restrictions_data(**data)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_pagepermission")
|
|
self.add_global_permission(
|
|
staff_user,
|
|
can_change=True,
|
|
can_change_permissions=False,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertNotContainsPermissions(response)
|
|
self.client.post(endpoint, data)
|
|
self.assertFalse(
|
|
self._page_permission_exists(
|
|
user=staff_user_2,
|
|
grant_on=5,
|
|
)
|
|
)
|
|
|
|
def test_user_can_delete_page_view_restrictions(self):
|
|
"""
|
|
User can delete view restrictions if he has
|
|
change permissions on the Page model,
|
|
delete permissions on the PagePermission model,
|
|
global change permission and global change permissions permission.
|
|
"""
|
|
admin = self.get_superuser()
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=admin)
|
|
permission = self.add_page_permission(
|
|
user=staff_user_2,
|
|
page=page,
|
|
can_view=True,
|
|
)
|
|
|
|
data = model_to_dict(permission, exclude=["group"])
|
|
data["DELETE"] = True
|
|
|
|
data = self._get_page_view_restrictions_data(**data)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_pagepermission")
|
|
self.add_global_permission(
|
|
staff_user,
|
|
can_change=True,
|
|
can_change_permissions=True,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertContainsPermissions(response)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertRedirects(response, endpoint)
|
|
self.assertFalse(self._page_permission_exists(user=staff_user_2, can_view=True))
|
|
|
|
def test_user_cant_delete_page_view_restrictions(self):
|
|
"""
|
|
User can't delete view restrictions if he
|
|
does not have change permissions on the Page model,
|
|
does not have delete permissions on the PagePermission model,
|
|
does not have global change permission,
|
|
and/or does not have global change permissions permission.
|
|
"""
|
|
admin = self.get_superuser()
|
|
page = self.get_permissions_test_page()
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=admin)
|
|
permission = self.add_page_permission(
|
|
user=staff_user_2,
|
|
page=page,
|
|
can_view=True,
|
|
)
|
|
|
|
data = model_to_dict(permission, exclude=["group"])
|
|
data["DELETE"] = True
|
|
|
|
data = self._get_page_view_restrictions_data(**data)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_pagepermission")
|
|
self.add_global_permission(
|
|
staff_user,
|
|
can_change=True,
|
|
can_change_permissions=False,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertNotContainsPermissions(response)
|
|
self.client.post(endpoint, data)
|
|
self.assertTrue(self._page_permission_exists(user=staff_user_2, can_view=True))
|
|
|
|
def test_permissions_cache_invalidation(self):
|
|
"""
|
|
Permission cache clears on page save
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_std_permissions()
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
set_permission_cache(staff_user, page.site, "change_page", [page.pk])
|
|
|
|
with self.login_user_context(self.get_superuser()):
|
|
data = self._get_page_permissions_data(page=page.pk, user=staff_user.pk)
|
|
data["_continue"] = "1"
|
|
self.client.post(endpoint, data)
|
|
self.assertIsNone(get_permission_cache(staff_user, page.site, "change_page"))
|
|
|
|
def test_permission_cache_invalidation_on_group_add(self):
|
|
"""
|
|
Permissions cache is invalidated if the group relationship of a user is changed
|
|
"""
|
|
from django.contrib.auth.models import Group
|
|
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_std_permissions()
|
|
set_permission_cache(staff_user, page.site, "change_page", [page.pk])
|
|
|
|
group = Group(name="test_group")
|
|
group.save()
|
|
staff_user.groups.add(group)
|
|
|
|
self.assertIsNone(get_permission_cache(staff_user, page.site, "change_page"))
|
|
|
|
def test_permission_cache_invalidation_on_group_remove(self):
|
|
"""
|
|
Permissions cache is invalidated if the group relationship of a user is changed
|
|
"""
|
|
from django.contrib.auth.models import Group
|
|
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_std_permissions()
|
|
group = Group(name="test_group")
|
|
group.save()
|
|
staff_user.groups.add(group)
|
|
|
|
set_permission_cache(staff_user, page.site, "change_page", [page.pk])
|
|
|
|
group.user_set.remove(staff_user)
|
|
|
|
self.assertIsNone(get_permission_cache(staff_user, page.site, "change_page"))
|
|
|
|
def test_user_can_copy_page(self):
|
|
"""
|
|
Test that a page can be copied via the admin
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "add_page")
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(
|
|
staff_user,
|
|
can_add=True,
|
|
can_change=True,
|
|
)
|
|
|
|
count = Page.objects.count()
|
|
|
|
with self.login_user_context(staff_user):
|
|
endpoint = self.get_admin_url(Page, "get_copy_dialog", page.pk)
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
with self.login_user_context(staff_user):
|
|
self.copy_page(page, page, position=1)
|
|
self.assertEqual(count + 1, 3)
|
|
|
|
# Plugin related tests
|
|
|
|
def test_user_can_add_plugin(self):
|
|
"""
|
|
User can add a plugin if he has change permissions
|
|
on the Page model, add permissions on the plugin model
|
|
and global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
placeholder = page.get_placeholders("en").get(slot="body")
|
|
plugins = placeholder.get_plugins("en").filter(plugin_type="LinkPlugin")
|
|
endpoint = self._get_add_plugin_uri(page)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_link")
|
|
self.add_global_permission(staff_user, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"name": "A Link", "external_link": "https://www.django-cms.org"}
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(plugins.count(), 1)
|
|
|
|
def test_user_cant_add_plugin(self):
|
|
"""
|
|
User can't add a plugin if he
|
|
does not have change permissions on the Page model,
|
|
does not have add permissions on the plugin model
|
|
and/or does not have global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
placeholder = page.get_placeholders("en").get(slot="body")
|
|
plugins = placeholder.get_plugins("en").filter(plugin_type="LinkPlugin")
|
|
endpoint = self._get_add_plugin_uri(page)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_link")
|
|
self.add_global_permission(staff_user, can_change=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"name": "A Link", "external_link": "https://www.django-cms.org"}
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertEqual(plugins.count(), 0)
|
|
|
|
def test_user_can_edit_plugin(self):
|
|
"""
|
|
User can edit a plugin if he has change permissions
|
|
on the Page model, change permissions on the plugin model
|
|
and global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
endpoint = self.get_change_plugin_uri(plugin)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_link")
|
|
self.add_global_permission(staff_user, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = model_to_dict(plugin, fields=["name", "external_link"])
|
|
data["name"] = "A link 2"
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 200)
|
|
plugin.refresh_from_db()
|
|
self.assertEqual(plugin.name, data["name"])
|
|
|
|
def test_user_cant_edit_plugin(self):
|
|
"""
|
|
User can't edit a plugin if he
|
|
does not have change permissions on the Page model,
|
|
does not have change permissions on the plugin model
|
|
and/or does not have global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
endpoint = self.get_change_plugin_uri(plugin)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_link")
|
|
self.add_global_permission(staff_user, can_change=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = model_to_dict(plugin, fields=["name", "external_link"])
|
|
data["name"] = "A link 2"
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
plugin.refresh_from_db()
|
|
self.assertNotEqual(plugin.name, data["name"])
|
|
|
|
def test_user_can_delete_plugin(self):
|
|
"""
|
|
User can delete a plugin if he has change permissions
|
|
on the Page model, delete permissions on the plugin model
|
|
and global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
endpoint = self.get_delete_plugin_uri(plugin)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_link")
|
|
self.add_global_permission(staff_user, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": True}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertContains(response, '<div class="success"></div>')
|
|
self.assertFalse(CMSPlugin.objects.filter(pk=plugin.pk).exists())
|
|
|
|
def test_user_cant_delete_plugin(self):
|
|
"""
|
|
User can't delete a plugin if he
|
|
does not have change permissions on the Page model,
|
|
does not have delete permissions on the plugin model
|
|
and/or does not have global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
endpoint = self.get_delete_plugin_uri(plugin)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_link")
|
|
self.add_global_permission(staff_user, can_change=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": True}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(CMSPlugin.objects.filter(pk=plugin.pk).exists())
|
|
|
|
def test_user_can_move_plugin(self):
|
|
"""
|
|
User can move a plugin if he has change permissions
|
|
on the Page model, change permissions on the plugin model
|
|
and global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
endpoint = self.get_move_plugin_uri(plugin)
|
|
source_placeholder = plugin.placeholder
|
|
target_placeholder = page.get_placeholders("en").get(slot="right-column")
|
|
|
|
data = self._get_move_data(plugin, position=1, placeholder=target_placeholder)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_link")
|
|
self.add_global_permission(staff_user, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTrue(target_placeholder.get_plugins("en").filter(pk=plugin.pk))
|
|
self.assertFalse(source_placeholder.get_plugins("en").filter(pk=plugin.pk))
|
|
|
|
def test_user_cant_move_plugin(self):
|
|
"""
|
|
User can't move a plugin if he
|
|
does not have change permissions on the Page model,
|
|
does not have change permissions on the plugin model
|
|
and/or does not have global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
endpoint = self.get_move_plugin_uri(plugin)
|
|
source_placeholder = plugin.placeholder
|
|
target_placeholder = page.get_placeholders("en").get(slot="right-column")
|
|
|
|
data = self._get_move_data(plugin, position=1, placeholder=target_placeholder)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_link")
|
|
self.add_global_permission(staff_user, can_change=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertFalse(target_placeholder.get_plugins("en").filter(pk=plugin.pk))
|
|
self.assertTrue(source_placeholder.get_plugins("en").filter(pk=plugin.pk))
|
|
|
|
def test_user_can_copy_plugin(self):
|
|
"""
|
|
User can copy a plugin if he has change permissions
|
|
on the Page model, add permissions on the plugin model
|
|
and global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_copy_plugin_uri(plugin)
|
|
source_placeholder = plugin.placeholder
|
|
target_placeholder = page.get_placeholders("en").get(slot="right-column")
|
|
|
|
data = {
|
|
"source_plugin_id": plugin.pk,
|
|
"source_placeholder_id": source_placeholder.pk,
|
|
"source_language": plugin.language,
|
|
"target_language": translation.language,
|
|
"target_placeholder_id": target_placeholder.pk,
|
|
}
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_link")
|
|
self.add_global_permission(staff_user, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTrue(source_placeholder.get_plugins("en").filter(pk=plugin.pk).exists())
|
|
self.assertTrue(
|
|
target_placeholder.get_plugins(translation.language).filter(plugin_type=plugin.plugin_type).exists()
|
|
)
|
|
|
|
def test_user_cant_copy_plugin(self):
|
|
"""
|
|
User can't copy a plugin if he
|
|
does not have change permissions on the Page model,
|
|
does not have add permissions on the plugin model,
|
|
and/or does not have global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_copy_plugin_uri(plugin)
|
|
source_placeholder = plugin.placeholder
|
|
target_placeholder = page.get_placeholders("en").get(slot="right-column")
|
|
|
|
data = {
|
|
"source_plugin_id": plugin.pk,
|
|
"source_placeholder_id": source_placeholder.pk,
|
|
"source_language": plugin.language,
|
|
"target_language": translation.language,
|
|
"target_placeholder_id": target_placeholder.pk,
|
|
}
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_link")
|
|
self.add_global_permission(staff_user, can_change=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(source_placeholder.get_plugins("en").filter(pk=plugin.pk).exists())
|
|
self.assertFalse(
|
|
target_placeholder.get_plugins(translation.language).filter(plugin_type=plugin.plugin_type).exists()
|
|
)
|
|
|
|
def test_user_can_copy_plugins_to_language(self):
|
|
"""
|
|
User can copy all plugins to another language if he has
|
|
change permissions on the Page model, add permissions on the
|
|
plugins being copied and global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
source_translation = self.get_pagecontent_obj(page, "en")
|
|
target_translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_admin_url(PageContent, "copy_language", source_translation.pk)
|
|
plugins = [
|
|
self._add_plugin_to_page(page),
|
|
self._add_plugin_to_page(page),
|
|
self._add_plugin_to_page(page),
|
|
self._add_plugin_to_page(page),
|
|
]
|
|
source_placeholder = plugins[0].placeholder
|
|
target_placeholder = target_translation.get_placeholders().get(slot=source_placeholder.slot)
|
|
|
|
data = {
|
|
"source_language": "en",
|
|
"target_language": target_translation.language,
|
|
}
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_link")
|
|
self.add_global_permission(staff_user, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 200)
|
|
new_plugins = target_placeholder.get_plugins()
|
|
self.assertEqual(new_plugins.count(), len(plugins))
|
|
|
|
def test_copy_language_downcasts_plugins_across_placeholders_in_one_query(self):
|
|
page = self.get_permissions_test_page()
|
|
source_translation = self.get_pagecontent_obj(page, "en")
|
|
target_translation = self._add_translation_to_page(page)
|
|
source_placeholders = page.get_placeholders("en")
|
|
add_plugin(source_placeholders.get(slot="body"), "TextPlugin", "en", body="Body")
|
|
add_plugin(source_placeholders.get(slot="right-column"), "TextPlugin", "en", body="Right column")
|
|
endpoint = self.get_admin_url(PageContent, "copy_language", source_translation.pk)
|
|
|
|
with self.login_user_context(self.get_superuser()):
|
|
with CaptureQueriesContext(connection) as queries:
|
|
response = self.client.post(endpoint, {"target_language": target_translation.language})
|
|
|
|
plugin_batch_queries = []
|
|
concrete_plugin_queries = []
|
|
for query in queries:
|
|
sql = query["sql"].replace('"', "").replace("`", "")
|
|
if "FROM cms_cmsplugin" in sql and "placeholder_id IN" in sql:
|
|
plugin_batch_queries.append(query)
|
|
if f"FROM {Text._meta.db_table}" in sql:
|
|
concrete_plugin_queries.append(query)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(len(plugin_batch_queries), 1)
|
|
self.assertEqual(len(concrete_plugin_queries), 1)
|
|
self.assertCountEqual(
|
|
Text.objects.filter(language="de").values_list("body", flat=True), ["Body", "Right column"]
|
|
)
|
|
|
|
def test_user_cant_copy_plugins_to_language(self):
|
|
"""
|
|
User can't copy all plugins to another language if he does have
|
|
change permissions on the Page model, does not have add permissions
|
|
on the plugins being copied and/or does not have global
|
|
change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_admin_url(PageContent, "copy_language", translation.pk)
|
|
plugins = [
|
|
self._add_plugin_to_page(page),
|
|
self._add_plugin_to_page(page),
|
|
self._add_plugin_to_page(page),
|
|
self._add_plugin_to_page(page),
|
|
]
|
|
placeholder = plugins[0].placeholder
|
|
|
|
data = {
|
|
"source_language": "en",
|
|
"target_language": translation.language,
|
|
}
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_link")
|
|
self.add_global_permission(staff_user, can_change=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
new_plugins = placeholder.get_plugins(translation.language)
|
|
self.assertEqual(new_plugins.count(), 0)
|
|
|
|
def test_copy_plugins_to_language_skips_missing_placeholders(self):
|
|
"""
|
|
When copying plugins to another language, placeholders that don't
|
|
exist in the target template should be skipped without raising
|
|
DoesNotExist exception.
|
|
|
|
Regression test for copying content when template placeholders have
|
|
changed between languages. This test ensures the fix at pageadmin.py:1213-1217
|
|
properly handles the DoesNotExist exception.
|
|
"""
|
|
admin = self.get_superuser()
|
|
|
|
# Create page with nav_playground template (has 'body' and 'right-column' placeholders)
|
|
page = create_page(
|
|
"test-page",
|
|
"nav_playground.html",
|
|
"en",
|
|
created_by=admin,
|
|
)
|
|
|
|
# Add plugins to both placeholders in English
|
|
body_placeholder = page.get_placeholders("en").get(slot="body")
|
|
right_column_placeholder = page.get_placeholders("en").get(slot="right-column")
|
|
|
|
add_plugin(body_placeholder, "LinkPlugin", "en", name="Body Link", external_link="https://example.com")
|
|
add_plugin(
|
|
right_column_placeholder, "LinkPlugin", "en", name="Right Column Link", external_link="https://example.com"
|
|
)
|
|
|
|
# Create German translation with col_two template (has 'col_sidebar' and 'col_left' placeholders)
|
|
# This simulates a template change where old placeholders no longer exist
|
|
de_content = create_page_content(
|
|
"de",
|
|
"test-page-de",
|
|
page,
|
|
slug="test-page-de",
|
|
template="col_two.html",
|
|
)
|
|
|
|
# Try to copy from English to German - should not raise DoesNotExist
|
|
endpoint = self.get_admin_url(PageContent, "copy_language", de_content.pk)
|
|
data = {
|
|
"source_language": "en",
|
|
"target_language": "de",
|
|
}
|
|
|
|
with self.login_user_context(admin):
|
|
response = self.client.post(endpoint, data)
|
|
# Should succeed without raising DoesNotExist exception
|
|
# This is the key behavior being tested - the operation completes
|
|
# successfully even when source placeholders don't exist in target
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
# Verify original English plugins are still intact
|
|
self.assertEqual(body_placeholder.get_plugins("en").count(), 1)
|
|
self.assertEqual(right_column_placeholder.get_plugins("en").count(), 1)
|
|
|
|
# Placeholder related tests
|
|
|
|
def test_user_can_clear_empty_placeholder(self):
|
|
"""
|
|
User can clear an empty placeholder if he has change permissions
|
|
on the Page model and global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
placeholder = page.get_placeholders("en").get(slot="body")
|
|
endpoint = self.get_clear_placeholder_url(placeholder)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(staff_user, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, {"test": 0})
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_user_cant_clear_empty_placeholder(self):
|
|
"""
|
|
User can't clear an empty placeholder if he does not have
|
|
change permissions on the Page model and/or does not have
|
|
global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
placeholder = page.get_placeholders("en").get(slot="body")
|
|
endpoint = self.get_clear_placeholder_url(placeholder)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(staff_user, can_change=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, {"test": 0})
|
|
self.assertEqual(response.status_code, 403)
|
|
|
|
def test_user_can_clear_non_empty_placeholder(self):
|
|
"""
|
|
User can clear a placeholder with plugins if he has
|
|
change permissions on the Page model, delete permissions
|
|
on the plugin models in the placeholder and global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugins = [
|
|
self._add_plugin_to_page(page, "TextPlugin"),
|
|
self._add_plugin_to_page(page, "LinkPlugin"),
|
|
]
|
|
placeholder = plugins[0].placeholder
|
|
endpoint = self.get_clear_placeholder_url(placeholder)
|
|
|
|
self.add_permission(staff_user, "delete_text")
|
|
self.add_permission(staff_user, "delete_link")
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(staff_user, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, {"test": 0})
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(placeholder.get_plugins("en").count(), 0)
|
|
|
|
def test_user_cant_clear_non_empty_placeholder(self):
|
|
"""
|
|
User can't clear a placeholder with plugins if he does not have
|
|
change permissions on the Page model, does not have delete
|
|
permissions on the plugin models in the placeholder and/or
|
|
does not have global change permissions.
|
|
"""
|
|
page = self.get_permissions_test_page()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugins = [
|
|
self._add_plugin_to_page(page, "TextPlugin"),
|
|
self._add_plugin_to_page(page, "LinkPlugin"),
|
|
]
|
|
placeholder = plugins[0].placeholder
|
|
endpoint = self.get_clear_placeholder_url(placeholder)
|
|
|
|
self.add_permission(staff_user, "delete_text")
|
|
self.add_permission(staff_user, "delete_link")
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(staff_user, can_change=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, {"test": 0})
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertEqual(placeholder.get_plugins("en").count(), 2)
|
|
|
|
|
|
@override_settings(CMS_PERMISSION=True)
|
|
class PermissionsOnPageTest(PermissionsTestCase):
|
|
"""
|
|
Tests all user interactions with the page admin
|
|
while permissions are set to True and user has
|
|
page permissions.
|
|
"""
|
|
|
|
def setUp(self):
|
|
self._permissions_page = self.get_permissions_test_page()
|
|
|
|
def test_pages_in_admin_index(self):
|
|
"""
|
|
User can see the "Pages" section the admin
|
|
if he has change permissions on the Page model
|
|
and he has global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = admin_reverse("app_list", args=["cms"])
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_set_home_requires_permission_on_old_home(self):
|
|
"""
|
|
Setting a new home page demotes the current one and rewrites its urls,
|
|
so change permission on the target page alone is not enough.
|
|
"""
|
|
old_home = create_page("old-home", "nav_playground.html", "en")
|
|
old_home.set_as_homepage()
|
|
new_home = create_page("new-home", "nav_playground.html", "en")
|
|
endpoint = self.get_admin_url(Page, "set_home", new_home.pk)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_page_permission(staff_user, new_home, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint)
|
|
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(old_home.reload().is_home)
|
|
self.assertFalse(new_home.reload().is_home)
|
|
|
|
def test_set_home_with_permission_on_both_pages(self):
|
|
"""Change permission on both the old and the new home page is enough."""
|
|
old_home = create_page("old-home", "nav_playground.html", "en")
|
|
old_home.set_as_homepage()
|
|
new_home = create_page("new-home", "nav_playground.html", "en")
|
|
endpoint = self.get_admin_url(Page, "set_home", new_home.pk)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_page_permission(staff_user, new_home, can_change=True)
|
|
self.add_page_permission(staff_user, old_home, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertFalse(old_home.reload().is_home)
|
|
self.assertTrue(new_home.reload().is_home)
|
|
|
|
def test_get_permissions_page_permissions_can_change_without_global_permission(self):
|
|
"""Ensure PageAdmin.get_permissions computes can_change from allowed page paths.
|
|
|
|
This specifically covers the branch where the user cannot change global
|
|
permissions and can_change is computed via a prefix match against the
|
|
user's allowed page paths.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "get_permissions", page.pk)
|
|
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
other_staff = self._create_user("staff2", is_staff=True, is_superuser=False)
|
|
|
|
# Staff user must be able to access the view.
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_page_permission(staff_user, page, can_change=True)
|
|
|
|
# Ensure at least one GlobalPagePermission exists for the site so the
|
|
# template has something to render in the global section.
|
|
self.add_global_permission(other_staff, can_change=True)
|
|
|
|
# Add a page-level permission row that should be changeable by staff_user
|
|
# due to their own allowed page paths.
|
|
other_permission = self.add_page_permission(other_staff, page, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
rows = response.context["rows"]
|
|
permission_row = next(
|
|
row for row in rows if (not row.is_global and row.permission.pk == other_permission.pk)
|
|
)
|
|
self.assertTrue(permission_row.can_change)
|
|
|
|
def test_get_permissions_page_permissions_cant_change_with_only_global_page_permission(self):
|
|
"""Cover the False-case of can_change computation in PageAdmin.get_permissions.
|
|
|
|
The user is allowed to access the view via a *global* page permission,
|
|
but has no page-level permissions. Since get_permissions() computes
|
|
allowed pages with check_global=False, the allowed list is empty and
|
|
thus can_change evaluates to False.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "get_permissions", page.pk)
|
|
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
other_staff = self._create_user("staff3", is_staff=True, is_superuser=False)
|
|
|
|
# Access the view (has_change_permission) via global page permission.
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(staff_user, can_change=True)
|
|
|
|
# Create a page permission row for the page which staff_user should NOT
|
|
# be able to change based on page-level allowed paths.
|
|
other_permission = self.add_page_permission(other_staff, page, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
rows = response.context["rows"]
|
|
permission_row = next(
|
|
row for row in rows if (not row.is_global and row.permission.pk == other_permission.pk)
|
|
)
|
|
self.assertFalse(permission_row.can_change)
|
|
|
|
def test_pages_not_in_admin_index(self):
|
|
"""
|
|
User can't see the "Pages" section the admin
|
|
if he does not have change permissions on the Page model
|
|
and/or does not have global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = admin_reverse("app_list", args=["cms"])
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=False,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 404)
|
|
|
|
endpoint = self.get_pages_admin_list_uri()
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertEqual(response.status_code, 403)
|
|
|
|
def test_user_can_edit_page_settings(self):
|
|
"""
|
|
User can edit page settings if he has change permissions
|
|
on the Page model and and he has global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_page_change_uri("en", page)
|
|
redirect_to = self.get_pages_admin_list_uri()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
data = self._get_page_data(slug="permissions-2")
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertTrue(self._translation_exists(slug="permissions-2"))
|
|
|
|
def test_user_cant_edit_page_settings(self):
|
|
"""
|
|
User can't edit page settings if he does not
|
|
have change permissions on the Page model and/or
|
|
does not have global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_page_change_uri("en", page)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
data = self._get_page_data(slug="permissions-2")
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
page_perm = self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=False,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertFalse(self._translation_exists(slug="permissions-2"))
|
|
|
|
self.remove_permission(staff_user, "change_page")
|
|
page_perm.can_change = True
|
|
page_perm.save(update_fields=["can_change"])
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertFalse(self._translation_exists(slug="permissions-2"))
|
|
|
|
def test_user_can_edit_advanced_page_settings(self):
|
|
"""
|
|
User can edit advanced page settings if he has change permissions
|
|
on the Page model, global change permissions and
|
|
global change advanced settings permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk)
|
|
redirect_to = self.get_pages_admin_list_uri(site_id=page.site_id)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
data = self._get_page_data(reverse_id="permissions-2")
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertTrue(self._page_exists(reverse_id="permissions-2"))
|
|
|
|
def test_user_cant_edit_advanced_page_settings(self):
|
|
"""
|
|
User can't edit advanced page settings if he does not
|
|
have change permissions on the Page model,
|
|
does not have global change permissions and/or
|
|
does not have global change advanced settings permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
data = self._get_page_data(reverse_id="permissions-2")
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
page_perm = self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_change_advanced_settings=False,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertFalse(self._page_exists(reverse_id="permissions-2"))
|
|
|
|
self.remove_permission(staff_user, "change_page")
|
|
page_perm.can_change = True
|
|
page_perm.save(update_fields=["can_change"])
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertFalse(self._page_exists(reverse_id="permissions-2"))
|
|
|
|
def test_user_can_delete_empty_page(self):
|
|
"""
|
|
User can delete an empty page if he has delete & change permissions
|
|
on the Page model and he has page delete & change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "delete", page.pk)
|
|
redirect_to = admin_reverse("index")
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_page")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_delete=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": "yes"}
|
|
response = self.client.post(endpoint, data, follow=True)
|
|
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertFalse(self._page_exists())
|
|
|
|
def test_user_cant_delete_empty_page(self):
|
|
"""
|
|
User can't delete an empty page if he does not
|
|
have delete permissions on the Page model and/or
|
|
does not have global delete permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "delete", page.pk)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_page")
|
|
page_perm = self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=False,
|
|
can_delete=False,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": "yes"}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(self._page_exists())
|
|
|
|
self.remove_permission(staff_user, "delete_page")
|
|
page_perm.can_delete = True
|
|
page_perm.save(update_fields=["can_delete"])
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": "yes"}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(self._page_exists())
|
|
|
|
def test_user_can_delete_non_empty_page(self):
|
|
"""
|
|
User can delete a page with plugins if he has delete permissions
|
|
on the Page model, delete permissions on the plugins in the page
|
|
translations and page delete & change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "delete", page.pk)
|
|
redirect_to = admin_reverse("index")
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self._add_plugin_to_page(page)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_page")
|
|
self.add_permission(staff_user, "delete_link")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_delete=True,
|
|
)
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": "yes"}
|
|
response = self.client.post(endpoint, data, follow=True)
|
|
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertFalse(self._page_exists())
|
|
|
|
def test_user_cant_delete_non_empty_page(self):
|
|
"""
|
|
User can't delete a page with plugins if he
|
|
does not have delete permissions on the Page model,
|
|
does not have delete permissions on the plugins
|
|
in the page translations, and/or does not have
|
|
global delete permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "delete", page.pk)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self._add_plugin_to_page(page)
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_page")
|
|
|
|
page_perm = self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=False,
|
|
can_delete=False,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": "yes"}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(self._page_exists())
|
|
|
|
self.remove_permission(staff_user, "delete_page")
|
|
page_perm.can_delete = True
|
|
page_perm.save(update_fields=["can_delete"])
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": "yes"}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(self._page_exists())
|
|
|
|
def test_user_can_delete_empty_translation(self):
|
|
"""
|
|
User can delete an empty translation if he has
|
|
delete permissions on the Page model and he has
|
|
page delete & change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_admin_url(PageContent, "delete", translation.pk)
|
|
redirect_to = self.get_pages_admin_list_uri()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_page")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_delete=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"language": translation.language}
|
|
response = self.client.post(endpoint, data)
|
|
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertFalse(self._translation_exists())
|
|
|
|
def test_user_cant_delete_empty_translation(self):
|
|
"""
|
|
User can't delete an empty translation if he does not
|
|
have delete permissions on the Page model and/or
|
|
does not have global delete permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_admin_url(PageContent, "delete", translation.pk)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_page")
|
|
page_perm = self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=False,
|
|
can_delete=False,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"language": translation.language}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(self._translation_exists())
|
|
|
|
self.remove_permission(staff_user, "delete_page")
|
|
page_perm.can_delete = True
|
|
page_perm.save(update_fields=["can_delete"])
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"language": translation.language}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(self._translation_exists())
|
|
|
|
def test_user_can_delete_non_empty_translation(self):
|
|
"""
|
|
User can delete a translation with plugins if he has delete permissions
|
|
on the Page model, delete permissions on the plugins in the translation
|
|
and page delete & change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_admin_url(PageContent, "delete", translation.pk)
|
|
redirect_to = self.get_pages_admin_list_uri()
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self._add_plugin_to_page(page, language=translation.language)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_page")
|
|
self.add_permission(staff_user, "delete_link")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_delete=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"language": translation.language}
|
|
response = self.client.post(endpoint, data)
|
|
|
|
self.assertRedirects(response, redirect_to)
|
|
self.assertFalse(self._translation_exists())
|
|
|
|
def test_user_cant_delete_non_empty_translation(self):
|
|
"""
|
|
User can't delete a translation with plugins if he
|
|
does not have delete permissions on the Page model,
|
|
does not have delete permissions on the plugins in the translation,
|
|
and/or does not have global delete permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_admin_url(PageContent, "delete", translation.pk)
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
|
|
self._add_plugin_to_page(page, language=translation.language)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_page")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=False,
|
|
can_delete=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"language": translation.language}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(self._translation_exists())
|
|
|
|
def test_user_can_add_page_permissions(self):
|
|
"""
|
|
User can add page permissions if he has
|
|
change permissions on the Page model,
|
|
add permissions on the PagePermission model,
|
|
global change permission and global change permissions permission.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=staff_user)
|
|
|
|
data = self._get_page_permissions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_pagepermission")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_change_permissions=True,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertContainsPermissions(response)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertRedirects(response, endpoint)
|
|
self.assertTrue(self._page_permission_exists(user=staff_user_2))
|
|
|
|
def test_user_cant_add_page_permissions(self):
|
|
"""
|
|
User can't add page permissions if he
|
|
does not have change permissions on the Page model,
|
|
does not have add permissions on the PagePermission model,
|
|
does not have global change permission,
|
|
and/or does not have global change permissions permission.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=staff_user)
|
|
|
|
data = self._get_page_permissions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_pagepermission")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_change_permissions=False,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertNotContainsPermissions(response)
|
|
self.client.post(endpoint, data)
|
|
self.assertFalse(self._page_permission_exists(user=staff_user_2))
|
|
|
|
def test_user_can_edit_page_permissions(self):
|
|
"""
|
|
User can edit page permissions if he has
|
|
change permissions on the Page model,
|
|
change permissions on the PagePermission model,
|
|
global change permission and global change permissions permission.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=staff_user)
|
|
|
|
permission = self.add_page_permission(user=staff_user_2, page=page, can_change_permissions=True)
|
|
|
|
data = self._get_page_permissions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
id=permission.pk,
|
|
can_change_permissions=False,
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_pagepermission")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_change_permissions=True,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertContainsPermissions(response)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertRedirects(response, endpoint)
|
|
self.assertTrue(
|
|
self._page_permission_exists(
|
|
user=staff_user_2,
|
|
can_change_permissions=False,
|
|
)
|
|
)
|
|
|
|
def test_user_cant_edit_page_permissions(self):
|
|
"""
|
|
User can't edit page permissions if he
|
|
does not have change permissions on the Page model,
|
|
does not have change permissions on the PagePermission model,
|
|
does not have global change permission,
|
|
and/or does not have global change permissions permission.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=staff_user)
|
|
|
|
permission = self.add_page_permission(user=staff_user_2, page=page, can_change_permissions=True)
|
|
|
|
data = self._get_page_permissions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
id=permission.pk,
|
|
can_change_permissions=False,
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_pagepermission")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_change_permissions=False,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertNotContainsPermissions(response)
|
|
self.client.post(endpoint, data)
|
|
self.assertFalse(
|
|
self._page_permission_exists(
|
|
user=staff_user_2,
|
|
can_change_permissions=False,
|
|
)
|
|
)
|
|
|
|
def test_user_can_delete_page_permissions(self):
|
|
"""
|
|
User can delete page permissions if he has
|
|
change permissions on the Page model,
|
|
delete permissions on the PagePermission model,
|
|
global change permission and global change permissions permission.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=staff_user)
|
|
permission = self.add_page_permission(user=staff_user_2, page=page)
|
|
|
|
data = self._get_page_permissions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
id=permission.pk,
|
|
DELETE="on",
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_pagepermission")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_change_permissions=True,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertContainsPermissions(response)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertRedirects(response, endpoint)
|
|
self.assertFalse(self._page_permission_exists(user=staff_user_2))
|
|
|
|
def test_user_cant_delete_page_permissions(self):
|
|
"""
|
|
User can't delete page permissions if he
|
|
does not have change permissions on the Page model,
|
|
does not have delete permissions on the PagePermission model,
|
|
does not have global change permission,
|
|
and/or does not have global change permissions permission.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=staff_user)
|
|
permission = self.add_page_permission(user=staff_user_2, page=page)
|
|
|
|
data = self._get_page_permissions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
id=permission.pk,
|
|
DELETE="on",
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_pagepermission")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_change_permissions=False,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertNotContainsPermissions(response)
|
|
self.client.post(endpoint, data)
|
|
self.assertTrue(self._page_permission_exists(user=staff_user_2))
|
|
|
|
def test_user_can_add_page_view_restrictions(self):
|
|
"""
|
|
User can add page view restrictions if he has
|
|
change permissions on the Page model,
|
|
add permissions on the PagePermission model,
|
|
global change permission and global change permissions permission.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=staff_user)
|
|
|
|
data = self._get_page_view_restrictions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_pagepermission")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_change_permissions=True,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertContainsPermissions(response)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertRedirects(response, endpoint)
|
|
self.assertTrue(self._page_permission_exists(user=staff_user_2, can_view=True))
|
|
|
|
def test_user_cant_add_page_view_restrictions(self):
|
|
"""
|
|
User can't add page view restrictions if he
|
|
does not have change permissions on the Page model,
|
|
does not have add permissions on the PagePermission model,
|
|
does not have global change permission,
|
|
and/or does not have global change permissions permission.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=staff_user)
|
|
|
|
data = self._get_page_view_restrictions_data(
|
|
page=page.pk,
|
|
user=staff_user_2.pk,
|
|
)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_pagepermission")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_change_permissions=False,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertNotContainsPermissions(response)
|
|
self.client.post(endpoint, data)
|
|
self.assertFalse(self._page_permission_exists(user=staff_user_2, can_view=True))
|
|
|
|
def test_user_can_edit_page_view_restrictions(self):
|
|
"""
|
|
User can edit page view restrictions if he has
|
|
change permissions on the Page model,
|
|
change permissions on the PagePermission model,
|
|
global change permission and global change permissions permission.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=staff_user)
|
|
|
|
permission = self.add_page_permission(
|
|
user=staff_user_2,
|
|
page=page,
|
|
can_view=True,
|
|
grant_on=1,
|
|
)
|
|
|
|
data = model_to_dict(permission, exclude=["group"])
|
|
data["grant_on"] = 5
|
|
|
|
data = self._get_page_view_restrictions_data(**data)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_pagepermission")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_change_permissions=True,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertContainsPermissions(response)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertRedirects(response, endpoint)
|
|
self.assertTrue(
|
|
self._page_permission_exists(
|
|
user=staff_user_2,
|
|
grant_on=5,
|
|
)
|
|
)
|
|
|
|
def test_user_cant_edit_page_view_restrictions(self):
|
|
"""
|
|
User can't edit page view restrictions if he
|
|
does not have change permissions on the Page model,
|
|
does not have change permissions on the PagePermission model,
|
|
does not have global change permission,
|
|
and/or does not have global change permissions permission.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=staff_user)
|
|
permission = self.add_page_permission(
|
|
user=staff_user_2,
|
|
page=page,
|
|
can_view=True,
|
|
grant_on=1,
|
|
)
|
|
|
|
data = model_to_dict(permission, exclude=["group"])
|
|
data["grant_on"] = 5
|
|
|
|
data = self._get_page_view_restrictions_data(**data)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_pagepermission")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_change_permissions=False,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertNotContainsPermissions(response)
|
|
self.client.post(endpoint, data)
|
|
self.assertFalse(
|
|
self._page_permission_exists(
|
|
user=staff_user_2,
|
|
grant_on=5,
|
|
)
|
|
)
|
|
|
|
def test_user_can_delete_page_view_restrictions(self):
|
|
"""
|
|
User can delete view restrictions if he has
|
|
change permissions on the Page model,
|
|
delete permissions on the PagePermission model,
|
|
global change permission and global change permissions permission.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=staff_user)
|
|
permission = self.add_page_permission(
|
|
user=staff_user_2,
|
|
page=page,
|
|
can_view=True,
|
|
)
|
|
|
|
data = model_to_dict(permission, exclude=["group"])
|
|
data["DELETE"] = True
|
|
|
|
data = self._get_page_view_restrictions_data(**data)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_pagepermission")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_change_permissions=True,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertContainsPermissions(response)
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertRedirects(response, endpoint)
|
|
self.assertFalse(self._page_permission_exists(user=staff_user_2, can_view=True))
|
|
|
|
def test_user_cant_delete_page_view_restrictions(self):
|
|
"""
|
|
User can't delete view restrictions if he
|
|
does not have change permissions on the Page model,
|
|
does not have delete permissions on the PagePermission model,
|
|
does not have global change permission,
|
|
and/or does not have global change permissions permission.
|
|
"""
|
|
page = self._permissions_page
|
|
endpoint = self.get_admin_url(Page, "advanced", page.pk) + "?language=en"
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
staff_user_2 = self.get_staff_page_user(created_by=staff_user)
|
|
permission = self.add_page_permission(
|
|
user=staff_user_2,
|
|
page=page,
|
|
can_view=True,
|
|
)
|
|
|
|
data = model_to_dict(permission, exclude=["group"])
|
|
data["DELETE"] = True
|
|
|
|
data = self._get_page_view_restrictions_data(**data)
|
|
data["_continue"] = "1"
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_pagepermission")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
can_change_permissions=False,
|
|
can_change_advanced_settings=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.get(endpoint)
|
|
self.assertNotContainsPermissions(response)
|
|
self.client.post(endpoint, data)
|
|
self.assertTrue(self._page_permission_exists(user=staff_user_2, can_view=True))
|
|
|
|
# Plugin related tests
|
|
|
|
def test_user_can_add_plugin(self):
|
|
"""
|
|
User can add a plugin if he has change permissions
|
|
on the Page model, add permissions on the plugin model
|
|
and global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
placeholder = page.get_placeholders("en").get(slot="body")
|
|
plugins = placeholder.get_plugins("en").filter(plugin_type="LinkPlugin")
|
|
endpoint = self._get_add_plugin_uri(page)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_link")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"name": "A Link", "external_link": "https://www.django-cms.org"}
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(plugins.count(), 1)
|
|
|
|
def test_user_cant_add_plugin(self):
|
|
"""
|
|
User can't add a plugin if he
|
|
does not have change permissions on the Page model,
|
|
does not have add permissions on the plugin model
|
|
and/or does not have global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
placeholder = page.get_placeholders("en").get(slot="body")
|
|
plugins = placeholder.get_plugins("en").filter(plugin_type="LinkPlugin")
|
|
endpoint = self._get_add_plugin_uri(page)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_link")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=False,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"name": "A Link", "external_link": "https://www.django-cms.org"}
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertEqual(plugins.count(), 0)
|
|
|
|
def test_user_can_edit_plugin(self):
|
|
"""
|
|
User can edit a plugin if he has change permissions
|
|
on the Page model, change permissions on the plugin model
|
|
and global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
endpoint = self.get_change_plugin_uri(plugin)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_link")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = model_to_dict(plugin, fields=["name", "external_link"])
|
|
data["name"] = "A link 2"
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 200)
|
|
plugin.refresh_from_db()
|
|
self.assertEqual(plugin.name, data["name"])
|
|
|
|
def test_user_cant_edit_plugin(self):
|
|
"""
|
|
User can't edit a plugin if he
|
|
does not have change permissions on the Page model,
|
|
does not have change permissions on the plugin model
|
|
and/or does not have global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
endpoint = self.get_change_plugin_uri(plugin)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_link")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=False,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = model_to_dict(plugin, fields=["name", "external_link"])
|
|
data["name"] = "A link 2"
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
plugin.refresh_from_db()
|
|
self.assertNotEqual(plugin.name, data["name"])
|
|
|
|
def test_user_can_delete_plugin(self):
|
|
"""
|
|
User can delete a plugin if he has change permissions
|
|
on the Page model, delete permissions on the plugin model
|
|
and global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
endpoint = self.get_delete_plugin_uri(plugin)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_link")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": True}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertContains(response, '<div class="success"></div>')
|
|
self.assertFalse(CMSPlugin.objects.filter(pk=plugin.pk).exists())
|
|
|
|
def test_user_cant_delete_plugin(self):
|
|
"""
|
|
User can't delete a plugin if he
|
|
does not have change permissions on the Page model,
|
|
does not have delete permissions on the plugin model
|
|
and/or does not have global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
endpoint = self.get_delete_plugin_uri(plugin)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "delete_link")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=False,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
data = {"post": True}
|
|
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(CMSPlugin.objects.filter(pk=plugin.pk).exists())
|
|
|
|
def test_user_can_move_plugin(self):
|
|
"""
|
|
User can move a plugin if he has change permissions
|
|
on the Page model, change permissions on the plugin model
|
|
and global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
endpoint = self.get_move_plugin_uri(plugin)
|
|
source_placeholder = plugin.placeholder
|
|
target_placeholder = page.get_placeholders("en").get(slot="right-column")
|
|
|
|
data = self._get_move_data(plugin, position=1, placeholder=target_placeholder)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_link")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTrue(target_placeholder.get_plugins("en").filter(pk=plugin.pk))
|
|
self.assertFalse(source_placeholder.get_plugins("en").filter(pk=plugin.pk))
|
|
|
|
def test_user_cant_move_plugin(self):
|
|
"""
|
|
User can't move a plugin if he
|
|
does not have change permissions on the Page model,
|
|
does not have change permissions on the plugin model
|
|
and/or does not have global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
endpoint = self.get_move_plugin_uri(plugin)
|
|
source_placeholder = plugin.placeholder
|
|
target_placeholder = page.get_placeholders("en").get(slot="right-column")
|
|
|
|
data = self._get_move_data(plugin, position=1, placeholder=target_placeholder)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "change_link")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=False,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertFalse(target_placeholder.get_plugins("en").filter(pk=plugin.pk))
|
|
self.assertTrue(source_placeholder.get_plugins("en").filter(pk=plugin.pk))
|
|
|
|
def test_user_can_copy_plugin(self):
|
|
"""
|
|
User can copy a plugin if he has change permissions
|
|
on the Page model, add permissions on the plugin model
|
|
and global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_copy_plugin_uri(plugin)
|
|
source_placeholder = plugin.placeholder
|
|
page.get_content_obj(translation.language)
|
|
target_placeholder = page.get_placeholders(translation.language).get(slot="right-column")
|
|
|
|
data = {
|
|
"source_plugin_id": plugin.pk,
|
|
"source_placeholder_id": source_placeholder.pk,
|
|
"source_language": plugin.language,
|
|
"target_language": translation.language,
|
|
"target_placeholder_id": target_placeholder.pk,
|
|
}
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_link")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTrue(source_placeholder.get_plugins("en").filter(pk=plugin.pk).exists())
|
|
self.assertTrue(
|
|
target_placeholder.get_plugins(translation.language).filter(plugin_type=plugin.plugin_type).exists()
|
|
)
|
|
|
|
def test_user_cant_copy_plugin(self):
|
|
"""
|
|
User can't copy a plugin if he
|
|
does not have change permissions on the Page model,
|
|
does not have add permissions on the plugin model,
|
|
and/or does not have global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugin = self._add_plugin_to_page(page)
|
|
translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_copy_plugin_uri(plugin)
|
|
source_placeholder = plugin.placeholder
|
|
target_placeholder = page.get_placeholders(translation.language).get(slot="right-column")
|
|
|
|
data = {
|
|
"source_plugin_id": plugin.pk,
|
|
"source_placeholder_id": source_placeholder.pk,
|
|
"source_language": plugin.language,
|
|
"target_language": translation.language,
|
|
"target_placeholder_id": target_placeholder.pk,
|
|
}
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_link")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=False,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertTrue(source_placeholder.get_plugins("en").filter(pk=plugin.pk).exists())
|
|
self.assertFalse(
|
|
target_placeholder.get_plugins(translation.language).filter(plugin_type=plugin.plugin_type).exists()
|
|
)
|
|
|
|
def test_user_can_copy_plugins_to_language(self):
|
|
"""
|
|
User can copy all plugins to another language if he has
|
|
change permissions on the Page model, add permissions on the
|
|
plugins being copied and global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
source_translation = self.get_pagecontent_obj(page, "en")
|
|
target_translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_admin_url(PageContent, "copy_language", source_translation.pk)
|
|
plugins = [
|
|
self._add_plugin_to_page(page),
|
|
self._add_plugin_to_page(page),
|
|
self._add_plugin_to_page(page),
|
|
self._add_plugin_to_page(page),
|
|
]
|
|
source_placeholder = plugins[0].placeholder
|
|
target_placeholder = target_translation.get_placeholders().get(slot=source_placeholder.slot)
|
|
|
|
data = {
|
|
"source_language": "en",
|
|
"target_language": target_translation.language,
|
|
}
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_link")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=True,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 200)
|
|
new_plugins = target_placeholder.get_plugins()
|
|
self.assertEqual(new_plugins.count(), len(plugins))
|
|
|
|
def test_user_cant_copy_plugins_to_language(self):
|
|
"""
|
|
User can't copy all plugins to another language if he does have
|
|
change permissions on the Page model, does not have add permissions
|
|
on the plugins being copied and/or does not have global
|
|
change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
translation = self._add_translation_to_page(page)
|
|
endpoint = self.get_admin_url(PageContent, "copy_language", translation.pk)
|
|
plugins = [
|
|
self._add_plugin_to_page(page),
|
|
self._add_plugin_to_page(page),
|
|
self._add_plugin_to_page(page),
|
|
self._add_plugin_to_page(page),
|
|
]
|
|
placeholder = plugins[0].placeholder
|
|
|
|
data = {
|
|
"source_language": "en",
|
|
"target_language": translation.language,
|
|
}
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_permission(staff_user, "add_link")
|
|
self.add_page_permission(
|
|
staff_user,
|
|
page,
|
|
can_change=False,
|
|
)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, data)
|
|
self.assertEqual(response.status_code, 403)
|
|
new_plugins = placeholder.get_plugins(translation.language)
|
|
self.assertEqual(new_plugins.count(), 0)
|
|
|
|
# Placeholder related tests
|
|
|
|
def test_user_can_clear_empty_placeholder(self):
|
|
"""
|
|
User can clear an empty placeholder if he has change permissions
|
|
on the Page model and global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
placeholder = page.get_placeholders("en").get(slot="body")
|
|
endpoint = self.get_clear_placeholder_url(placeholder)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(staff_user, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, {"test": 0})
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_user_cant_clear_empty_placeholder(self):
|
|
"""
|
|
User can't clear an empty placeholder if he does not have
|
|
change permissions on the Page model and/or does not have
|
|
global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
placeholder = page.get_placeholders("en").get(slot="body")
|
|
endpoint = self.get_clear_placeholder_url(placeholder)
|
|
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(staff_user, can_change=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, {"test": 0})
|
|
self.assertEqual(response.status_code, 403)
|
|
|
|
def test_user_can_clear_non_empty_placeholder(self):
|
|
"""
|
|
User can clear a placeholder with plugins if he has
|
|
change permissions on the Page model, delete permissions
|
|
on the plugin models in the placeholder and global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugins = [
|
|
self._add_plugin_to_page(page, "TextPlugin"),
|
|
self._add_plugin_to_page(page, "LinkPlugin"),
|
|
]
|
|
placeholder = plugins[0].placeholder
|
|
endpoint = self.get_clear_placeholder_url(placeholder)
|
|
|
|
self.add_permission(staff_user, "delete_text")
|
|
self.add_permission(staff_user, "delete_link")
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(staff_user, can_change=True)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, {"test": 0})
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(placeholder.get_plugins("en").count(), 0)
|
|
|
|
def test_user_cant_clear_non_empty_placeholder(self):
|
|
"""
|
|
User can't clear a placeholder with plugins if he does not have
|
|
change permissions on the Page model, does not have delete
|
|
permissions on the plugin models in the placeholder and/or
|
|
does not have global change permissions.
|
|
"""
|
|
page = self._permissions_page
|
|
staff_user = self.get_staff_user_with_no_permissions()
|
|
plugins = [
|
|
self._add_plugin_to_page(page, "TextPlugin"),
|
|
self._add_plugin_to_page(page, "LinkPlugin"),
|
|
]
|
|
placeholder = plugins[0].placeholder
|
|
endpoint = self.get_clear_placeholder_url(placeholder)
|
|
|
|
self.add_permission(staff_user, "delete_text")
|
|
self.add_permission(staff_user, "delete_link")
|
|
self.add_permission(staff_user, "change_page")
|
|
self.add_global_permission(staff_user, can_change=False)
|
|
|
|
with self.login_user_context(staff_user):
|
|
response = self.client.post(endpoint, {"test": 0})
|
|
self.assertEqual(response.status_code, 403)
|
|
self.assertEqual(placeholder.get_plugins("en").count(), 2)
|
|
|
|
|
|
@override_settings(CMS_PERMISSION=False)
|
|
class PermissionsOffTest(PermissionsTestCase):
|
|
"""
|
|
Tests all user interactions with the page admin
|
|
while permissions are set to False.
|
|
"""
|
|
|
|
|
|
@override_settings(ROOT_URLCONF="cms.test_utils.project.noadmin_urls")
|
|
class NoAdminPageTests(CMSTestCase):
|
|
def test_get_page_from_request_fakeadmin_nopage(self):
|
|
noadmin_apps = [app for app in installed_apps() if app != "django.contrib.admin"]
|
|
with self.settings(INSTALLED_APPS=noadmin_apps):
|
|
request = self.get_request("/en/admin/")
|
|
page = get_page_from_request(request)
|
|
self.assertEqual(page, None)
|