Skip to content

Commit

Permalink
Respect page viewing permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
fsbraun committed May 24, 2024
1 parent 9a12a36 commit e8dba36
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 15 deletions.
33 changes: 24 additions & 9 deletions djangocms_rest/serializers/placeholder.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
from cms.utils.conf import get_cms_setting
from cms.utils.plugins import get_plugins
from django.contrib.sites.shortcuts import get_current_site
from django.template.context import Context
from django.template.defaulttags import now
from rest_framework import serializers
from rest_framework.request import Request
from sekizai.context import SekizaiContext
from sekizai.helpers import get_varname


def _get_placeholder_cache_version(placeholder, lang, site_id):
Expand Down Expand Up @@ -183,6 +184,7 @@ class Meta:
exclude = (
"id",
"placeholder",
"language",
"position",
"creation_date",
"changed_date",
Expand Down Expand Up @@ -212,14 +214,27 @@ def __init__(
use_cache=True,
)
if request.GET.get("html", False):
content_renderer = ContentRenderer(request)
placeholder.html = content_renderer.render_placeholder(
placeholder,
context=Context({"request": request, "LANGUAGE_CODE": language}),
language=language,
use_cache=True,
)
self.fields["html"] = serializers.CharField()
html = self.render_html(request, placeholder, language)
for key, value in html.items():
if not hasattr(placeholder, key):
setattr(placeholder, key, value)
self.fields[key] = serializers.CharField()
placeholder.label = placeholder.get_label()
placeholder.language = language
super().__init__(placeholder, *args, **kwargs)

def render_html(self, request, placeholder, language):
content_renderer = ContentRenderer(request)
context = SekizaiContext({"request": request, "LANGUAGE_CODE": language})
content = content_renderer.render_placeholder(
placeholder,
context=context,
language=language,
use_cache=True,
)
sekizai_blocks = context[get_varname()]

return {
"html": content,
**{key: "".join(value) for key, value in sekizai_blocks.items() if value},
}
38 changes: 32 additions & 6 deletions djangocms_rest/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from cms.models import Page, PageUrl, Placeholder
from cms.models import Page, PageUrl, Placeholder, PageContent
from cms.utils.conf import get_languages
from cms.utils.i18n import get_language_tuple
from cms.utils.page_permissions import user_can_view_page
from django.contrib.sites.shortcuts import get_current_site
from django.http import Http404
from django.urls import reverse
Expand All @@ -12,6 +13,7 @@


class APIView(DRFAPIView):
# This is a base class for all API views. It sets the allowed methods to GET and OPTIONS.
http_method_names = ("get", "options")


Expand All @@ -30,9 +32,7 @@ def get(self, request, format=None):


class PageList(APIView):
"""
List of all pages on this site for a given language.
"""
"""List of all pages on this site for a given language."""

def get(self, request, language, format=None):
site = get_current_site(request)
Expand All @@ -42,7 +42,11 @@ def get(self, request, language, format=None):
qs = Page.objects.filter(node__site=site)
if request.user.is_anonymous:
qs = qs.filter(login_required=False)
pages = (RESTPage(request, page, language=language) for page in qs)
pages = (
RESTPage(request, page, language=language)
for page in qs
if user_can_view_page(request.user, page)
)
serializer = PageSerializer(pages, many=True, read_only=True)
return Response(serializer.data)

Expand Down Expand Up @@ -74,14 +78,31 @@ def get(self, request, language, path="", format=None):
if language not in allowed_languages:
raise Http404
page = self.get_object(site, path)

# Check if the user has permission to view the page
if not user_can_view_page(request.user, page):
raise Http404

serializer = PageSerializer(
RESTPage(request, page, language=language), read_only=True
)
return Response(serializer.data)


class PlaceholderDetail(APIView):
"""Placeholder contain the dynamic content."""
"""Placeholder contain the dynamic content. This view retrieves the content as a
structured nested object.
Attributes:
- "slot": The slot name of the placeholder.
- "content": The content of the placeholder as a nested JSON tree
- "language": The language of the content
- "label": The verbose label of the placeholder
Optional (if the get parameter `?html=1` is added to the API url):
- "html": The content rendered as html. Sekizai blocks such as "js" or "css" will be added
as separate attributes"""

def get_placeholder(self, content_type_id, object_id, slot):
try:
Expand All @@ -103,6 +124,11 @@ def get(self, request, language, content_type_id, object_id, slot, format=None):
)
if source is None:
raise Http404
# Check if the user has permission to view the page (should the placeholder be on a page)
if isinstance(source, PageContent) and not user_can_view_page(
request.user, source.page
):
raise Http404
serializer = PlaceholderSerializer(
request, placeholder, language, read_only=True
)
Expand Down

0 comments on commit e8dba36

Please sign in to comment.