diff --git a/aircox/templates/aircox/program_detail.html b/aircox/templates/aircox/program_detail.html new file mode 100644 index 0000000..fb2f154 --- /dev/null +++ b/aircox/templates/aircox/program_detail.html @@ -0,0 +1,90 @@ +{% extends "aircox/basepage_detail.html" %} +{% load static i18n humanize honeypot aircox %} +{% comment %} +Base template used to display a Page + +Context: +- page: page +- parent: parent page +{% endcomment %} + +{% block header_crumbs %} +{{ block.super }} +{% if page.category %} +{% if parent %} / {% endif %} {{ page.category.title }} +{% endif %} +{% endblock %} + +{% block top-nav-tools %} +{% has_perm page page.change_permission_codename simple=True as can_edit %} +{% if can_edit %} + + + +   + {% translate "Edit" %} + +{% endif %} +{% endblock %} + +{% block main %} +{{ block.super }} + +{% block comments %} +{% if comments or comment_form %} +
+

{% translate "Comments" %}

+ + {% for comment in comments %} +
+
+

+ {{ comment.nickname }} + +
+ {{ comment.content }} +

+
+
+ {% endfor %} + + {% if comment_form %} +
+
{% translate "Post a comment" %}
+ {% csrf_token %} + {% render_honeypot_field "website" %} + + {% for field in comment_form %} +
+
+ +
+
+
+

{{ field }}

+ {% if field.errors %} +

{{ field.errors }}

+ {% endif %} + {% if field.help_text %} +

{{ field.help_text|safe }}

+ {% endif %} +
+
+
+ {% endfor %} +
+ + +
+
+ {% endif %} +
+{% endif %} + +{% endblock %} +{% endblock %} diff --git a/aircox/templates/aircox/program_form.html b/aircox/templates/aircox/program_form.html new file mode 100644 index 0000000..b14fc3f --- /dev/null +++ b/aircox/templates/aircox/program_form.html @@ -0,0 +1,91 @@ +{% extends "aircox/basepage_detail.html" %} +{% load static i18n humanize honeypot aircox %} +{% comment %} +Base template used to display a Page + +Context: +- page: page +- parent: parent page +{% endcomment %} + +{% block header_crumbs %} +{{ block.super }} +{% if page.category %} +{% if parent %} / {% endif %} {{ page.category.title }} +{% endif %} +{% endblock %} + +{% block top-nav-tools %} + + + +   + {% translate "View" %} + +{% endblock %} + +{% block main %} +
{% csrf_token %} + {{ form.as_p }} + +
+{{ block.super }} + +{% block comments %} +{% if comments or comment_form %} +
+

{% translate "Comments" %}

+ + {% for comment in comments %} +
+
+

+ {{ comment.nickname }} + +
+ {{ comment.content }} +

+
+
+ {% endfor %} + + {% if comment_form %} +
+
{% translate "Post a comment" %}
+ {% csrf_token %} + {% render_honeypot_field "website" %} + + {% for field in comment_form %} +
+
+ +
+
+
+

{{ field }}

+ {% if field.errors %} +

{{ field.errors }}

+ {% endif %} + {% if field.help_text %} +

{{ field.help_text|safe }}

