Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: collective/collective.developermanual
...
head fork: collective/collective.developermanual
  • 5 commits
  • 18 files changed
  • 0 commit comments
  • 1 contributor
Commits on Jul 20, 2012
@jean jean Add .rst extension (enable 'gf' nav in vim). 8a4092f
@jean jean Improve markup. fb7d587
Commits on Jul 31, 2012
@jean jean Merge branch 'master' of github.com:collective/collective.developerma…
…nual
7610506
@jean jean Typos, formulation. e0cd21a
@jean jean Tidying up.
Break very long lines, fix indentation, heading levels, and improve markup.
ce0284b
Showing with 464 additions and 311 deletions.
  1. +11 −14 source/i18n/language.rst
  2. +5 −5 source/members/index.rst
  3. +112 −97 source/members/member_profile.rst
  4. +19 −8 source/members/pluggable_authentication_service/authorisation-algorithm.rst
  5. +17 −6 source/members/pluggable_authentication_service/concepts.rst
  6. +17 −6 source/members/pluggable_authentication_service/configuring-an-individual-pas-plugin.rst
  7. +41 −13 source/members/pluggable_authentication_service/configuring-pas.rst
  8. +23 −8 source/members/pluggable_authentication_service/features-and-interfaces.rst
  9. +32 −27 source/members/pluggable_authentication_service/group-plugins.rst
  10. +3 −2 source/members/pluggable_authentication_service/index.rst
  11. +15 −6 source/members/pluggable_authentication_service/introduction.rst
  12. +22 −14 source/members/pluggable_authentication_service/properties-plugins.rst
  13. +23 −20 source/members/pluggable_authentication_service/roles-plugin.rst
  14. +18 −6 source/members/pluggable_authentication_service/the-important-interfaces.rst
  15. +21 −13 source/members/pluggable_authentication_service/the-user-object.rst
  16. +6 −6 source/members/pluggable_authentication_service/user-creation.rst
  17. +19 −11 source/members/pluggable_authentication_service/user-factory-plugin.rst
  18. +60 −49 source/serving/webdav.rst
