26. User generated content¶
How do prospective speakers submit talks? We let them register on the site and grant right to create talks. For this we go back to changing the site through-the-web.
In this chapter we:
- allow self-registration
- constrain types on the talk-folder
- grant local roles
- create a custom workflow for talks
- Go to the Security-controlpanel at http://localhost:8080/Plone/@@security-controlpanel and Enable self-registration
- Leave “Enable User Folders” off unless you want a community-site.
- On the talk-folder select Restrictions… from the Add new menu. Only allow to add talks.
Grant local roles¶
- Go to Sharing and grant the role Can add to the group logged-in users. Now every user can add content in this folder (and only this folder).
Now all logged-in users can create and submit talks in this folder with the permission of the default-workflow.
A custom workflow for talks¶
We still need to fix a problem: Authenticated users can see all talks, even the ones of other users in the private state. Since we don’t 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 ZMI > portal_workflow
- See how talks have the same workflow as most content
- Go to the tab Contents, check the box next to
- Rename the new workflow from copy_of_simple_publication_workflow to talks_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 talbe-column for the role Contributor and remove the permissions for
Access contents informationand
View. Note that the Owner (i.e. 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. Click Change and then Update security settings.
The addon plone.app.workflowmanager provides a much nicer user-interface for this. The problem is you need a big screen for it and it can be pretty confusing as well.
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 package.
- export the GenericSetup step Workflow Tool in http://localhost:8080/Plone/portal_setup/manage_exportSteps.
- drop the file
profiles/default/workflows/talks_workflow/definition.xml. The others are just definitions of the default-workflows and we only want things in our package that changes Plone.
This has to happen in python in a custom setuphandler.py since there is not yet a exportable setting for this.
Register a import-step in
configure.zcml. It will be automatically run when (re-)installing the addon.
1 2 3 4 5 6 7
<genericsetup:importStep name="ploneconf.site" title="ploneconf.site special import handlers" description="" handler="ploneconf.site.setuphandlers.setupVarious"> <depends name="typeinfo"/> </genericsetup:importStep>
Note that the setuphandler has a dependency on typeinfo because it will only allow the creation of talks. For this the type already has to exist.
Create a new file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
# -*- coding: UTF-8 -*- from plone.app.controlpanel.security import ISecuritySchema from plone import api import logging PROFILE_ID = 'profile-ploneconf.site:default' logger = logging.getLogger('ploneconf.site') def setupVarious(context): # Ordinarily, GenericSetup handlers check for the existence of XML files. # Here, we are not parsing an XML file, but we use this text file as a # flag to check that we actually meant for this import step to be run. # The file is found in profiles/default. if context.readDataFile('ploneconf.site_various.txt') is None: return site = api.portal.get() set_up_security(site) def set_up_security(site): secSchema = ISecuritySchema(site) secSchema.set_enable_self_reg(True)
Add the marker-file
profile/default/ploneconf.site_various.txt used in line 18:
The ploneconf.site_various step is run if this file is present in the profile
Grant local roles¶
Since this applies only to a certain folder in the site we would normally not write code for it.
But we can easily add a method to the setuphandler that creates the folder and sets up some setting for it.
Here is an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
# -*- coding: UTF-8 -*- from plone.app.controlpanel.security import ISecuritySchema from plone import api from Products.CMFPlone.interfaces.constrains import ISelectableConstrainTypes from plone.app.dexterity.behaviors import constrains import logging PROFILE_ID = 'profile-ploneconf.site:default' logger = logging.getLogger('ploneconf.site') def setupVarious(context): # Ordinarily, GenericSetup handlers check for the existence of XML files. # Here, we are not parsing an XML file, but we use this text file as a # flag to check that we actually meant for this import step to be run. # The file is found in profiles/default. if context.readDataFile('ploneconf.site_various.txt') is None: return site = api.portal.get() set_up_security(site) set_up_content(site) def set_up_security(site): secSchema = ISecuritySchema(site) secSchema.set_enable_self_reg(True) def set_up_content(site): """Create and configure some initial content""" if 'talks' in site: return talks = api.content.create( container=site, type='Folder', id='talks', title='Talks') api.content.transition(talks, 'publish') api.group.grant_roles( groupname='AuthenticatedUsers', roles=['Contributor'], obj=talks) # Enable constraining behavior = ISelectableConstrainTypes(talks) behavior.setConstrainTypesMode(constrains.ENABLED) behavior.setLocallyAllowedTypes(['talk']) behavior.setImmediatelyAddableTypes(['talk']) logger.info("Created and configured %s" % talks.absolute_url())