pythonwagtailwagtail-admin

Wagtail CMS - Programmatically enabling user access to manage Pages within the Admin panel


Context

Wagtail CMS has a permission system that builds on that of Django's. However, customizing it for users that are neither an admin nor using the pre-made groups Moderator or Editor is unclear. Presently, I have:

            Program
               |
             Course
           /    |    \
     Report   Labs   Events

I'd like to add a group, Student, which can add/submit pages of type Report. Like stated in the title, I require a programmatic solution. Having an admin go through and personally assign permissions is not acceptable.


Problem

Wagtail provides only one programmatic code example, which is for adding a custom permission here in their documentation:

from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from wagtail.admin.models import Admin


content_type = ContentType.objects.get_for_model(Admin)
permission = Permission.objects.create(
    content_type=content_type,
    codename="can_do_something",
    name="Can do something",
)

Technically, I don't need a custom permission. I need to grant a Group a custom set of existing permissions. To accomplish this, I've attempted the following:

from django.contrib.auth.models import Permission, Group
from example.website.models import StudentUser
group, created = Group.objects.get_or_create(name="Student")
add_report = Permission.objects.get(codename="add_reportpage")
change_report = Permission.objects.get(codename="change_reportpage")
group.permissions.add(add_report, change_report)
user = StudentUser.objects.get(email="john.doe@abc.com")
user.groups.add(group)

Unfortunately, this hasn't worked. When I log into the backend with a user of type StudentUser (the account to which I provided the permission), there's nothing but the Documents tab (that is default) in the navigation menu. Nowhere can I see a place to modify Report.

If I try to copy the exact Report URL path used in the admin login, it doesn't allow access when logged in the StudentUser despite the added permissions.


Further debugging

To figure out if there are some other types of permissions I'm missing, I listed the permissions for all groups. Then, I copied them for my new group. You can see the list of permissions now below that I copied from the built-in Moderators group:

Moderators
<Permission: Wagtail admin | admin | Can access Wagtail admin>,
<Permission: Wagtail documents | document | Can add document>,
<Permission: Wagtail documents | document | Can change document>,
<Permission: Wagtail documents | document | Can choose document>,
<Permission: Wagtail documents | document | Can delete document>,
<Permission: Wagtail images | image | Can add image>,
<Permission: Wagtail images | image | Can change image>,
<Permission: Wagtail images | image | Can choose image>,
<Permission: Wagtail images | image | Can delete image>

Student
<Permission: Wagtail admin | admin | Can access Wagtail admin>,
<Permission: Website | report index | Can view report index>,
<Permission: Website | report | Can add report>,
<Permission: Website | report | Can change report>,
<Permission: Website | report | Can delete report>,
<Permission: Website | report | Can view report>

As you can see, it would appear only admin access seems like the prerequisite for seeing content in the Admin interface. Despite this, logging in as Student still shows no changes in the Wagtail admin panel. And attempts to access any report in the admin interface (as you would as admin) continue to get a permission denied return code.

What step am I missing here to ensure custom groups can access content in the admin interface?


Solution

  • Page permissions in Wagtail are determined by position within the page hierarchy rather than by page type. So, while it's not possible to directly give students edit permission over the Report page model - if all your Report pages exist under a single ReportIndex (something that can be enforced through the use of parent_page_types / subpage_types rules), you can give them add/change permission over that ReportIndex page, which will thus allow them to create Report pages there.

    Page permissions are defined through the wagtail.models.GroupPagePermission model, which is distinct from Django's built-in group/permission relation. To set such a permission rule up, you can do the following:

    from wagtail.models import GroupPagePermission
    from django.contrib.auth.models import Permission, Group
    from myapp.models import ReportIndex
    
    students, created = Group.objects.get_or_create(name="Student")
    add_page = Permission.objects.get(codename="add_reportpage")
    report_index_page = ReportIndex.objects.first()
    
    GroupPagePermission.objects.create(
        group=students,
        page=report_index_page,
        permission=add_page,
    )