Back to index

plone3  3.1.7
ufactory.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # PlonePAS - Adapt PluggableAuthService for use in Plone
00004 # Copyright (C) 2005 Enfold Systems, Kapil Thangavelu, et al
00005 #
00006 # This software is subject to the provisions of the Zope Public License,
00007 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this
00008 # distribution.
00009 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00010 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00011 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00012 # FOR A PARTICULAR PURPOSE.
00013 #
00014 ##############################################################################
00015 """
00016 """
00017 
00018 from AccessControl import ClassSecurityInfo
00019 from AccessControl.PermissionRole import _what_not_even_god_should_do
00020 from Globals import InitializeClass, DTMLFile
00021 
00022 from Products.PluggableAuthService.utils import classImplements
00023 from Products.PluggableAuthService.PropertiedUser import PropertiedUser
00024 from Products.PluggableAuthService.UserPropertySheet import UserPropertySheet
00025 from Products.PluggableAuthService.interfaces.plugins import IUserFactoryPlugin
00026 from Products.PluggableAuthService.interfaces.propertysheets import IPropertySheet
00027 from Products.PluggableAuthService.interfaces.plugins import IPropertiesPlugin
00028 from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
00029 
00030 from Products.CMFPlone.MemberDataTool import _marker
00031 
00032 from Products.PlonePAS.interfaces.plugins import ILocalRolesPlugin
00033 from Products.PlonePAS.interfaces.propertysheets import IMutablePropertySheet
00034 from Products.PlonePAS.utils import unique, getCharset
00035 from Products.PlonePAS.odict import OrderedDict
00036 
00037 manage_addPloneUserFactoryForm = DTMLFile('../zmi/PloneUserFactoryForm',
00038                                           globals())
00039 
00040 def manage_addPloneUserFactory(self, id, title='', RESPONSE=None):
00041     """
00042     Add a plone user factory
00043     """
00044 
00045     puf = PloneUserFactory(id, title)
00046     self._setObject(puf.getId(), puf)
00047 
00048     if RESPONSE is not None:
00049         return RESPONSE.redirect('manage_workspace')
00050 
00051 
00052 class PloneUserFactory(BasePlugin):
00053 
00054     security = ClassSecurityInfo()
00055     meta_type = 'Plone User Factory'
00056 
00057     def __init__(self, id, title=''):
00058         self.id = id
00059         self.title = title or self.meta_type
00060 
00061     security.declarePrivate('createUser')
00062     def createUser(self, user_id, name):
00063         return PloneUser(user_id, name)
00064 
00065 classImplements(PloneUserFactory,
00066                 IUserFactoryPlugin)
00067 
00068 InitializeClass(PloneUserFactory)
00069 
00070 
00071 class PloneUser(PropertiedUser):
00072 
00073     security = ClassSecurityInfo()
00074 
00075     #################################
00076     # GRUF API
00077     _isGroup = False
00078 
00079     def __init__( self, id, login=None ):
00080         super( PloneUser, self).__init__( id, login )
00081         self._propertysheets = OrderedDict()
00082 
00083     def _getPAS(self):
00084         # XXX This is not very optimal *at all*
00085         return self.acl_users
00086         
00087     def _getPlugins(self):
00088         # XXX This is not very optimal *at all*
00089         return self._getPAS().plugins
00090 
00091     security.declarePublic('isGroup')
00092     def isGroup(self):
00093         """Return 1 if this user is a group abstraction"""
00094         return self._isGroup
00095 
00096     security.declarePublic('getName')
00097     def getName(self):
00098         """Get user's or group's name.
00099         This is the id. PAS doesn't do prefixes and such like GRUF.
00100         """
00101         return self.getId()
00102 
00103     security.declarePublic('getName')
00104     def getUserId(self):
00105         """Get user's or group's name.
00106         This is the id. PAS doesn't do prefixes and such like GRUF.
00107         """
00108         return self.getId()
00109 
00110     security.declarePublic('getGroupNames')
00111     def getGroupNames(self):
00112         """Return ids of this user's groups. GRUF compat."""
00113         return self.getGroups()
00114 
00115     security.declarePublic('getGroupIds')
00116     getGroupIds = getGroupNames
00117 
00118     #################################
00119     # acquisition aware
00120 
00121     security.declarePublic('getPropertysheet')
00122     def getPropertysheet(self, id):
00123         """ -> propertysheet (wrapped if supported)
00124         """
00125         sheet = self._propertysheets[id]
00126         try:
00127             return sheet.__of__(self)
00128         except AttributeError:
00129             return sheet
00130 
00131     security.declarePrivate('addPropertysheet')
00132     def addPropertysheet(self, id, data):
00133         """ -> add a prop sheet, given data which is either
00134         a property sheet or a raw mapping.
00135         """
00136         if IPropertySheet.providedBy(data):
00137             sheet = data
00138         else:
00139             sheet = UserPropertySheet(id, **data)
00140 
00141         if self._propertysheets.get(id) is not None:
00142             raise KeyError, 'Duplicate property sheet: %s' % id
00143 
00144         self._propertysheets[id] = sheet
00145 
00146     def _getPropertyPlugins(self):
00147         return self._getPAS().plugins.listPlugins(IPropertiesPlugin)
00148 
00149     security.declarePrivate('getOrderedPropertySheets')
00150     def getOrderedPropertySheets(self):
00151         return self._propertysheets.values()
00152 
00153     #################################
00154     # local roles plugin type delegation
00155 
00156     def _getLocalRolesPlugins(self):
00157         return self._getPAS().plugins.listPlugins(ILocalRolesPlugin)
00158 
00159     def getRolesInContext(self, object):
00160         lrmanagers = self._getLocalRolesPlugins()
00161         roles = []
00162         for lrid, lrmanager in lrmanagers:
00163             roles.extend(lrmanager.getRolesInContext(self, object))
00164         roles.extend(self.getRoles())
00165         return unique(roles)
00166 
00167     def allowed(self, object, object_roles = None):
00168         if object_roles is _what_not_even_god_should_do:
00169             return 0
00170 
00171         # Short-circuit the common case of anonymous access.
00172         if object_roles is None or 'Anonymous' in object_roles:
00173             return 1
00174 
00175         # Provide short-cut access if object is protected by 'Authenticated'
00176         # role and user is not nobody
00177         if 'Authenticated' in object_roles and (
00178             self.getUserName() != 'Anonymous User'):
00179             return 1
00180 
00181         # Check for ancient role data up front, convert if found.
00182         # This should almost never happen, and should probably be
00183         # deprecated at some point.
00184         if 'Shared' in object_roles:
00185             object_roles = self._shared_roles(object)
00186             if object_roles is None or 'Anonymous' in object_roles:
00187                 return 1
00188 
00189         # Check for a role match with the normal roles given to
00190         # the user, then with local roles only if necessary. We
00191         # want to avoid as much overhead as possible.
00192         user_roles = self.getRoles()
00193         for role in object_roles:
00194             if role in user_roles:
00195                 if self._check_context(object):
00196                     return 1
00197                 return None
00198 
00199         # check for local roles
00200         lrmanagers = self._getLocalRolesPlugins()
00201 
00202         for lrid, lrm in lrmanagers:
00203             allowed = lrm.checkLocalRolesAllowed(self, object, object_roles)
00204             # return values
00205             # 0, 1, None
00206             # - 1 success
00207             # - 0 object context violation
00208             # - None - failure
00209             if allowed is None:
00210                 continue
00211             return allowed
00212         return None
00213 
00214     def setProperties(self, properties=None, **kw):
00215         if properties is None:
00216             properties=kw
00217 
00218         for sheet in self.getOrderedPropertySheets():
00219             if not IMutablePropertySheet.providedBy(sheet):
00220                 continue
00221 
00222             update={}
00223             for (key,value) in kw.items():
00224                 if sheet.hasProperty(key):
00225                     update[key]=value
00226                     del kw[key]
00227 
00228             if update:
00229                 sheet.setProperties(self, update)
00230 
00231 
00232     def getProperty(self, id, default=_marker):
00233         for sheet in self.getOrderedPropertySheets():
00234             if sheet.hasProperty(id):
00235                 value=sheet.getProperty(id)
00236                 if isinstance(value, unicode):
00237                     # XXX Temporarily work around the fact that
00238                     # property sheets blindly store and return
00239                     # unicode. This is sub-optimal and should be
00240                     # dealed with at the property sheets level by
00241                     # using Zope's converters.
00242                     charset = getCharset(self)
00243                     return value.encode(charset)
00244                 return value
00245 
00246         return default
00247 
00248 InitializeClass(PloneUser)