Back to index

plone3  3.1.7
RegistrationTool.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
00004 #
00005 # This software is subject to the provisions of the Zope Public License,
00006 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
00007 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00008 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00009 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00010 # FOR A PARTICULAR PURPOSE.
00011 #
00012 ##############################################################################
00013 """ Basic user registration tool.
00014 
00015 $Id: RegistrationTool.py 77182 2007-06-28 17:25:27Z yuppie $
00016 """
00017 
00018 import re
00019 from random import choice
00020 
00021 from AccessControl import ClassSecurityInfo
00022 from AccessControl.requestmethod import postonly
00023 from Globals import DTMLFile
00024 from Globals import InitializeClass
00025 from OFS.SimpleItem import SimpleItem
00026 from zope.interface import implements
00027 
00028 from interfaces import IRegistrationTool
00029 from interfaces.portal_registration \
00030         import portal_registration as z2IRegistrationTool
00031 from permissions import AddPortalMember
00032 from permissions import MailForgottenPassword
00033 from permissions import ManagePortal
00034 from utils import _checkPermission
00035 from utils import _dtmldir
00036 from utils import _limitGrantedRoles
00037 from utils import getToolByName
00038 from utils import Message as _
00039 from utils import UniqueObject
00040 
00041 
00042 class RegistrationTool(UniqueObject, SimpleItem):
00043 
00044     """ Create and modify users by making calls to portal_membership.
00045     """
00046 
00047     implements(IRegistrationTool)
00048     __implements__ = (z2IRegistrationTool, )
00049 
00050     id = 'portal_registration'
00051     meta_type = 'CMF Registration Tool'
00052     member_id_pattern = ''
00053     default_member_id_pattern = "^[A-Za-z][A-Za-z0-9_]*$"
00054     _ALLOWED_MEMBER_ID_PATTERN = re.compile(default_member_id_pattern)
00055 
00056     security = ClassSecurityInfo()
00057 
00058     manage_options = ( ({'label': 'Overview',
00059                          'action': 'manage_overview'},
00060                         {'label': 'Configure',
00061                          'action': 'manage_configuration'})
00062                      + SimpleItem.manage_options
00063                      )
00064 
00065     #
00066     #   ZMI methods
00067     #
00068     security.declareProtected(ManagePortal, 'manage_overview')
00069     manage_overview = DTMLFile( 'explainRegistrationTool', _dtmldir )
00070 
00071     security.declareProtected(ManagePortal, 'manage_configuration')
00072     manage_configuration = DTMLFile('configureRegistrationTool', _dtmldir)
00073 
00074     security.declareProtected(ManagePortal, 'manage_editIDPattern')
00075     def manage_editIDPattern(self, pattern, REQUEST=None):
00076         """Edit the allowable member ID pattern TTW"""
00077         pattern.strip()
00078 
00079         if len(pattern) > 0:
00080             self.member_id_pattern = pattern
00081             self._ALLOWED_MEMBER_ID_PATTERN = re.compile(pattern)
00082         else:
00083             self.member_id_pattern = ''
00084             self._ALLOWED_MEMBER_ID_PATTERN = re.compile(
00085                                                 self.default_member_id_pattern)
00086 
00087         if REQUEST is not None:
00088             msg = 'Member ID Pattern changed'
00089             return self.manage_configuration(manage_tabs_message=msg)
00090 
00091     security.declareProtected(ManagePortal, 'getIDPattern')
00092     def getIDPattern(self):
00093         """ Return the currently-used member ID pattern """
00094         return self.member_id_pattern
00095 
00096     security.declareProtected(ManagePortal, 'getDefaultIDPattern')
00097     def getDefaultIDPattern(self):
00098         """ Return the currently-used member ID pattern """
00099         return self.default_member_id_pattern
00100 
00101 
00102     #
00103     #   'portal_registration' interface methods
00104     #
00105     security.declarePublic('isRegistrationAllowed')
00106     def isRegistrationAllowed(self, REQUEST):
00107         '''Returns a boolean value indicating whether the user
00108         is allowed to add a member to the portal.
00109         '''
00110         return _checkPermission(AddPortalMember, self.aq_inner.aq_parent)
00111 
00112     security.declarePublic('testPasswordValidity')
00113     def testPasswordValidity(self, password, confirm=None):
00114         '''If the password is valid, returns None.  If not, returns
00115         a string explaining why.
00116         '''
00117         return None
00118 
00119     security.declarePublic('testPropertiesValidity')
00120     def testPropertiesValidity(self, new_properties, member=None):
00121         '''If the properties are valid, returns None.  If not, returns
00122         a string explaining why.
00123         '''
00124         return None
00125 
00126     security.declarePublic('generatePassword')
00127     def generatePassword(self):
00128         """ Generate a valid password.
00129         """
00130         # we don't use these to avoid typos: OQ0Il1
00131         chars = 'ABCDEFGHJKLMNPRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789'
00132         return ''.join( [ choice(chars) for i in range(6) ] )
00133 
00134     security.declareProtected(AddPortalMember, 'addMember')
00135     @postonly
00136     def addMember(self, id, password, roles=('Member',), domains='',
00137                   properties=None, REQUEST=None):
00138         '''Creates a PortalMember and returns it. The properties argument
00139         can be a mapping with additional member properties. Raises an
00140         exception if the given id already exists, the password does not
00141         comply with the policy in effect, or the authenticated user is not
00142         allowed to grant one of the roles listed (where Member is a special
00143         role that can always be granted); these conditions should be
00144         detected before the fact so that a cleaner message can be printed.
00145         '''
00146         # XXX: this method violates the rules for tools/utilities:
00147         # it depends on a non-utility tool
00148         if not self.isMemberIdAllowed(id):
00149             raise ValueError(_(u'The login name you selected is already in '
00150                                u'use or is not valid. Please choose another.'))
00151 
00152         failMessage = self.testPasswordValidity(password)
00153         if failMessage is not None:
00154             raise ValueError(failMessage)
00155 
00156         if properties is not None:
00157             failMessage = self.testPropertiesValidity(properties)
00158             if failMessage is not None:
00159                 raise ValueError(failMessage)
00160 
00161         # Limit the granted roles.
00162         # Anyone is always allowed to grant the 'Member' role.
00163         _limitGrantedRoles(roles, self, ('Member',))
00164 
00165         membership = getToolByName(self, 'portal_membership')
00166         membership.addMember(id, password, roles, domains, properties)
00167 
00168         member = membership.getMemberById(id)
00169         self.afterAdd(member, id, password, properties)
00170         return member
00171 
00172     security.declareProtected(AddPortalMember, 'isMemberIdAllowed')
00173     def isMemberIdAllowed(self, id):
00174         '''Returns 1 if the ID is not in use and is not reserved.
00175         '''
00176         # XXX: this method violates the rules for tools/utilities:
00177         # it depends on a non-utility tool
00178         if len(id) < 1 or id == 'Anonymous User':
00179             return 0
00180         if not self._ALLOWED_MEMBER_ID_PATTERN.match( id ):
00181             return 0
00182         membership = getToolByName(self, 'portal_membership')
00183         if membership.getMemberById(id) is not None:
00184             return 0
00185         return 1
00186 
00187     security.declarePublic('afterAdd')
00188     def afterAdd(self, member, id, password, properties):
00189         '''Called by portal_registration.addMember()
00190         after a member has been added successfully.'''
00191         pass
00192 
00193     security.declareProtected(MailForgottenPassword, 'mailPassword')
00194     def mailPassword(self, forgotten_userid, REQUEST):
00195         '''Email a forgotten password to a member.  Raises an exception
00196         if user ID is not found.
00197         '''
00198         raise NotImplementedError
00199 
00200 InitializeClass(RegistrationTool)