View
25 source/i18n/language.rst
@@ -11,14 +11,14 @@ Language functions
Introduction
============
-Each page view a has a language associated with it.
+Each page view has a language associated with it.
The active language is negotiated by the ``plone.i18n.negotiator`` module.
-Several factors may involve determining what the language should be:
+Several factors may be involved in determining what the language should be:
* Cookies (setting from the language selector)
-* Top-level domain name (like ``.fi`` for Finnish, ``.se`` for Swedish)
+* The top-level domain name (e.g. ``.fi`` for Finnish, ``.se`` for Swedish)
* Context (current content) language
@@ -62,7 +62,6 @@ the served language on the content.
Example BrowserView method::
-
from Acquisition import aq_inner
def language(self):
@@ -71,7 +70,6 @@ Example BrowserView method::
Useful in producing <html> tag.
You need to output language for every HTML page, see http://www.w3.org/TR/xhtml1/#strict
-
@return: The two letter language code of the current content.
"""
portal_state = self.context.unrestrictedTraverse("@@plone_portal_state")
@@ -123,8 +121,8 @@ Example below::
if lang != preferred:
result[lang] = data
- # For the convenience, export language ISO code also inside data,
- # so it easier to iterate data in the templates
+ # For convenience, include the language ISO code in the export,
+ # so it is easier to iterate data in the templates
for lang, data in result.items():
data["id"] = lang
@@ -399,14 +397,14 @@ Below some example code.
replacement=".languages.working_portal_state_language"
/>
-Login aware language negotiation
+Login-aware language negotiation
==========================================
-Because language negotiation happens before the authentication by default
-and if you wish to use authenticated credentials in the negotiation you
-can do the following.
+By default, language negotiation happens before authentication.
+Therefore, if you wish to use authenticated credentials in the negotiation,
+you can do the following.
-This can be done by hooking to after traversal event.
+Hook the after-traversal event.
Example event registration
@@ -420,9 +418,8 @@ Example event registration
<subscriber handler=".language_negotiation.Negotiator"/>
</configure>
-Related event handler::
+Corresponding event handler::
-
from zope.interface import Interface
from zope.component import adapter
from ZPublisher.interfaces import IPubEvent,IPubAfterTraversal
View
10 source/members/index.rst
@@ -5,9 +5,9 @@ Users and members
.. toctree::
:maxdepth: 2
- member_basics
- member_profile
- pluggable_authentication_service/index
- membrane
- sharing_tab
+ member_basics.rst
+ member_profile.rst
+ pluggable_authentication_service/index.rst
+ membrane.rst
+ sharing_tab.rst
View
209 source/members/member_profile.rst
@@ -2,43 +2,48 @@
Member profiles
=================
-.. contents :: :local:
+.. contents:: :local:
.. admonition:: Description
- How to manage Plone member propeties programmatically
+ How to manage Plone member properties programmatically
Introduction
--------------
+=============
-Member profile fields are the fields which the logged in member
-can edit oneself on his user account page.
+Member profile fields are the fields which the logged-in member
+can edit themself on their user account page.
-For more info, see
+For more info, see:
-* MemberDataTool: http://svn.zope.org/Products.CMFCore/trunk/Products/CMFCore/MemberDataTool.py?rev=110418&view=auto
+``MemberDataTool``
+ http://svn.zope.org/Products.CMFCore/trunk/Products/CMFCore/MemberDataTool.py?rev=110418&view=auto
-* MemberData class: http://svn.zope.org/Products.CMFCore/trunk/Products/CMFCore/MemberDataTool.py?rev=110418&view=auto
+``MemberData`` class
+ http://svn.zope.org/Products.CMFCore/trunk/Products/CMFCore/MemberDataTool.py?rev=110418&view=auto
-PlonePAS subclasses and extends MemberData and MemberDataTool
+PlonePAS subclasses and extends MemberData and MemberDataTool.
* `See PlonePAS MemberDataTool <http://dev.plone.org/collective/browser/Products.PlonePAS/trunk/Products/PlonePAS/tools/memberdata.py?rev=122125#L27>`_.
* `See PlonePAS MemberData class <http://dev.plone.org/collective/browser/Products.PlonePAS/trunk/Products/PlonePAS/tools/memberdata.py?rev=122125#L220>`_.
Getting member profile properties
----------------------------------
+=================================
.. note::
- Following concerns vanilla Plone only. If you have customized membership behavior
- it doesn't necessarily work.
+ The following applies to vanilla Plone.
+ If you have customized membership behavior it won't necessarily work.
-Member profile properties (title, address, biography, etc.) are stored in portal_membership tool.
+Member profile properties (title, address, biography, etc.)
+are stored in ``portal_membership`` tool.
-Available fields can be found in ZMI -> portal_membership -> Properties tab.
+Available fields can be found in the
+:term:`ZMI` -> ``portal_membership`` -> :guilabel:`Properties` tab.
-The script below is a simple example of how to list all member email addresses::
+The script below is a simple example showing how to list all member
+email addresses::
from Products.CMFCore.utils import getToolByName
memberinfo = []
@@ -49,27 +54,27 @@ The script below is a simple example of how to list all member email addresses::
Accessing member data
-=====================
+---------------------
.. TODO::
Get member data by username
Furher reading
-==============
+--------------
* `ToolbarViewlet has some sample code <https://github.com/plone/plone.app.layout/tree/master/plone/app/layout/viewlets/common.py>`_
how to retrieve these properties.
Getting member fullname
-=======================
+-----------------------
-In Python code you can ask info from MemberData object::
+In Python code you can access properties on the ``MemberData`` object::
- fullname = member_data.getProperty("fullname")
+ fullname = member_data.getProperty("fullname")
-In template you can do something along the lines::
+In a template you can do something along the same lines::
<tal:with-fullname define="membership context/portal_membership;info python:membership.getMemberInfo(user.getId()); fullname info/fullname">
You are are <span class="name" tal:content="fullname" />
@@ -78,19 +83,19 @@ In template you can do something along the lines::
Note that this code won't work for anonymous users.
Setting member profile properties
----------------------------------
+=================================
-Use *setMemberProperties(mapping={})* to batch update properties.
+Use ``setMemberProperties(mapping={...})`` to batch update properties.
Old properties are not removed.
Example::
- member = portal_membership.getMemberById(user_id)
- member.setMemberProperties(mapping={"email":"aaa@aaa.com"})
-
-New properties must be explicitly declared in portal_memberdata,
+ member = portal_membership.getMemberById(user_id)
+ member.setMemberProperties(mapping={"email":"aaa@aaa.com"})
+
+New properties must be explicitly declared in ``portal_memberdata``,
before creation of the member,
-or setMemberProperties() will silently fail.
+or ``setMemberProperties()`` will silently fail.
.. TODO::
@@ -98,36 +103,36 @@ or setMemberProperties() will silently fail.
Example::
- def prepareMemberProperties(site):
- """ Adjust site for custom member properties """
-
- # Need to use ancient Z2 property sheet API here...
- portal_memberdata = getToolByName(site, "portal_memberdata")
+ def prepareMemberProperties(site):
+ """ Adjust site for custom member properties """
+
+ # Need to use ancient Z2 property sheet API here...
+ portal_memberdata = getToolByName(site, "portal_memberdata")
+
+ # When new member is created, it's MemberData
+ # is populated with the values from portal_memberdata property sheet,
+ # so value="" will be the default value for users' home_folder_uid
+ # member property
+ if not portal_memberdata.hasProperty("home_folder_uid"):
+ portal_memberdata.manage_addProperty(id="home_folder_uid", value="", type="string")
+
+ ....
+
+ def createMatchingHomeFolder(member):
+ """ """
+
+ email = member.getProperty("email")
+ home_folder.setEmail(email)
+
+ # Store UID of the created folder in memberdata so we can
+ # look it up later to e.g. generate the link to the member folder
+ member.setMemberProperties(mapping={"home_folder_uid": home_folder.UID()})
+
+
+ return home_folder
- # When new member is created, it's MemberData
- # is populated with the values from portal_memberdata property sheet,
- # so value="" will be the default value for users' home_folder_uid
- # member property
- if not portal_memberdata.hasProperty("home_folder_uid"):
- portal_memberdata.manage_addProperty(id="home_folder_uid", value="", type="string")
-
- ....
-
- def createMatchingHomeFolder(member):
- """ """
-
- email = member.getProperty("email")
- home_folder.setEmail(email)
-
- # Store UID of the created folder in memberdata so we can
- # look it up later to e.g. generate the link to the member folder
- member.setMemberProperties(mapping={"home_folder_uid": home_folder.UID()})
-
-
- return home_folder
-
Setting password
-=====================
+---------------------
Password is a special case.
@@ -139,69 +144,80 @@ Example how to set the user password::
Increase minimum password size
-==============================
+------------------------------
-To increase the minimum password size copy "validate_pwreset_password" to your custom folder and insert the following lines::
+To increase the minimum password size, copy ``validate_pwreset_password``
+to your custom folder and insert the following lines::
- if len(password) < 8:
- state.setError('password', 'ERROR')
+ if len(password) < 8:
+ state.setError('password', 'ERROR')
-This will increase the minimum password size for the password reset form to 8 characters. (This does not effect new user regsitration, that limit will still be 5)
+This will increase the minimum password size for the password reset form
+to 8 characters. (This does not effect new user registration, that limit
+will still be 5.)
Don't forget to update your form templates to reflect your changes!
Default password length - password reset form
-=============================================
+---------------------------------------------
-The password reset form's minimum password length is 5 characters, to increase this:
+The password reset form's minimum password length is 5 characters.
+To increase this:
-Copy validate_pwreset_password into your custom folder and add the following lines:
+Copy ``validate_pwreset_password`` into your custom folder
+and add the following lines::
- if len(password) <8:
- state.setError('password','ERROR')
+ if len(password) < 8:
+ state.setError('password','ERROR')
-Before the "if state.getErrors():" method.
+before the ``if state.getErrors():`` method.
-This would increase the minimum password size to 8 characters. Remember to update your form templates accordingly.
+This would increase the minimum password size to 8 characters.
+Remember to update your form templates accordingly.
Setting visual editor for all users
-=======================================
+---------------------------------------
-Visual editor property is set on the member on the member creation.
+The *visual editor* property is set on the member upon creation.
-If you want to all site members to use TinyMCE instead of Kupu.
-Plone provides no means to do change other member properties through-the-web,
-but you can do it using the command-line scripting snippet below
+If you want to change all site members to use TinyMCE instead of Kupu.
+you have to do it using the command-line ---
+Plone provides no through-the-web way to change
+the properties of other members.
+Here is a script which does the job:
-migrate.py::
+``migrate.py``::
import transaction
# Traverse to your Plone site from Zope application root
- context = app.yoursiteid.sitsngta # site id is mfabrik
-
- users = context.acl_users.getUserNames()
-
+ context = app.yoursiteid.sitsngta # site id is yoursiteid
+
+ usernames = context.acl_users.getUserNames()
portal_membership = context.portal_membership
-
+ txn = transaction.get()
+
i = 0
- for user in users:
- member = portal_membership.getMemberById(user)
- value = member.wysiwyg_editor
-
- # Show the existing editor choice before upgrading
- print str(user) + ": " + str(value)
-
- # Set WYSIWYG editor for the member
- member.wysiwyg_editor = "TinyMCE"
-
- # Make sure transaction buffer does not grow too large
- i += 1
- if i % 25 == 0:
- transaction.commit()
+ for userid in usernames:
+ member = portal_membership.getMemberById(userid)
+ value = member.wysiwyg_editor
+
+ # Show the existing editor choice before upgrading
+ print str(userid) + ": " + str(value)
+
+ # Set WYSIWYG editor for the member
+ member.wysiwyg_editor = "TinyMCE"
+
+ # Make sure transaction buffer does not grow too large
+ i += 1
+ if i % 25 == 0:
+ txn.savepoint(optimistic=True)
+
+ # Once done, commit all the changes
+ txn.commit()
Run it::
@@ -209,7 +225,6 @@ Run it::
.. note::
- The script does not work through ZMI as member properties
- do not have proper security declarations to set them as admin.
-
-
+ The script does not work through the :term:`ZMI`
+ as member properties do not have proper security declarations,
+ so no changes are permitted.
View
27 source/members/pluggable_authentication_service/authorisation-algorithm.rst
@@ -2,17 +2,28 @@
Authorisation algorithm
=======================
-.. contents :: :local:
+.. contents:: :local:
-These are the steps the PAS user folder follows in its validate method:
+These are the steps the PAS user folder follows in its ``validate`` method:
-#. extract all credentials. This looks for any possible form of authentication information in a request: HTTP cookies, HTTP form parameters, HTTP authentication headers, originating IP address, etc. A request can have multiple (or no) sets of credentials.
-#. for each set of credentials found
+#. extract all credentials.
+ This looks for any possible form of authentication information in a
+ request: HTTP cookies, HTTP form parameters, HTTP authentication
+ headers, originating IP address, etc.
+ A request can have multiple (or no) sets of credentials.
- #. try to authorise the credentials. This checks if the credentials correspond to a known user and are valid.
+#. for each set of credentials found:
+
+ #. try to authorise the credentials.
+ This checks if the credentials correspond to a known user and are
+ valid.
#. create a user instance
- #. try to authorise the request. If succesful use this user and stop further processing.
+ #. try to authorise the request.
+ If successful, use this user and stop further processing.
#. create an anonymous user
-#. try to authorise the request using the anonymous user. If successful use this, if not:
-#. issue a challenge
+
+#. try to authorise the request using the anonymous user.
+ If successful use this, if not:
+
+#. issue a challenge.
View
23 source/members/pluggable_authentication_service/concepts.rst
@@ -2,22 +2,33 @@
Concepts
========
-.. contents :: :local:
+.. contents:: :local:
.. admonition:: Description
- PAS has a few basic concepts that you must understand in order to develop PAS related code.
+ PAS has a few basic concepts that you must understand in order to
+ develop PAS related code.
There are a few basic concepts used in PAS:
**credentials**
- Credentials are a set of information which can be used to authenticate a user. This can be a login name and password, an IP address, a session cookie or something else.
+ Credentials are a set of information which can be used to authenticate
+ a user.
+ This can be a login name and password, an IP address, a session cookie
+ or something else.
**user name**
- The user name is the name used by the user to log into the system. To avoid confusion between user id and user name this tutorial will use the term login name instead.
+ The user name is the name used by the user to log into the system.
+ To avoid confusion between "user id" and "user name" this tutorial will
+ use the term login name instead.
**user id**
- All users must be uniquely identified by their user id. A users id can be different than the login name.
+ All users must be uniquely identified by their user id.
+ A user's id can be different than the login name.
**principal**
- A principal is an identifier for any entity within the authentication system. This can be either a user or a group. This implies that it is not legal to have a user and a group with the same id!
+ A principal is an identifier for any entity within the authentication
+ system.
+ This can be either a user or a group.
+ This implies that it is not legal to have a user and a group with the
+ same id!
View
23 source/members/pluggable_authentication_service/configuring-an-individual-pas-plugin.rst
@@ -2,23 +2,34 @@
Configuring an individual PAS plugin
====================================
-.. contents :: :local:
+.. contents:: :local:
.. admonition:: Description
- In addition to enabling and disabling plugins via the plugins object each plugin can also
- have its own configuration. You can access this by opening a plugin in the ZMI.
+ In addition to enabling and disabling plugins via the plugins object
+ each plugin can also have its own configuration.
+ You can access this by opening a plugin in the ZMI.
-Taking the *credentials_cookie_auth* as example again you will see the screen for the *Activate* tab. This tab is mandatory and allows you to enable and disable PAS interfaces for a plugin. This corresponds to the plugin configuration we saw earlier, but does not allow you to change the ordering of different plugins for an interface. If you enable a new interface for a particular plugin, it will be activated and placed last in the list of plugins for a particular interface.
+Taking the ``credentials_cookie_auth`` as example again you will see the
+screen for the :guilabel:`Activate` tab.
+This tab is mandatory and allows you to enable and disable PAS interfaces
+for a plugin.
+This corresponds to the plugin configuration we saw earlier, but does not
+allow you to change the ordering of different plugins for an interface.
+If you enable a new interface for a particular plugin, it will be
+activated and placed last in the list of plugins for a particular
+interface.
.. image:: cookie-plugin.jpg
:width: 400 px
:alt: cookie-plugin.jpg
-You can also go to the properties tab to edit settings specific for this plugin:
+You can also go to the :guilabel:`properties` tab to edit settings
+specific for this plugin:
.. image:: cookie-plugin-properties.jpg
:width: 400 px
:alt: cookie-plugin-properties.jpg
-What you can configure will differ per plugin. Some plugins do not have any configurations options, others can be very complex.
+What you can configure will differ per plugin. Some plugins do not have
+any configurations options, others can be very complex.
View
54 source/members/pluggable_authentication_service/configuring-pas.rst
@@ -2,35 +2,63 @@
Configuring PAS
===============
-.. contents :: :local:
+.. contents:: :local:
.. admonition:: Description
- There is no Plone interface to configure PAS: you will need to use the Zope Management
- Interface (ZMI). In the ZMI you will see a *acl_users* folder in the site root. This is
- your PAS.
+ There is no Plone interface to configure PAS:
+ you will need to use the Zope Management Interface (:term:`ZMI`).
+ In the ZMI you will see a ``acl_users`` folder in the site root.
+ This is your PAS object.
-If you open the *acl_users* folder you will see a number of different items. Each item is a PAS plugin, which implements some PAS functionality.
+If you open the ``acl_users`` folder you will see
+a number of different items.
+Each item is a PAS plugin, which implements some PAS functionality.
.. image:: pas-contents.jpg
:width: 400 px
:alt: The contents of a PAS user folder in the ZMI
-There is one special item: the *plugins* objects manages all administrative bookkeeping within PAS. It remembers which interfaces are active for each plugin and in what order the plugins should be called.
+There is one special item: the ``plugins`` object manages
+all administrative bookkeeping within PAS.
+It remembers which interfaces are active for each plugin
+and in what order the plugins should be called.
-Let's take a look to see how this works. If you open the *plugins* object you will see a list of all the PAS interfaces, along with a short description of what they do.
+Let's take a look to see how this works.
+If you open the ``plugins`` object
+you will see a list of all the PAS interfaces,
+along with a short description of what they do.
-We will take a look at the extraction plugins. These plugins take care of extracting the credentials such as your username and password from a request. These credentials can then be used to authenticate the user. If you click on the Extraction Plugins header you will see a screen which shows the plugins which implement this interface and allows you to configure which plugins will be used and in what order.
+We will take a look at the extraction plugins.
+These plugins take care of extracting the credentials
+such as your username and password from a request.
+These credentials can then be used to authenticate the user.
+If you click on the Extraction Plugins header you will see
+a screen which shows the plugins which implement this interface
+and allows you to configure which plugins will be used and in what order.
.. image:: extraction-interface-config.jpg
:width: 400 px
:alt: Configuration for the extraction plugins.
-In the default Plone configuration there are two plugins enabled for this interface:
+In the default Plone configuration there are two plugins enabled for this
+interface:
-* the *credentials_cookie_auth* plugin can extract the login name and password from an HTTP cookie and HTTP form values from the login form or portlet
-* the *credentials_basic_auth* plugin can extract the login name and password from standard HTTP authentication headers.
+* the ``credentials_cookie_auth`` plugin can extract the login name and
+ password from an HTTP cookie and HTTP form values from the login form or
+ portlet;
+* the ``credentials_basic_auth`` plugin can extract the login name and
+ password from standard HTTP authentication headers.
-In the default configuration the cookie plugin takes preference over the basic authentication plugin. This means that credentials from a HTTP cookie will be preferred over credentials form HTTP authentication headers if both are present You can try this by first logging in using standard HTTP authentication in the Zope root and then visiting your Plone site and logging in with a different user there: you will see that the new user is now the active user.
+In the default configuration the cookie plugin takes preference over the
+basic authentication plugin.
+This means that credentials from a HTTP cookie will be preferred over
+credentials from HTTP authentication headers if both are present.
+You can try this by first logging in using standard
+HTTP authentication in the Zope root, and then visiting your Plone site
+and logging in with a different user there: you will see that the new user
+is now the active user.
-You can change the order of the plugins by clicking on a plugin and moving it up or down with the arrows. Using the left and right arrows you can enable and disable a plugin for this interface.
+You can change the order of the plugins by clicking on a plugin and moving
+it up or down with the arrows. Using the left and right arrows you can
+enable and disable a plugin for this interface.
View
31 source/members/pluggable_authentication_service/features-and-interfaces.rst
@@ -2,19 +2,34 @@
Features and interfaces
=======================
-.. contents :: :local:
+.. contents:: :local:
.. admonition:: Description
- A user folder such as PAS provides a number of different services: it takes care of user
- authentication, it asks users to login if needed, it allows you to search for users and
- groups.
+ A user folder such as PAS provides a number of different services:
+ it takes care of user authentication,
+ it asks users to login if needed,
+ and it allows you to search for users and groups.
-In order to make both configuration and implementation simpler and more powerful all these different tasks have been divided into different interfaces. Each interface describes how a specific feature, such as authenticating a user, has to be implemented.
+In order to make both configuration and implementation simpler
+and more powerful, all these different tasks have been divided
+into different interfaces.
+Each interface describes how a specific feature,
+such as authenticating a user, has to be implemented.
-Within PAS plugins are used to provide those features. Plugins are small pieces of logic which implement one or more functions as defined by these interfaces.
+Within PAS, plugins are used to provide these features.
+Plugins are small pieces of logic which implement one or more functions
+as defined by these interfaces.
This separation is useful for different reasons:
-* it makes it possible to configure different aspects of the system separately. For example how users authenticate (cookies, login forms, etc.) can be configured separately from where user information is stored (ZODB, LDAP, RADIUS, SQL, etc.). This flexibility makes it very easy to tune the system to specific needs.
-* it makes it possible for developers to write small pieces of code that only perform a single task. This leads to code that is easier to understand, more testable and better maintainable.
+* it makes it possible to configure different aspects of the system
+ separately.
+ For example *how* users authenticate (cookies, login forms, etc.) can be
+ configured separately
+ from *where* user information is stored (ZODB, LDAP, RADIUS, SQL, etc.).
+ This flexibility makes it very easy to tune the system to specific needs.
+* it makes it possible for developers to write small pieces of code
+ that only perform a single task.
+ This leads to code that is easier to understand,
+ more testable and better maintainable.
View
59 source/members/pluggable_authentication_service/group-plugins.rst
@@ -2,36 +2,41 @@
Group plugins
=============
-.. contents :: :local:
+.. contents:: :local:
-Group plugins return the identifiers for the groups a principal is a member of. Since a principal can be either a user or a group this implies that PAS can support nested group members. The default PAS configuration does not support this though.
+Group plugins return the identifiers for the groups a principal is a
+member of. Since a principal can be either a user or a group this means
+that PAS can support nested group members. The default PAS configuration
+does not support this though.
-Like other PAS interfaces the IGroupsPlugin interface is simple and only specifies a single method::
+Like other PAS interfaces, the ``IGroupsPlugin`` interface is simple and
+only specifies a single method::
- def getGroupsForPrincipal( principal, request=None ):
- """ principal -> ( group_1, ... group_N )
- o Return a sequence of group names to which the principal
- (either a user or another group) belongs.
- o May assign groups based on values in the REQUEST object, if present
- """
+ def getGroupsForPrincipal(principal, request=None):
+ """ principal -> ( group_1, ... group_N )
+ o Return a sequence of group names to which the principal
+ (either a user or another group) belongs.
+ o May assign groups based on values in the REQUEST object, if present
+ """
Here is a simple example::
- def getGroupsForPrincipal(self, principal, request=None):
- # Manager can not be itself
- if principal=="Manager":
- return ()
-
- # Only act on the current user
- if getSecurityManager().getUser().getId()!=principal:
- return ()
-
- # Only act if the request originates from the local host
- if request is not None:
- ip=request.get("HTTP_X_FORWARDED_FOR", request.get("REMOTE_ADDR", ""))
- if ip!="127.0.0.1":
- return ()
-
- return ("Manager",)
-
-This puts the current user in the Manager group if the site is being accessed from the Zope server itself.
+ def getGroupsForPrincipal(self, principal, request=None):
+ # Manager can not be itself
+ if principal == "Manager":
+ return ()
+
+ # Only act on the current user
+ if getSecurityManager().getUser().getId() != principal:
+ return ()
+
+ # Only act if the request originates from the local host
+ if request is not None:
+ ip=request.get("HTTP_X_FORWARDED_FOR", request.get("REMOTE_ADDR", ""))
+ if ip != "127.0.0.1":
+ return ()
+
+ return ("Manager",)
+
+This puts the current user in the Manager group if the site is being
+accessed from the Zope server itself.
View
5 source/members/pluggable_authentication_service/index.rst
@@ -4,8 +4,9 @@
.. admonition:: Description
- Pluggable authentication service (PAS) provides easy way to customize your user, permission
- authentication behavior.
+ The Pluggable authentication service (PAS)
+ provides an easy way to customize the way your users are
+ authenticated and assigned roles.
.. toctree::
:maxdepth: 2
View
21 source/members/pluggable_authentication_service/introduction.rst
@@ -2,14 +2,23 @@
Introduction
============
-.. contents :: :local:
+.. contents:: :local:
.. admonition:: Description
- The Pluggable Authentication Service (PAS) is an alternative to the standard Zope User
- Folder or the popular Group User Folder (GRUF). PAS has a highly modular design, which is
- very powerful, but also a lot harder to understand.
+ The Pluggable Authentication Service (PAS) is an alternative
+ to the standard Zope User Folder
+ or the popular Group User Folder (GRUF).
+ PAS has a highly modular design, which is
+ very powerful, but also a lot harder to understand.
-PAS is built around the concepts of interfaces and plugins: all possible tasks related to user and group management and authentication are described in separate interfaces. These interfaces are implemented by plugins, which can be selectively enabled per interface.
+PAS is built around the concepts of interfaces and plugins:
+all possible tasks related to user and group management and authentication
+are described in separate interfaces.
+These interfaces are implemented by plugins
+which can be selectively enabled per interface.
-Plone uses PlonePAS, which extends PAS with a couple of extra plugin types and which adds GRUF compatibility. Since PlonePAS extensions are rarely needed and are subject to change in the next Plone releases this tutorial will only focus on pure PAS features.
+Plone uses PlonePAS, which extends PAS with a couple of extra plugin types
+and which adds GRUF compatibility.
+Since PlonePAS extensions are rarely needed and are subject to change
+in new Plone releases, this tutorial will focus only on pure PAS features.
View
36 source/members/pluggable_authentication_service/properties-plugins.rst
@@ -2,24 +2,32 @@
Properties plugins
==================
-.. contents :: :local:
+.. contents:: :local:
-Properties are stored in property sheets: mapping-like objecst, such as a standard python dictionary, which contain the properties for a principal. The property sheets are ordered: if a property is present in multiple property sheets only the property in the sheet with the highest priority is visible.
+Properties are stored in property sheets:
+mapping-like objects, such as a standard python dictionary,
+which contain the properties for a principal.
+The property sheets are ordered:
+if a property is present in multiple property sheets only the property in
+the sheet with the highest priority is visible.
-Property sheets are created by plugins implementing the IPropertiesPlugin interface. This interface contains only a single method::
+Property sheets are created by plugins implementing the
+``IPropertiesPlugin`` interface.
+This interface contains only a single method::
- def getPropertiesForUser( user, request=None ):
- """ user -> {}
- o User will implement IPropertiedUser.
- o Plugin may scribble on the user, if needed (but must still
- return a mapping, even if empty).
- o May assign properties based on values in the REQUEST object, if
- present
- """
+ def getPropertiesForUser( user, request=None ):
+ """ user -> {}
+ o User will implement IPropertiedUser.
+ o Plugin may scribble on the user, if needed (but must still
+ return a mapping, even if empty).
+ o May assign properties based on values in the REQUEST object, if
+ present
+ """
Here is a simple example::
- def getPropertiesForUser(self, user, request=None):
- return { "email" : user.getId() + "@ourcompany.com" }
+ def getPropertiesForUser(self, user, request=None):
+ return { "email" : user.getId() + "@ourcompany.com" }
-this adds an email property to a user which is hardcoded to the user id followed by a companies domain name.
+this adds an *email* property to a user which is hardcoded to the user id
+followed by a company's domain name.
View
43 source/members/pluggable_authentication_service/roles-plugin.rst
@@ -2,29 +2,32 @@
Roles plugin
============
-.. contents :: :local:
+.. contents:: :local:
-The IRolesPlugin plugins determine the global roles for a principal. Like the other interfaces the IRolesPlugin interface contains only a single method::
+The ``IRolesPlugin`` plugins determine the global roles for a principal.
+Like the other interfaces the ``IRolesPlugin`` interface contains only a
+single method::
- def getRolesForPrincipal( principal, request=None ):
- """ principal -> ( role_1, ... role_N )
- o Return a sequence of role names which the principal has.
- o May assign roles based on values in the REQUEST object, if present.
- """
+ def getRolesForPrincipal( principal, request=None ):
+ """ principal -> ( role_1, ... role_N )
+ o Return a sequence of role names which the principal has.
+ o May assign roles based on values in the REQUEST object, if present.
+ """
Here is a simple example::
- def getRolesForPrincipal(self, principal, request=None):
- # Only act on the current user
- if getSecurityManager().getUser().getId()!=principal:
- return ()
-
- # Only act if the request originates from the local host
- if request is not None:
- ip=request.get("HTTP_X_FORWARDED_FOR", request.get("REMOTE_ADDR", ""))
- if ip!="127.0.0.1":
- return ()
-
- return ("Manager",)
+ def getRolesForPrincipal(self, principal, request=None):
+ # Only act on the current user
+ if getSecurityManager().getUser().getId()!=principal:
+ return ()
+
+ # Only act if the request originates from the local host
+ if request is not None:
+ ip=request.get("HTTP_X_FORWARDED_FOR", request.get("REMOTE_ADDR", ""))
+ if ip!="127.0.0.1":
+ return ()
+
+ return ("Manager",)
-This gives the current user in Manager role if the site is being accessed from the Zope server itself.
+This gives the current user in Manager role if the site is being accessed
+from the Zope server itself.
View
24 source/members/pluggable_authentication_service/the-important-interfaces.rst
@@ -2,25 +2,37 @@
The important interfaces
========================
-.. contents :: :local:
+.. contents:: :local:
.. admonition:: Description
- PAS has a number of interfaces that are important for everyone.
+ PAS has a number of interfaces that are important for everyone.
The most important interfaces that you may want to configure are:
**Authentication**
- Authentication plugins are responsible for authenticating a set of credentials. Usually that will mean verifying if a login name and password are correct by comparing them with a user record in a database such as the ZODB or an SQL database.
+ Authentication plugins are responsible for authenticating a set of
+ credentials. Usually that will mean verifying if a login name and
+ password are correct by comparing them with a user record in a database
+ such as the ZODB or an SQL database.
**Extraction**
- Extraction plugins determine the credentials for a request. Credentials can take different forms such as a HTTP cookie, HTTP form data or the users IP address.
+ Extraction plugins determine the credentials for a request.
+ Credentials can take different forms, such as a HTTP cookie, HTTP form
+ data or the user's IP address.
**Groups**
- These plugins determine of which group(s) a user (or group) is a member.
+ These plugins determine which group(s) a user (or group) belongs to.
**Properties**
- Property plugins manage all properties for users. This includes the standard information such as the user's name and email address but can also be any other piece of data that you want to store for a user. Multiple properties plugins can be used in parallel, making it possible for example to use some information from a central system such as active directory while storing data specific for your Plone site in the ZODB
+ Property plugins manage all properties for users.
+ This includes the standard information such as the user's name and
+ email address but can also be any other piece of data that you want to
+ store for a user.
+ Multiple properties plugins can be used in parallel,
+ making it possible for example to use some information from a central
+ system such as active directory while storing data specific to your
+ Plone site in the ZODB.
**User Enumeration**
User enumeration plugins implement the searching logic for users.
View
34 source/members/pluggable_authentication_service/the-user-object.rst
@@ -2,25 +2,33 @@
The user object
===============
-.. contents :: :local:
+.. contents:: :local:
.. admonition:: Description
- Contrary to other user folders, a user does not have a single source in a PAS environment.
- Various aspects of a user (properties, groups, roles, etc.) are managed by different
- plugins. To accommodate this, PAS features a user object which provides a single interface
- to all different aspects.
-
-There are two basic user types: a normal user (as defined by the IBasicUser interface) and a user with member properties (defined by the IPropertiedUser interface). Since basic users are not used within Plone we will only consider IPropertiedUser users.
-
-**getId()**
+ In contrast to other user folders, a user in a PAS environment does
+ not have a single source.
+ Various aspects of a user (properties, groups, roles, etc.) are
+ managed by different plugins.
+ To accommodate this, PAS features a user object which provides a
+ single interface to all different aspects.
+
+There are two basic user types:
+a normal user (as defined by the ``IBasicUser`` interface)
+and a user with member properties
+(defined by the ``IPropertiedUser`` interface).
+Since basic users are not used within Plone we will only consider
+``IPropertiedUser`` users.
+
+``getId()``
returns the user id. This is a unique identifier for a user.
-**getUserName()**
+``getUserName()``
Return the login name used by the user to log into the system.
-**getRoles()**
+``getRoles()``
Return the roles assigned to a user "globally".
-**getRolesInContext(context)**
- Return the roles assigned to the user within a specific context. This includes the global roles as returned by getRoles().
+``getRolesInContext(context)``
+ Return the roles assigned to the user within a specific context.
+ This includes the global roles as returned by ``getRoles()``.
View
12 source/members/pluggable_authentication_service/user-creation.rst
@@ -2,13 +2,13 @@
User creation
=============
-.. contents :: :local:
+.. contents:: :local:
.. admonition:: Description
- PAS uses a multi-phase algorithm to create a user object
+ PAS uses a multi-phase algorithm to create a user object
-#. An IUserFactoryPlugin plugin is used to create a new user object.
-#. All IPropertiesPlugin plugins are queried to get the property sheets.
-#. All IGroupsPlugin plugins are queried to get the groups.
-#. All IRolesPlugin plugins are queried to get the global roles
+#. An ``IUserFactoryPlugin`` plugin is used to create a new user object.
+#. All ``IPropertiesPlugin`` plugins are queried to get the property sheets.
+#. All ``IGroupsPlugin`` plugins are queried to get the groups.
+#. All ``IRolesPlugin`` plugins are queried to get the global roles.
View
30 source/members/pluggable_authentication_service/user-factory-plugin.rst
@@ -2,22 +2,30 @@
User factory plugin
===================
-.. contents :: :local:
+.. contents:: :local:
-PAS supports multiple user types. PAS contains two default user types: IBasicUser and IPropertiesUser. IBasicUser is a simple user type which supports a user id, login name, roles and domain restrictions. IPropertiedUser extends this type and adds user properties.
+PAS supports multiple user types.
+The two default user types are: ``IBasicUser`` and ``IPropertiesUser``.
+``IBasicUser`` is a simple user type which supports a user id,
+login name, roles and domain restrictions.
+``IPropertiedUser`` extends this type and adds user properties.
-A user factory plugin creates a new user instance. PAS will add properties, groups and roles to this instance as part of its user creation process.
+A user factory plugin creates a new user instance.
+PAS will add properties, groups and roles to this instance as part of its
+user creation process.
-If no user factory plugin is able to create a user PAS will fall back to creating a standard PropertiedUser instance.
+If no user factory plugin is able to create a user, PAS will fall back to
+creating a standard ``PropertiedUser`` instance.
-The IUserFactoryPlugin interface is a simple one containing a single method::
+The ``IUserFactoryPlugin`` interface is a simple one containing a single
+method::
- def createUser( user_id, name ):
- """ Return a user, if possible.
- o Return None to allow another plugin, or the default, to fire.
- """
+ def createUser( user_id, name ):
+ """ Return a user, if possible.
+ o Return None to allow another plugin, or the default, to fire.
+ """
The default PAS behaviour is demonstrated by this code::
- def createUser(self, user_id, name):
- return ProperiedUser(user_id, name)
+ def createUser(self, user_id, name):
+ return ProperiedUser(user_id, name)
View
109 source/serving/webdav.rst
@@ -1,6 +1,6 @@
------------
+===========
WebDAV
------------
+===========
.. admonition:: Description
@@ -99,7 +99,7 @@ A ``HEAD`` request retrieves headers only.
value if that exists. Otherwise, it returns a ``405 Method Not Allowed`` response.
If there is no ``index_html`` object, it returns ``404 Not Found``.
-GET
+``GET``
----------------
A ``GET`` request retrieves headers and body.
@@ -174,10 +174,10 @@ This differs from the event sequence of an object created through the web.
Here, only an ``IObjectCreatedEvent`` is fired, and only *after* the object
has been fully initialised.
-DELETE
+``DELETE``
----------------
-A DELETE request instructs the WebDAV server to delete a resource.
+A ``DELETE`` request instructs the WebDAV server to delete a resource.
``Resource.DELETE()`` calls ``manage_delObjects()`` on the parent folder to delete
an object.
@@ -185,25 +185,25 @@ an object.
``Collection.DELETE()`` does the same, but checks for write locks of all
children of the collection, recursively, before allowing the delete.
-PROPFIND
+``PROPFIND``
----------------
-A PROPFIND request returns all or a set of WebDAV properties. WebDAV
+A ``PROPFIND`` request returns all or a set of WebDAV properties. WebDAV
properties are metadata used to describe an object, such as the last modified
time or the author.
``Resource.PROPFIND()`` parses the request and then looks for a
``propertysheets`` attribute on self.
-If an 'allprop' request is received, it calls ``dav__allprop()``, if
+If an ``allprop`` request is received, it calls ``dav__allprop()``, if
available, on each property sheet. This method returns a list of name/value
pairs in the correct WebDAV XML encoding, plus a status.
-If a 'propnames' request is received, it calls ``dav__propnames()``, if
+If a ``propnames`` request is received, it calls ``dav__propnames()``, if
available, on each property sheet. This method returns a list of property
names in the correct WebDAV XML encoding, plus a status.
-If a 'propstat' request is received, it calls ``dav__propstats()``, if
+If a ``propstat`` request is received, it calls ``dav__propstats()``, if
available, on each property sheet, for each requested property. This method
returns a property name/value pair in the correct WebDAV XML encoding, plus a
status.
@@ -222,39 +222,49 @@ number of read-only properties: ``creationdate``, ``displayname``,
``supportedlock``, and ``lockdiscovery``. These in turn are delegated to
methods prefixed with ``dav__``, so e.g. reading the ``creationdate`` property
calls ``dav__creationdate()`` on the property sheet instance. These methods
-in turn return values based on the the property manager instance (i.e. the
+in turn return values based on the property manager instance (i.e. the
content object). In particular:
-* ``creationdate`` returns a fixed date (January 1st, 1970).
-* ``displayname`` returns the value of the ``title_or_id()`` method
-* ``resourcetype`` returns an empty string or <n:collection/>
-* ``getlastmodified`` returns the ZODB modification time
-* ``getcontenttype`` delegates to the ``content_type()`` method, falling
- back on the ``default_content_type()`` method. In Dexterity,
- ``content_type()`` is implemented to look up the ``IRawReadFile`` adapter
- on the context and return the value of its ``mimeType`` property.
-* ``getcontentlength`` delegates to the ``get_size()`` method (which is also
- used for the "size" column in Plone folder listings). In Dexterity,
- this looks up a ``zope.size.interfaces.ISized`` adapter on the object and
- calls ``sizeForSorting()``. If this returns a unit of ``'bytes'``, the
- value portion is used. Otherwise, a size of 0 is returned.
-* ``source`` returns a link to ``/document_src``, if that attribute exists
-* ``supportedlock`` indicates whether ``IWriteLock`` is supported by the
- content item
-* ``lockdiscovery`` returns information about any active locks
+``creationdate``
+ returns a fixed date (January 1st, 1970).
+``displayname``
+ returns the value of the ``title_or_id()`` method
+``resourcetype``
+ returns an empty string or <n:collection/>
+``getlastmodified``
+ returns the ZODB modification time
+``getcontenttype``
+ delegates to the ``content_type()`` method, falling
+ back on the ``default_content_type()`` method. In Dexterity,
+ ``content_type()`` is implemented to look up the ``IRawReadFile`` adapter
+ on the context and return the value of its ``mimeType`` property.
+``getcontentlength``
+ delegates to the ``get_size()`` method (which is also
+ used for the "size" column in Plone folder listings). In Dexterity,
+ this looks up a ``zope.size.interfaces.ISized`` adapter on the object and
+ calls ``sizeForSorting()``. If this returns a unit of ``'bytes'``, the
+ value portion is used. Otherwise, a size of 0 is returned.
+``source``
+ returns a link to ``/document_src``, if that attribute exists
+``supportedlock``
+ indicates whether ``IWriteLock`` is supported by the content item
+``lockdiscovery``
+ returns information about any active locks
Other properties in this and any other property sheets are returned as stored
when requested.
-If the PROPFIND request specifies a depth of 1 or infinity (i.e. the client
-wants properties for items in a collection), the process is repeated for all
-items returned by the ``listDAVObjects()`` methods, which by default returns
+If the ``PROPFIND`` request specifies a depth of 1 or infinity
+(i.e. the client wants properties for items in a collection),
+the process is repeated for all
+items returned by the ``listDAVObjects()`` methods,
+which by default returns
all contained items via the ``objectValues()`` method.
-PROPPATCH
+``PROPPATCH``
----------------
-A PROPPATCH request is used to update the properties on an existing object.
+A ``PROPPATCH`` request is used to update the properties on an existing object.
``Resource.PROPPATCH()`` deals with the same types of properties from property
sheets as ``PROPFIND()``. It uses the ``PropertySheet`` API to add or update
@@ -282,28 +292,29 @@ In Dexterity, ``MKCOL()_handler`` is overridden to adapt self to an
a directory. The default implementation simply calls ``manage_addFolder()``
on the parent. This will create an instance of the ``Folder`` type.
-COPY
+``COPY``
----------------
-A COPY request is used to copy a resource.
+A ``COPY`` request is used to copy a resource.
``Resource.COPY()`` implements this operation using the standard Zope content
object copy semantics.
-MOVE
+``MOVE``
----------------
-A MOVE request is used to relocate or rename a resource.
+A ``MOVE`` request is used to relocate or rename a resource.
``Resource.MOVE()`` implements this operation using the standard Zope content
object move semantics.
-LOCK
+``LOCK``
----------------
-A LOCK request is used to lock a content object.
+A ``LOCK`` request is used to lock a content object.
-All relevant WebDAV methods in the ``webdav`` package are lock aware. That is,
+All relevant WebDAV methods in the ``webdav`` package are lock aware.
+That is,
they check for locks before attempting any operation that would violate a
lock.
@@ -319,10 +330,10 @@ this means locking the name of the non-existent resource. When a
parent (remember that a ``NullResource`` is a transient object returned
when a child object cannot be found in a WebDAV request).
-UNLOCK
+``UNLOCK``
----------------
-An UNLOCK request is used to unlock a locked object.
+An ``UNLOCK`` request is used to unlock a locked object.
``Resource.UNLOCK()`` handles unlock requests.
@@ -339,10 +350,10 @@ a pseudo-file with the name '_data', by injecting this into the return value
of ``listDAVObjects()`` and adding a special traversal hook to allow its
contents to be retrieved.
-This pseudo-file supports ``HEAD``, ``GET``, ``PUT``, ``LOCK``, ``UNLOCK``,
-``PROPFIND`` and ``PROPPATCH``
-requests (an error will be raised if the user attempts to rename, copy, move
-or delete it). These operate on the container object, obviously. For example,
-when the data object is updated via a ``PUT`` request, the ``PUT()`` method on
-the container is called, by default delegating to an ``IRawWriteFile`` adapter
-on the container.
+This pseudo-file supports ``HEAD``, ``GET``, ``PUT``, ``LOCK``,
+``UNLOCK``, ``PROPFIND`` and ``PROPPATCH`` requests
+(an error will be raised if the user attempts to rename, copy, move
+or delete it). These operate on the container object, obviously.
+For example, when the data object is updated via a ``PUT`` request,
+the ``PUT()`` method on the container is called,
+by default delegating to an ``IRawWriteFile`` adapter on the container.

No commit comments for this range

Something went wrong with that request. Please try again.