Skip to content

Commit 5eff8c4

Browse files
authored
feat: add public language support (#27)
* Refactor language permissions to handle public languages. * refactor language permissions in views, revert languages endpoint (display all available languages) * fix pytest dependencies * test: add coverage for endpoint using non-public language * refactor: remove unused app/plugin dependencies from test settings and requirements * fix: Refactor permission method to remove redundant return statement
1 parent bf441ad commit 5eff8c4

File tree

7 files changed

+210
-26
lines changed

7 files changed

+210
-26
lines changed

djangocms_rest/permissions.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from cms.models import Page, PageContent
2-
from cms.utils.i18n import get_language_tuple
2+
from cms.utils.i18n import get_language_tuple, get_languages
33
from cms.utils.page_permissions import user_can_view_page
44
from rest_framework.exceptions import NotFound
55
from rest_framework.permissions import BasePermission
@@ -10,7 +10,7 @@
1010

1111
class IsAllowedLanguage(BasePermission):
1212
"""
13-
Check whether the provided language is allowed.
13+
Check whether the provided language is allowed for a given site.
1414
"""
1515

1616
def has_permission(self, request: Request, view: BaseAPIView) -> bool:
@@ -22,6 +22,24 @@ def has_permission(self, request: Request, view: BaseAPIView) -> bool:
2222
return True
2323

2424

25+
class IsAllowedPublicLanguage(IsAllowedLanguage):
26+
"""
27+
Check whether the provided language is allowed and public for a given site.
28+
"""
29+
def has_permission(self, request: Request, view: BaseAPIView) -> bool:
30+
super().has_permission(request, view)
31+
language = view.kwargs.get("language")
32+
languages = get_languages()
33+
public_languages = [
34+
lang["code"] for lang in languages if lang.get("public", True)
35+
]
36+
if language not in public_languages:
37+
raise NotFound()
38+
return True
39+
40+
41+
42+
2543
class CanViewPage(IsAllowedLanguage):
2644
"""
2745
Check whether the provided language is allowed and the user can view the page.

djangocms_rest/views.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
CanViewPage,
1313
CanViewPageContent,
1414
IsAllowedLanguage,
15+
IsAllowedPublicLanguage,
1516
)
1617
from djangocms_rest.serializers.languages import LanguageSerializer
1718
from djangocms_rest.serializers.pages import (
@@ -64,7 +65,7 @@ def get(self, request: Request | None) -> Response:
6465

6566

6667
class PageListView(BaseListAPIView):
67-
permission_classes = [IsAllowedLanguage]
68+
permission_classes = [IsAllowedPublicLanguage]
6869
serializer_class = PageListSerializer
6970
pagination_class = LimitOffsetPagination
7071

@@ -90,7 +91,7 @@ def get_queryset(self):
9091
raise NotFound()
9192

9293
class PageTreeListView(BaseAPIView):
93-
permission_classes = [IsAllowedLanguage]
94+
permission_classes = [IsAllowedPublicLanguage]
9495
serializer_class = PageMetaSerializer
9596

9697
def get(self, request, language):
@@ -119,7 +120,7 @@ def get(self, request, language):
119120

120121

121122
class PageDetailView(BaseAPIView):
122-
permission_classes = [CanViewPage]
123+
permission_classes = [IsAllowedPublicLanguage, CanViewPage]
123124
serializer_class = PageContentSerializer
124125

125126
def get(self, request: Request, language: str, path: str = "") -> Response:
@@ -140,8 +141,8 @@ def get(self, request: Request, language: str, path: str = "") -> Response:
140141

141142

142143
class PlaceholderDetailView(BaseAPIView):
144+
permission_classes = [IsAllowedPublicLanguage, CanViewPageContent]
143145
serializer_class = PlaceholderSerializer
144-
permission_classes = [CanViewPageContent]
145146

146147
@extend_placeholder_schema
147148

poetry.lock

Lines changed: 167 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ classifiers = [
3333
]
3434

3535
[tool.poetry.dependencies]
36-
python = ">=3.9"
36+
python = ">=3.9,<4"
3737
django-cms = ">=4.1.1"
3838
djangorestframework = "*"
3939
djangocms-link = "^5.0.0"
4040
djangocms-text = "^0.8.0"
4141
pytest-cov = "^6.0.0"
4242
pytest-django = "^4.10.0"
43+
djangocms-picture = "^4.1.1"
44+
django-filer = "^3.3.1"
4345

4446
[tool.poetry.group.dev.dependencies]
4547
pytest = "^7.3.1"

tests/endpoints/test_page_list.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ def test_get_paginated_list(self):
7373
response = self.client.get(reverse("page-list", kwargs={"language": "xx"}))
7474
self.assertEqual(response.status_code, 404)
7575

76+
# Check Non-Public language
77+
response = self.client.get(reverse("page-list", kwargs={"language": "fr"}))
78+
self.assertEqual(response.status_code, 404)
79+
7680
# GET PREVIEW
7781
response = self.client.get(reverse("preview-page-list", kwargs={"language": "en"}))
7882
self.assertEqual(response.status_code, 403)

tests/requirements/base.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# requirements from setup.py
22
djangorestframework
3-
djangocms-picture>=2.1.0
4-
djangocms-link>=2.2.1
53
djangocms-text
64
setuptools
75

tests/settings.py

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,7 @@ def __getitem__(self, item):
3131
'treebeard',
3232
'sekizai',
3333

34-
'djangocms_link',
35-
'djangocms_picture',
3634
'djangocms_text',
37-
'filer',
38-
'easy_thumbnails',
3935
'tests.test_app',
4036
]
4137

@@ -71,23 +67,23 @@ def __getitem__(self, item):
7167
CMS_LANGUAGES = {
7268
1: [
7369
{
74-
'code': 'en',
75-
'name': gettext('English'),
76-
'public': True,
70+
"code": "en",
71+
"name": gettext("English"),
72+
"public": True,
7773
},
7874
{
79-
'code': 'it',
80-
'name': gettext('Italiano'),
81-
'public': True,
75+
"code": "it",
76+
"name": gettext("Italiano"),
77+
"public": True,
8278
},
8379
{
84-
'code': 'fr',
85-
'name': gettext('French'),
86-
'public': True,
80+
"code": "fr",
81+
"name": gettext("French"),
82+
"public": False,
8783
},
8884
],
89-
'default': {
90-
'hide_untranslated': False,
85+
"default": {
86+
"hide_untranslated": False,
9187
},
9288
}
9389

0 commit comments

Comments
 (0)