Contents
remember (small r) and membrane are framework add-on products for Plone which allows you to manipulate site members as they were normal content objects. The product also allows distributed user management and different user classes.
Example:
from Products.CMFCore.utils import getToolByName
membrane = getToolByName(context, "membrane_tool")
# getUserAuthProvider returns None if there is no membrane based user match for username
# e.g. this will return None for Zope admin user
sits_user = membrane.getUserAuthProvider(username)
return sits_user
Below is an example how to resolve member content object from MembraneUser record “owner” who is user “local_user”:
(Pdb) mbtool = self.portal.membrane_tool
(Pdb) owner
<MembraneUser 'local_user'>
(Pdb) mbtool.getUserAuthProvider(owner.getId())
<SitsLocalUser at /plone/country/hospital/local_users/local_user
The following snippet works in unit tests:
mem_password = 'secret'
def_mem_data = {
'email': 'noreply@xxxxxxxxyyyyyy.com',
'password': mem_password,
'confirm_password': mem_password,
}
mem_data = {
'portal_member':
{
'fullname': 'Portal Member',
'mail_me': True,
},
'admin_member':
{
'roles': ['Manager', 'Member']
},
'blank_member':
{},
}
mdata = getToolByName(self.portal, 'portal_memberdata')
mdata.invokeFactory("MyUserPortalType", name)
member = getattr(mdata, name) #
Use the following unit test snippet:
def populateUser(self, member):
""" Auto-ppulate member object required fields based on Archetypes schema.
@param member: Memberane member content object
"""
from Products.SitsHospital.content.SitsUser import SitsUser
schema = SitsUser.schema
data={}
for f in schema._fields.values():
if not f.required:
continue
if f.__name__ in [ "password", "id" ]:
# Do not set password or member id
continue
# Autofill member field values
if f.vocabulary:
value = f.vocabulary[0][0]
elif f.__name__ in [ "email" ]:
value = "test@xyz.com"
else:
value = "foo"
# print "filling in field:" + str(f)
data[f.__name__] = value
member.update(**data)
The following snippet is useful for unit testing:
def assertValidMember(self, member):
""" Emulate Products.remember.content.member validation behavior with verbose output.
"""
errors = {}
# make sure object has required data and metadata
member.Schema().validate(member, None, errors, 1, 1)
if errors:
raise AssertionError("Member contained errors:" + str(errors))
Passwords are stored hashed and can be set using BaseMember._setPassword() method.
_setPassword() takes password as plain-text argument and hashes it before storing:
user_object._setPassword("secret")
Use password attribute directly.
hashed = user_object.password
Password hash should be unicode string.
Note
By default, Products.remember uses HMACHash hasher. As a salt, str(context) string is used. This means that it is not possible to move hashed password from one context item to another. For more information see Products.remember.content.password_hashers module.