29. Workflow, roles and permissions#
In this part you will:
Allow self-registration
Constrain which content types can be added to the schedule folder
Grant local roles
Create a custom workflow for talks
Tools and techniques covered:
folder constraints
local roles
workflow
Check out mastering-plone-project at tag block:
git checkout block
The code at the end of the chapter:
git checkout user_generated_content
More info in The code for the training
How do prospective speakers submit talks? We let them register on the site and grant the right to create talks. For this we go back to changing the site through the web.
29.1. Self-registration#
Go to the Security control panel at http://localhost:3000/controlpanel/security and enable self-registration.
Leave Enable User Folders off unless you want a community site, in which users can create any content they want in their home folder.
Select the option Use email address as login name.
29.2. Constrain types to be addable#
On the schedule page, select Restrictions… http://localhost:8080/Plone/schedule/folder_constraintypes_form from the Add new menu. Restrict to only allow adding talks.
Note
This action is only available in Plone's Classic UI frontend, and not its Volto frontend.
29.3. Grant local roles#
On the schedule page, go to Sharing. Check the box for Can add for the group Logged-in users, and save. Now every logged-in user can add content in this folder (and only this folder).
The Can add column grants the Contributor role to this group within this folder.
By combining the type constraints and the local roles on this folder, we have made it so that non-admin users can create and submit talks inside the schedule.
29.4. A custom workflow for talks#
We still need to fix a problem: Authenticated users can see all talks, including those of other users, even if those talks are in the private state. Since we do not want this, we will create a modified workflow for talks. The new workflow will only let them see and edit talks they created themselves and not the ones of other users.
Go to the : http://localhost:8080/Plone/portal_workflow/manage
See how talks have the same workflow as most content, namely (Default)
Go to the tab Contents, check the box next to simple_publication_workflow, click copy and paste.
Rename the new workflow from
copy_of_simple_publication_workflowtotalks_workflow.Edit the workflow by clicking on it: Change the Title to
Talks Workflow.Click on the tab States and click on private to edit this state. In the next view select the tab Permissions.
Find the table column for the role Contributor and remove the permissions for Access contents information and View. Note that the Owner role (that's the creator) still has some permissions.
Do the same for the state pending
Go back to portal_workflow and set the new workflow
talks_workflowfor talks. ClickChangeand thenUpdate security settings.
The new workflow allows contributors to see and edit talks they created themselves, but not talks submitted by other contributors until they are published.
29.5. Move the changes to the file system#
We don't want to do these steps for every new conference by hand so we move the changes into our Generic Setup profile.
Export the workflow#
Export the Generic Setup step Workflow Tool in http://localhost:8080/Plone/portal_setup/manage_exportSteps.
Copy the file
workflows.xmlintobackend/src/ploneconf/site/profiles/defaultand clean out everything that is not related to talks.
<object meta_type="Plone Workflow Tool" name="portal_workflow"
- Copy {file}`workflows/talks_workflow/definition.xml` into {file}`backend/src/ploneconf/site/profiles/default/workflows/talks_workflow/definition.xml`.
(The other files are just definitions of the default workflows, and we only want things in our package that changes Plone.)
### Enable self-registration
To enable self-registration you need to change the global setting that controls this option.
Most global setting are stored in the registry. You can modify it by adding the following to {file}`src/ploneconf/site/profiles/default/registry/main.xml`:
```{code-block} xml
<record name="plone.enable_self_reg">
<value>True</value>
</record>
Grant local roles and constrain types to be addable#
Since the granting of local roles applies only to a certain folder in the site, we could easily do it by hand instead of writing code for it. But for testability and repeatability (there is a conference every year!), we should create the initial content structure automatically and also apply needed local roles.
Let's add an upgrade step to do this as well as importing the workflow and new registry setting.
Update the profile version in backend/src/ploneconf/site/profiles/default/metadata.xml:
1<?xml version="1.0" encoding="utf-8"?>
2<metadata>
3 <version>1004</version>
4 <dependencies>
5 <dependency>profile-plone.volto:default</dependency>
6 <dependency>profile-plone.app.caching:default</dependency>
7 <dependency>profile-plone.app.caching:with-caching-proxy</dependency>
8 </dependencies>
9</metadata>
Register the new upgrade step in backend/src/ploneconf/site/upgrades/configure.zcml:
<genericsetup:upgradeSteps
profile="ploneconf.site:default"
source="1003"
destination="1004"
>
<genericsetup:upgradeDepends
title="Add talks workflow"
description="Run workflow and plone.app.registry import steps"
import_steps="plone.app.registry workflow"
/>
<genericsetup:upgradeStep
title="Configure talk permissions"
description="Configure local roles and type constraints for talk schedule"
handler="ploneconf.site.upgrades.v1004.configure_talk_permissions"
/>
</genericsetup:upgradeSteps>
Create the file backend/src/ploneconf/site/upgrades/v1004.py:
1from plone import api
2from Products.CMFPlone.interfaces import constrains
3import logging
4
5logger = logging.getLogger(__name__)
6
7
8def configure_talk_permissions(context):
9 talks_folder = api.content.get("/schedule")
10
11 # Allow logged-in users to create content
12 api.group.grant_roles(
13 groupname='AuthenticatedUsers',
14 roles=['Contributor'],
15 obj=talks_folder)
16
17 # Constrain addable types to talk
18 behavior = constrains.ISelectableConstrainTypes(talks_folder)
19 behavior.setConstrainTypesMode(constrains.ENABLED)
20 behavior.setLocallyAllowedTypes(['talk'])
21 behavior.setImmediatelyAddableTypes(['talk'])
22 logger.info(f'Added and configured {talks_folder.absolute_url()}')
Once we apply the upgrade step, the schedule page is updated with the appropriate local roles and constraints.
29.6. Exercise#
In Upgrade steps we wrote an upgrade step to create the basic page structure of the site. But we want that to be created not only during an upgrade, but also when a new site is created by hand or in tests.
One way to do this is to create a list of dictionaries containing the type, parent and title plus optionally workflow state etc. to create an initial structure.
In some projects it could also make sense to have additional profiles besides default:
a
demoorcontentprofile that creates the initial structurea
testingprofile that creates dummy content (talks, speakers etc) for tests
Create an optional Generic Setup profile content that creates the content, grants local roles and sets constraints.