Repository: digitalfabrik/integreat-cms

Issue:
Add page owner
A page should optionally have a page owner, which is used to determine a logo beneath the content.
We could either solve this
 - via a user, which is linked to an organization
 - or directly via an organization

Which solution do you prefer? I think directly choosing an organization is a good idea. This way, we could make sure all members of an organization can change this page without adding multiple page editors/publishers.


Discussion:
I vote for org as well.

Resolving patch:
diff --git a/src/cms/forms/pages/page_form.py b/src/cms/forms/pages/page_form.py
--- a/src/cms/forms/pages/page_form.py
+++ b/src/cms/forms/pages/page_form.py
@@ -212,7 +212,7 @@ class Meta:
         #: The model of this :class:`django.forms.ModelForm`
         model = Page
         #: The fields of the model which should be handled by this form
-        fields = ["icon", "mirrored_page", "mirrored_page_first"]
+        fields = ["icon", "mirrored_page", "mirrored_page_first", "organization"]
         #: The classes for the fields if they differ from the standard field class
         field_classes = {"mirrored_page": MirrorPageField}
         #: The widgets for the fields if they differ from the standard widgets
diff --git a/src/cms/models/pages/page.py b/src/cms/models/pages/page.py
--- a/src/cms/models/pages/page.py
+++ b/src/cms/models/pages/page.py
@@ -8,6 +8,7 @@
 
 from .abstract_base_page import AbstractBasePage
 from ..regions.region import Region
+from ..users.organization import Organization
 from ...utils.translation_utils import ugettext_many_lazy as __
 
 logger = logging.getLogger(__name__)
@@ -82,6 +83,17 @@ class Page(MPTTModel, AbstractBasePage):
             ),
         ),
     )
+    organization = models.ForeignKey(
+        Organization,
+        null=True,
+        blank=True,
+        on_delete=models.SET_NULL,
+        related_name="pages",
+        verbose_name=_("responsible organization"),
+        help_text=_(
+            "This allows all members of the organization to edit and publish this page."
+        ),
+    )
 
     @property
     def explicitly_archived_ancestors(self):
@@ -164,7 +176,6 @@ class Meta:
         default_permissions = ()
         #: The custom permissions for this model
         permissions = (
-            ("view_pages", "Can view pages"),
             ("edit_pages", "Can edit pages"),
             ("publish_pages", "Can publish pages"),
             ("grant_page_permissions", "Can grant page permissions"),
diff --git a/src/cms/rules.py b/src/cms/rules.py
--- a/src/cms/rules.py
+++ b/src/cms/rules.py
@@ -101,6 +101,43 @@ def can_publish_all_pages(user, page):
     return user.has_perm("cms.publish_pages")
 
 
+@predicate
+def can_edit_or_publish_some_pages(user):
+    """
+    This predicate checks whether the given user can edit or publish at least some specific pages.
+
+    :param user: The user who's permission should be checked
+    :type user: ~django.contrib.auth.models.User
+
+    :return: Whether or not ``user`` can edit or publish some pages
+    :rtype: bool
+    """
+    if user.editable_pages.exists() or user.publishable_pages.exists():
+        return True
+    if user.profile.organization and user.profile.organization.pages.exists():
+        return True
+    return False
+
+
+@predicate
+def is_in_responsible_organization(user, page):
+    """
+    This predicate checks whether the given user is a member of the page's responsible organization.
+
+    :param user: The user who's permission should be checked
+    :type user: ~django.contrib.auth.models.User
+
+    :param page: The requested page
+    :type page: ~cms.models.pages.page.Page
+
+    :return: Whether or not ``user`` is a member of ``page.organization``
+    :rtype: bool
+    """
+    if not page or not page.organization:
+        return False
+    return user.profile in page.organization.members.all()
+
+
 @predicate
 def can_delete_chat_message(user, chat_message):
     """
@@ -124,9 +161,20 @@ def can_delete_chat_message(user, chat_message):
 
 # Permissions
 
+add_perm(
+    "cms.view_pages",
+    can_edit_or_publish_some_pages | can_edit_all_pages | can_publish_all_pages,
+)
 add_perm(
     "cms.edit_page",
-    can_edit_all_pages | is_page_editor | can_publish_all_pages | is_page_publisher,
+    can_edit_all_pages
+    | is_page_editor
+    | can_publish_all_pages
+    | is_page_publisher
+    | is_in_responsible_organization,
+)
+add_perm(
+    "cms.publish_page",
+    can_publish_all_pages | is_page_publisher | is_in_responsible_organization,
 )
-add_perm("cms.publish_page", can_publish_all_pages | is_page_publisher)
 add_perm("cms.delete_chat_message", can_delete_chat_message)


Test patch: