Creating membrane aware content

It is not difficult to extend content types to act as (parts of) users or groups with membrane. The only thing that is needed is to make sure that your content is adaptable to one of the membrane interfaces. You can either make your content type implement the interfaces directly, or register separate adapters.

Basic user

To expose a content object as a user you must implement the IMembraneUserObject interface. This is a very minimal interface which membrane users to find the userid and the login name for a user. This is a minimal implementation:

from plone.dexterity.content import Item
from Products.membrane.interfaces import IMembraneUserAuth
from plone.uuid.interfaces import IUUID

class MyContent(Item):
    pass

class MyContentUer(object):
    def __init__(self, context):
        self.context=context

    def getUserId(self):
        return IUUID(self.context, None)

    def getUserName(self):
        return self.context.login
interface Products.membrane.interfaces.IMembraneUserObject

Needs to be implemented by anything user-related so we can easily determine the unique user that the object is related to.

This is the base interface that all objects that want to provide a user via membrane much implement or be adaptable to.

getUserName()

Return the name used for login. This can be the same as the userid, but might also be something different such as the users email address.

getUserId()

Return the unique identifier for the user that this piece of content relates to. Historically the Archetype UID of an object is used as userid.

Note

If you use adapters to implement the membrane interfaces, and you also implement one of the other membrane interfaces you do not need to register the IMembraneUserObject adapter separately since all other interfaces are derived from it. It is recommended to use a MyContentUser-like class as base class for all adapters to make sure the getUserId() and getUserName() implemenations are not duplicated.

Authentication

If you want a user to be able to login in a site you must add authentication support to your user content type. This is handled through the IMembraneUserAuth interface. Below is an example for a very basic authentication handler which users a plaintext password attribute. This uses the BaseUserObject class shown above.

The example below demonstrates a very simple authentication adapter. It uses the MyContentUser class shown earlier, and uses five.grok to create the adapter so you do not need to write any ZCML.

from plone.dexterity.content import Item
from five import grok
from Products.membrane.interfaces import IMembraneUserAuth
from plone.uuid.interfaces import IUUID

class MyContent(Item):
    pass

class MyUserAuthentication(grok.Adapter, MyContentUser):
    grok.context(Content)
    grok.implements(IMembraneUserAuth)

    def authenticateCredentials(self, credentials):
        if self.context.password==credentials["password"]:
            return (self.getUserId(), self.getUserName())
        return None
interface Products.membrane.interfaces.IMembraneUserAuth

Extends: Products.membrane.interfaces.user.IMembraneUserObject, Products.PluggableAuthService.interfaces.plugins.IAuthenticationPlugin

Used for objects that can handle user authentication.

User properties

Every user in a Plone site will be able to use the standard user property support as provided by PluggableAuthService. Often you want to be able to use a content object to manage properties for a user, for example to be able to use standard edit screens to manage certain properties. You can do this by via the IMembraneUserProperties interface.

interface Products.membrane.interfaces.IMembraneUserProperties

Extends: Products.membrane.interfaces.user.IMembraneUserObject, Products.PlonePAS.interfaces.plugins.IMutablePropertiesPlugin

Used for objects that can provide user properties.

Table Of Contents

Previous topic

Products.membrane - Content as users

Next topic

Frequently asked questions

This Page