+ {% endif %} +
+
+
+ {% endfor %} +
+ + +
+
+ {% endif %} +
+{% endif %} + +{% endblock %} +{% endblock %} diff --git a/aircox/tests/test_permissions.py b/aircox/tests/test_permissions.py index 25866b3..a561f33 100644 --- a/aircox/tests/test_permissions.py +++ b/aircox/tests/test_permissions.py @@ -1,5 +1,6 @@ import pytest from django.contrib.auth.models import User, Group +from django.urls import reverse @pytest.mark.django_db() @@ -23,3 +24,13 @@ def test_group_can_change_program(user, client, program): user = User.objects.get(pk=user.pk) # reload user in order to have permissions set assert program.editors in user.groups.all() assert user.has_perm("aircox.%s" % program.change_permission_codename) + + +@pytest.mark.django_db() +def test_group_change_program(user, client, program): + client.force_login(user) + response = client.get(reverse("program-edit", kwargs={"pk": program.pk})) + assert response.status_code == 403 + user.groups.add(program.editors) + response = client.get(reverse("program-edit", kwargs={"pk": program.pk})) + assert response.status_code == 200 diff --git a/aircox/tests/test_program.py b/aircox/tests/test_program.py new file mode 100644 index 0000000..89a575e --- /dev/null +++ b/aircox/tests/test_program.py @@ -0,0 +1,17 @@ +import pytest +from django.urls import reverse + + +@pytest.mark.django_db() +def test_edit_program(user, client, program): + client.force_login(user) + response = client.get(reverse("program-detail", kwargs={"slug": program.slug})) + assert response.status_code == 200 + assert b"fa-pen" not in response.content + user.groups.add(program.editors) + response = client.get(reverse("program-detail", kwargs={"slug": program.slug})) + assert b"fa-pen" in response.content + assert b"foobar" not in response.content + response = client.post(reverse("program-edit", kwargs={"pk": program.pk}), {"content": "foobar"}) + response = client.get(reverse("program-detail", kwargs={"slug": program.slug})) + assert b"foobar" in response.content diff --git a/aircox/urls.py b/aircox/urls.py index 0ad7df6..8857297 100755 --- a/aircox/urls.py +++ b/aircox/urls.py @@ -92,6 +92,11 @@ urls = [ views.ProgramDetailView.as_view(), name="program-detail", ), + path( + _("program//edit/"), + views.ProgramUpdateView.as_view(), + name="program-edit", + ), path( _("programs//episodes/"), views.EpisodeListView.as_view(), diff --git a/aircox/views/__init__.py b/aircox/views/__init__.py index e4d9d4a..48e1191 100644 --- a/aircox/views/__init__.py +++ b/aircox/views/__init__.py @@ -16,6 +16,7 @@ from .program import ( ProgramListView, ProgramPageDetailView, ProgramPageListView, + ProgramUpdateView, ) __all__ = ( @@ -39,4 +40,5 @@ __all__ = ( "ProgramListView", "ProgramPageDetailView", "ProgramPageListView", + "ProgramUpdateView", ) diff --git a/aircox/views/page.py b/aircox/views/page.py index 7a0ef42..90ead86 100644 --- a/aircox/views/page.py +++ b/aircox/views/page.py @@ -1,6 +1,7 @@ from django.http import Http404, HttpResponse from django.utils.translation import gettext_lazy as _ from django.views.generic import DetailView, ListView +from django.views.generic.edit import UpdateView from honeypot.decorators import check_honeypot from ..filters import PageFilters @@ -138,3 +139,7 @@ class PageDetailView(BasePageDetailView): comment.page = self.object comment.save() return self.get(request, *args, **kwargs) + + +class PageUpdateView(BaseView, UpdateView): + pass diff --git a/aircox/views/program.py b/aircox/views/program.py index fb36d7d..2b2c9fe 100644 --- a/aircox/views/program.py +++ b/aircox/views/program.py @@ -1,8 +1,10 @@ from django.urls import reverse +from django.contrib.auth.mixins import UserPassesTestMixin + from ..models import Page, Program, StaticPage from .mixins import ParentMixin -from .page import PageDetailView, PageListView +from .page import PageDetailView, PageListView, PageUpdateView __all__ = ["ProgramPageDetailView", "ProgramDetailView", "ProgramPageListView"] @@ -23,10 +25,25 @@ class BaseProgramMixin: class ProgramDetailView(BaseProgramMixin, PageDetailView): model = Program + def get_template_names(self): + return super().get_template_names() + ["aircox/program_detail.html"] + def get_sidebar_queryset(self): return super().get_sidebar_queryset().filter(parent=self.program) +class ProgramUpdateView(UserPassesTestMixin, BaseProgramMixin, PageUpdateView): + model = Program + fields = ["content"] + + def get_sidebar_queryset(self): + return super().get_sidebar_queryset().filter(parent=self.program) + + def test_func(self): + program = self.get_object() + return self.request.user.has_perm("aircox.%s" % program.change_permission_codename) + + class ProgramListView(PageListView): model = Program attach_to_value = StaticPage.ATTACH_TO_PROGRAMS