diff --git a/club/models.py b/club/models.py index 6c2baec8..e9ad358e 100644 --- a/club/models.py +++ b/club/models.py @@ -238,7 +238,7 @@ class Club(models.Model): def can_be_edited_by(self, user: User) -> bool: """Method to see if that object can be edited by the given user.""" - return self.has_rights_in_club(user) + return user.has_perm("club.change_club") or self.has_rights_in_club(user) def can_roles_be_edited_by(self, user: User) -> bool: """Return True if the given user can edit the roles of this club""" diff --git a/club/templates/club/club_detail.jinja b/club/templates/club/club_detail.jinja index bc1a1c0b..8b63998b 100644 --- a/club/templates/club/club_detail.jinja +++ b/club/templates/club/club_detail.jinja @@ -26,6 +26,15 @@ {% endblock %} {% block content %} + {% if user.is_authenticated and user.can_edit(club) %} + + {% trans %}Edit{% endtrans %} + + {% endif %} +

{{ club.name }}

diff --git a/club/tests/test_page.py b/club/tests/test_page.py index ce5746e7..7cefa677 100644 --- a/club/tests/test_page.py +++ b/club/tests/test_page.py @@ -1,8 +1,9 @@ -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Callable import pytest from aemark import markdown from bs4 import BeautifulSoup +from django.contrib.auth.models import Permission from django.urls import reverse from model_bakery import baker from pytest_django.asserts import assertHTMLEqual, assertRedirects @@ -16,13 +17,20 @@ if TYPE_CHECKING: @pytest.mark.django_db -def test_page_display_on_club_main_page(client: Client): +@pytest.mark.parametrize("user_factory", [lambda: None, subscriber_user.make]) +def test_page_display_on_club_main_page( + client: Client, user_factory: Callable[[], User | None] +): """Test the club Page is properly displayed on the club main view""" club = baker.make(Club) + # create another previous revision, to test that we display the most recent one + baker.make(PageRev, page=club.page, revision=1) content = "# foo\nLorem ipsum dolor sit amet" - baker.make(PageRev, page=club.page, revision=1, content=content) - res = client.get(reverse("club:club_view", kwargs={"club_id": club.id})) + baker.make(PageRev, page=club.page, revision=2, content=content) + if user := user_factory(): + client.force_login(user) + res = client.get(reverse("club:club_view", kwargs={"club_id": club.id})) assert res.status_code == 200 soup = BeautifulSoup(res.text, "lxml") detail_html = soup.find(id="club-page").find(class_="markdown") @@ -30,20 +38,60 @@ def test_page_display_on_club_main_page(client: Client): @pytest.mark.django_db -def test_club_main_page_without_content(client: Client): - """Test the club view works, even if the club page is empty""" +@pytest.mark.parametrize( + ("user_factory", "can_view_tabs", "can_view_edit_button"), + [ + (lambda _: None, False, False), + (lambda _: baker.make(User), False, False), + (lambda _: subscriber_user.make(), True, False), + ( + # admin user + lambda _: subscriber_user.make( + user_permissions=[Permission.objects.get(codename="change_club")] + ), + True, + True, + ), + ( + # club board member + lambda club: ( + baker.make( + Membership, + club=club, + role=baker.make(ClubRole, is_board=True), + user=subscriber_user.make(), + ).user + ), + True, + True, + ), + ], + ids=["anonymous", "public", "subscriber", "admin", "club board"], +) +@pytest.mark.django_db +def test_club_main_page_displayed_elements( + client: Client, user_factory, can_view_tabs, can_view_edit_button +): + """Test that the appropriate elements are displayed depending on user status.""" club = baker.make(Club) - club.page.revisions.all().delete() + if user := user_factory(club): + client.force_login(user) res = client.get(reverse("club:club_view", kwargs={"club_id": club.id})) assert res.status_code == 200 soup = BeautifulSoup(res.text, "lxml") - detail_html = soup.find(id="club-page") - assert detail_html.find_all("markdown") == [] + tabs = soup.find(class_="tool_bar") + assert tabs is not None if can_view_tabs else tabs is None + edit_btn = soup.find( + "a", + href=reverse("core:page_edit", kwargs={"page_name": club.page.get_full_name()}), + ) + assert edit_btn is not None if can_view_edit_button else edit_btn is None @pytest.mark.django_db def test_page_revision(client: Client): + """Test that accessing a previous revision of the club page works.""" club = baker.make(Club) revisions = baker.make( PageRev, page=club.page, _quantity=3, content=iter(["foo", "bar", "baz"]) diff --git a/club/views.py b/club/views.py index 6f2c7716..77e59721 100644 --- a/club/views.py +++ b/club/views.py @@ -106,42 +106,35 @@ class ClubTabsMixin(TabedViewMixin): return self.object.get_display_name() def get_list_of_tabs(self): + if not self.request.user.has_perm("club.view_club"): + # The user will still be able to see the club main page, + # but nothing else. + # It's useless to display a tab with only one item, so return nothing. + return [] tab_list = [ { "url": reverse("club:club_view", kwargs={"club_id": self.object.id}), "slug": "infos", "name": _("Infos"), - } + }, + { + "url": reverse("club:club_members", kwargs={"club_id": self.object.id}), + "slug": "members", + "name": _("Members"), + }, + { + "url": reverse( + "club:club_old_members", kwargs={"club_id": self.object.id} + ), + "slug": "elderlies", + "name": _("Old members"), + }, + { + "url": reverse("club:club_hist", kwargs={"club_id": self.object.id}), + "slug": "history", + "name": _("History"), + }, ] - if self.request.user.has_perm("club.view_club"): - tab_list.extend( - [ - { - "url": reverse( - "club:club_members", kwargs={"club_id": self.object.id} - ), - "slug": "members", - "name": _("Members"), - }, - { - "url": reverse( - "club:club_old_members", kwargs={"club_id": self.object.id} - ), - "slug": "elderlies", - "name": _("Old members"), - }, - ] - ) - if self.object.page: - tab_list.append( - { - "url": reverse( - "club:club_hist", kwargs={"club_id": self.object.id} - ), - "slug": "history", - "name": _("History"), - } - ) if self.request.user.can_edit(self.object): tab_list.extend( [ @@ -159,21 +152,6 @@ class ClubTabsMixin(TabedViewMixin): "slug": "edit", "name": _("Edit"), }, - ] - ) - if self.object.page and self.request.user.can_edit(self.object.page): - tab_list.append( - { - "url": reverse( - "core:page_edit", - kwargs={"page_name": self.object.page.get_full_name()}, - ), - "slug": "page_edit", - "name": _("Edit club page"), - } - ) - tab_list.extend( - [ { "url": reverse( "club:club_sellings", kwargs={"club_id": self.object.id} diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index d3c30c7e..978c8cba 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -517,6 +517,22 @@ msgstr "Url dupliquée" msgid "This link doesn't match with the url base of its type." msgstr "Ce lien ne correspond pas à l'url de base de son type." +#: club/templates/club/club_detail.jinja club/views.py +#: com/templates/com/news_admin_list.jinja com/templates/com/poster_list.jinja +#: com/templates/com/screen_list.jinja com/templates/com/weekmail.jinja +#: core/templates/core/file.jinja core/templates/core/group_list.jinja +#: core/templates/core/page/base.jinja core/templates/core/user_tools.jinja +#: core/views/user.py counter/templates/counter/cash_summary_list.jinja +#: counter/templates/counter/counter_list.jinja +#: election/templates/election/election_detail.jinja +#: forum/templates/forum/macros.jinja +#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja +#: pedagogy/templates/pedagogy/guide.jinja sas/templates/sas/album.jinja +#: trombi/templates/trombi/detail.jinja +#: trombi/templates/trombi/edit_profile.jinja +msgid "Edit" +msgstr "Éditer" + #: club/templates/club/club_detail.jinja com/templates/com/news_list.jinja msgid "Links" msgstr "Liens" @@ -1019,26 +1035,6 @@ msgstr "Historique" msgid "Tools" msgstr "Outils" -#: club/views.py com/templates/com/news_admin_list.jinja -#: com/templates/com/poster_list.jinja com/templates/com/screen_list.jinja -#: com/templates/com/weekmail.jinja core/templates/core/file.jinja -#: core/templates/core/group_list.jinja core/templates/core/page/base.jinja -#: core/templates/core/user_tools.jinja core/views/user.py -#: counter/templates/counter/cash_summary_list.jinja -#: counter/templates/counter/counter_list.jinja -#: election/templates/election/election_detail.jinja -#: forum/templates/forum/macros.jinja -#: pedagogy/templates/pedagogy/fragments/ue_detail/comments.jinja -#: pedagogy/templates/pedagogy/guide.jinja sas/templates/sas/album.jinja -#: trombi/templates/trombi/detail.jinja -#: trombi/templates/trombi/edit_profile.jinja -msgid "Edit" -msgstr "Éditer" - -#: club/views.py -msgid "Edit club page" -msgstr "Éditer la page de club" - #: club/views.py msgid "Sellings" msgstr "Vente"