Commit 975ad4d7 authored by Kazuhiko Shiozaki's avatar Kazuhiko Shiozaki

ERP5Security: cleanup. fix indentation and remove unused import.

parent 3751610a
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
# #
############################################################################## ##############################################################################
from zLOG import LOG, PROBLEM
from Products.ERP5Type.Globals import InitializeClass from Products.ERP5Type.Globals import InitializeClass
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
...@@ -102,11 +101,11 @@ def addERP5AccessTokenExtractionPlugin(dispatcher, id, title=None, REQUEST=None) ...@@ -102,11 +101,11 @@ def addERP5AccessTokenExtractionPlugin(dispatcher, id, title=None, REQUEST=None)
dispatcher._setObject(plugin.getId(), plugin) dispatcher._setObject(plugin.getId(), plugin)
if REQUEST is not None: if REQUEST is not None:
REQUEST['RESPONSE'].redirect( REQUEST['RESPONSE'].redirect(
'%s/manage_workspace' '%s/manage_workspace'
'?manage_tabs_message=' '?manage_tabs_message='
'ERP5AccessTokenExtractionPlugin+added.' 'ERP5AccessTokenExtractionPlugin+added.'
% dispatcher.absolute_url()) % dispatcher.absolute_url())
#List implementation of class #List implementation of class
classImplements(ERP5AccessTokenExtractionPlugin, classImplements(ERP5AccessTokenExtractionPlugin,
......
...@@ -35,8 +35,8 @@ from Products.PluggableAuthService.utils import classImplements ...@@ -35,8 +35,8 @@ from Products.PluggableAuthService.utils import classImplements
from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
from Products.ERP5Security.ERP5UserManager import SUPER_USER from Products.ERP5Security.ERP5UserManager import SUPER_USER
from Products.PluggableAuthService.PluggableAuthService import DumbHTTPExtractor from Products.PluggableAuthService.PluggableAuthService import DumbHTTPExtractor
from AccessControl.SecurityManagement import getSecurityManager,\ from AccessControl.SecurityManagement import getSecurityManager, \
setSecurityManager, newSecurityManager setSecurityManager, newSecurityManager
#Form for new plugin in ZMI #Form for new plugin in ZMI
manage_addERP5BearerExtractionPluginForm = PageTemplateFile( manage_addERP5BearerExtractionPluginForm = PageTemplateFile(
...@@ -50,11 +50,11 @@ def addERP5BearerExtractionPlugin(dispatcher, id, title=None, REQUEST=None): ...@@ -50,11 +50,11 @@ def addERP5BearerExtractionPlugin(dispatcher, id, title=None, REQUEST=None):
dispatcher._setObject(plugin.getId(), plugin) dispatcher._setObject(plugin.getId(), plugin)
if REQUEST is not None: if REQUEST is not None:
REQUEST['RESPONSE'].redirect( REQUEST['RESPONSE'].redirect(
'%s/manage_workspace' '%s/manage_workspace'
'?manage_tabs_message=' '?manage_tabs_message='
'ERP5BearerExtractionPlugin+added.' 'ERP5BearerExtractionPlugin+added.'
% dispatcher.absolute_url()) % dispatcher.absolute_url())
class ERP5BearerExtractionPlugin(BasePlugin): class ERP5BearerExtractionPlugin(BasePlugin):
""" """
......
...@@ -69,11 +69,11 @@ def addERP5DumbHTTPExtractionPlugin(dispatcher, id, title=None, REQUEST=None): ...@@ -69,11 +69,11 @@ def addERP5DumbHTTPExtractionPlugin(dispatcher, id, title=None, REQUEST=None):
dispatcher._setObject(plugin.getId(), plugin) dispatcher._setObject(plugin.getId(), plugin)
if REQUEST is not None: if REQUEST is not None:
REQUEST['RESPONSE'].redirect( REQUEST['RESPONSE'].redirect(
'%s/manage_workspace' '%s/manage_workspace'
'?manage_tabs_message=' '?manage_tabs_message='
'ERP5DumbHTTPExtractionPlugin+added.' 'ERP5DumbHTTPExtractionPlugin+added.'
% dispatcher.absolute_url()) % dispatcher.absolute_url())
#List implementation of class #List implementation of class
classImplements(ERP5DumbHTTPExtractionPlugin, classImplements(ERP5DumbHTTPExtractionPlugin,
......
...@@ -49,11 +49,11 @@ def addERP5ExternalAuthenticationPlugin(dispatcher, id, title=None, user_id_key= ...@@ -49,11 +49,11 @@ def addERP5ExternalAuthenticationPlugin(dispatcher, id, title=None, user_id_key=
dispatcher._setObject(plugin.getId(), plugin) dispatcher._setObject(plugin.getId(), plugin)
if REQUEST is not None: if REQUEST is not None:
REQUEST['RESPONSE'].redirect( REQUEST['RESPONSE'].redirect(
'%s/manage_workspace' '%s/manage_workspace'
'?manage_tabs_message=' '?manage_tabs_message='
'ERP5ExternalAuthenticationPlugin+added.' 'ERP5ExternalAuthenticationPlugin+added.'
% dispatcher.absolute_url()) % dispatcher.absolute_url())
class ERP5ExternalAuthenticationPlugin(BasePlugin): class ERP5ExternalAuthenticationPlugin(BasePlugin):
""" """
......
...@@ -35,8 +35,8 @@ from Products.PluggableAuthService.utils import classImplements ...@@ -35,8 +35,8 @@ from Products.PluggableAuthService.utils import classImplements
from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
from Products.ERP5Security.ERP5UserManager import SUPER_USER from Products.ERP5Security.ERP5UserManager import SUPER_USER
from Products.PluggableAuthService.PluggableAuthService import DumbHTTPExtractor from Products.PluggableAuthService.PluggableAuthService import DumbHTTPExtractor
from AccessControl.SecurityManagement import getSecurityManager,\ from AccessControl.SecurityManagement import getSecurityManager, \
setSecurityManager, newSecurityManager setSecurityManager, newSecurityManager
from Products.ERP5Type.Cache import DEFAULT_CACHE_SCOPE from Products.ERP5Type.Cache import DEFAULT_CACHE_SCOPE
import socket import socket
from Products.ERP5Security.ERP5UserManager import getUserByLogin from Products.ERP5Security.ERP5UserManager import getUserByLogin
...@@ -66,11 +66,11 @@ def addERP5FacebookExtractionPlugin(dispatcher, id, title=None, REQUEST=None): ...@@ -66,11 +66,11 @@ def addERP5FacebookExtractionPlugin(dispatcher, id, title=None, REQUEST=None):
dispatcher._setObject(plugin.getId(), plugin) dispatcher._setObject(plugin.getId(), plugin)
if REQUEST is not None: if REQUEST is not None:
REQUEST['RESPONSE'].redirect( REQUEST['RESPONSE'].redirect(
'%s/manage_workspace' '%s/manage_workspace'
'?manage_tabs_message=' '?manage_tabs_message='
'ERP5FacebookExtractionPlugin+added.' 'ERP5FacebookExtractionPlugin+added.'
% dispatcher.absolute_url()) % dispatcher.absolute_url())
#Form for new plugin in ZMI #Form for new plugin in ZMI
manage_addERP5GoogleExtractionPluginForm = PageTemplateFile( manage_addERP5GoogleExtractionPluginForm = PageTemplateFile(
...@@ -84,11 +84,11 @@ def addERP5GoogleExtractionPlugin(dispatcher, id, title=None, REQUEST=None): ...@@ -84,11 +84,11 @@ def addERP5GoogleExtractionPlugin(dispatcher, id, title=None, REQUEST=None):
dispatcher._setObject(plugin.getId(), plugin) dispatcher._setObject(plugin.getId(), plugin)
if REQUEST is not None: if REQUEST is not None:
REQUEST['RESPONSE'].redirect( REQUEST['RESPONSE'].redirect(
'%s/manage_workspace' '%s/manage_workspace'
'?manage_tabs_message=' '?manage_tabs_message='
'ERP5GoogleExtractionPlugin+added.' 'ERP5GoogleExtractionPlugin+added.'
% dispatcher.absolute_url()) % dispatcher.absolute_url())
class ERP5ExternalOauth2ExtractionPlugin: class ERP5ExternalOauth2ExtractionPlugin:
......
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
from Products.ERP5Type.Globals import InitializeClass from Products.ERP5Type.Globals import InitializeClass
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from AccessControl.SecurityManagement import newSecurityManager,\
getSecurityManager, setSecurityManager
from Products.PageTemplates.PageTemplateFile import PageTemplateFile from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
from Products.PluggableAuthService.utils import classImplements from Products.PluggableAuthService.utils import classImplements
...@@ -28,7 +26,6 @@ from Products.ERP5Type.ERP5Type \ ...@@ -28,7 +26,6 @@ from Products.ERP5Type.ERP5Type \
import ERP5TYPE_SECURITY_GROUP_ID_GENERATION_SCRIPT import ERP5TYPE_SECURITY_GROUP_ID_GENERATION_SCRIPT
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from Products.ZSQLCatalog.SQLCatalog import SimpleQuery from Products.ZSQLCatalog.SQLCatalog import SimpleQuery
from Products.PluggableAuthService.PropertiedUser import PropertiedUser
from ZODB.POSException import ConflictError from ZODB.POSException import ConflictError
import sys import sys
...@@ -130,7 +127,6 @@ class ERP5GroupManager(BasePlugin): ...@@ -130,7 +127,6 @@ class ERP5GroupManager(BasePlugin):
else: # no person is linked to this user login else: # no person is linked to this user login
return () return ()
person_object = catalog_result[0].getObject() person_object = catalog_result[0].getObject()
person_id = person_object.getId()
# Fetch category values from defined scripts # Fetch category values from defined scripts
for (method_name, base_category_list) in security_definition_list: for (method_name, base_category_list) in security_definition_list:
......
...@@ -35,9 +35,6 @@ from Products.ERP5Type.Globals import InitializeClass ...@@ -35,9 +35,6 @@ from Products.ERP5Type.Globals import InitializeClass
from zope.interface import Interface from zope.interface import Interface
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from AccessControl.SecurityManagement import getSecurityManager,\
newSecurityManager,\
setSecurityManager
from Products.PageTemplates.PageTemplateFile import PageTemplateFile from Products.PageTemplates.PageTemplateFile import PageTemplateFile
...@@ -49,8 +46,8 @@ from Products.PluggableAuthService.plugins.CookieAuthHelper import CookieAuthHel ...@@ -49,8 +46,8 @@ from Products.PluggableAuthService.plugins.CookieAuthHelper import CookieAuthHel
from Products.ERP5Type.Cache import CachingMethod from Products.ERP5Type.Cache import CachingMethod
from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
from Products.ERP5Security.ERP5UserManager import ERP5UserManager,\ from Products.ERP5Security.ERP5UserManager import ERP5UserManager, \
SUPER_USER,\ SUPER_USER, \
_AuthenticationFailure _AuthenticationFailure
from Crypto.Cipher import AES from Crypto.Cipher import AES
...@@ -136,22 +133,22 @@ manage_addERP5KeyAuthPluginForm = PageTemplateFile( ...@@ -136,22 +133,22 @@ manage_addERP5KeyAuthPluginForm = PageTemplateFile(
'www/ERP5Security_addERP5KeyAuthPlugin', globals(), 'www/ERP5Security_addERP5KeyAuthPlugin', globals(),
__name__='manage_addERP5KeyAuthPluginForm') __name__='manage_addERP5KeyAuthPluginForm')
def addERP5KeyAuthPlugin(dispatcher, id, title=None,\ def addERP5KeyAuthPlugin(dispatcher, id, title=None,
encryption_key='', cipher='AES', cookie_name='',\ encryption_key='', cipher='AES', cookie_name='',
default_cookie_name='',REQUEST=None): default_cookie_name='',REQUEST=None):
""" Add a ERP5KeyAuthPlugin to a Pluggable Auth Service. """ """ Add a ERP5KeyAuthPlugin to a Pluggable Auth Service. """
plugin = ERP5KeyAuthPlugin(id=id, title=title, encryption_key=encryption_key, plugin = ERP5KeyAuthPlugin(id=id, title=title, encryption_key=encryption_key,
cipher=cipher, cookie_name=cookie_name, cipher=cipher, cookie_name=cookie_name,
default_cookie_name=default_cookie_name) default_cookie_name=default_cookie_name)
dispatcher._setObject(plugin.getId(), plugin) dispatcher._setObject(plugin.getId(), plugin)
if REQUEST is not None: if REQUEST is not None:
REQUEST['RESPONSE'].redirect( REQUEST['RESPONSE'].redirect(
'%s/manage_workspace' '%s/manage_workspace'
'?manage_tabs_message=' '?manage_tabs_message='
'ERP5KeyAuthPlugin+added.' 'ERP5KeyAuthPlugin+added.'
% dispatcher.absolute_url()) % dispatcher.absolute_url())
class ERP5KeyAuthPlugin(ERP5UserManager, CookieAuthHelper): class ERP5KeyAuthPlugin(ERP5UserManager, CookieAuthHelper):
""" """
...@@ -277,9 +274,9 @@ class ERP5KeyAuthPlugin(ERP5UserManager, CookieAuthHelper): ...@@ -277,9 +274,9 @@ class ERP5KeyAuthPlugin(ERP5UserManager, CookieAuthHelper):
if creds: if creds:
creds['remote_host'] = request.get('REMOTE_HOST', '') creds['remote_host'] = request.get('REMOTE_HOST', '')
try: try:
creds['remote_address'] = request.getClientAddr() creds['remote_address'] = request.getClientAddr()
except AttributeError: except AttributeError:
creds['remote_address'] = request.get('REMOTE_ADDR', '') creds['remote_address'] = request.get('REMOTE_ADDR', '')
except StandardError, e: except StandardError, e:
#Log standard error to check error #Log standard error to check error
LOG('ERP5KeyAuthPlugin.extractCredentials', PROBLEM, str(e)) LOG('ERP5KeyAuthPlugin.extractCredentials', PROBLEM, str(e))
...@@ -373,14 +370,13 @@ class ERP5KeyAuthPlugin(ERP5UserManager, CookieAuthHelper): ...@@ -373,14 +370,13 @@ class ERP5KeyAuthPlugin(ERP5UserManager, CookieAuthHelper):
id='ERP5KeyAuthPlugin_authenticateCredentials', id='ERP5KeyAuthPlugin_authenticateCredentials',
cache_factory='erp5_content_short') cache_factory='erp5_content_short')
try: try:
return _authenticateCredentials( return _authenticateCredentials(login=login)
login=login)
except _AuthenticationFailure: except _AuthenticationFailure:
return None return None
except StandardError, e: except StandardError, e:
#Log standard error #Log standard error
LOG('ERP5KeyAuthPlugin.authenticateCredentials', PROBLEM, str(e)) LOG('ERP5KeyAuthPlugin.authenticateCredentials', PROBLEM, str(e))
return None return None
################################ ################################
# Properties for ZMI managment # # Properties for ZMI managment #
...@@ -429,8 +425,8 @@ class ERP5KeyAuthPlugin(ERP5UserManager, CookieAuthHelper): ...@@ -429,8 +425,8 @@ class ERP5KeyAuthPlugin(ERP5UserManager, CookieAuthHelper):
#Redirect #Redirect
if RESPONSE is not None: if RESPONSE is not None:
if error_message != '': if error_message != '':
self.REQUEST.form['manage_tabs_message'] = error_message self.REQUEST.form['manage_tabs_message'] = error_message
return self.manage_editERP5KeyAuthPluginForm(RESPONSE) return self.manage_editERP5KeyAuthPluginForm(RESPONSE)
else: else:
message = "Updated" message = "Updated"
RESPONSE.redirect( '%s/manage_editERP5KeyAuthPluginForm' RESPONSE.redirect( '%s/manage_editERP5KeyAuthPluginForm'
......
...@@ -20,60 +20,60 @@ from AccessControl import ClassSecurityInfo ...@@ -20,60 +20,60 @@ from AccessControl import ClassSecurityInfo
from Products.PageTemplates.PageTemplateFile import PageTemplateFile from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
from Products.PluggableAuthService.utils import classImplements from Products.PluggableAuthService.utils import classImplements
from Products.PluggableAuthService.interfaces.plugins import IRolesPlugin,\ from Products.PluggableAuthService.interfaces.plugins import IRolesPlugin, \
IRoleEnumerationPlugin IRoleEnumerationPlugin
from ERP5UserManager import SUPER_USER from ERP5UserManager import SUPER_USER
manage_addERP5RoleManagerForm = PageTemplateFile( manage_addERP5RoleManagerForm = PageTemplateFile(
'www/ERP5Security_addERP5RoleManager', globals(), 'www/ERP5Security_addERP5RoleManager', globals(),
__name__='manage_addERP5RoleManagerForm' ) __name__='manage_addERP5RoleManagerForm' )
def addERP5RoleManager( dispatcher, id, title=None, REQUEST=None ): def addERP5RoleManager( dispatcher, id, title=None, REQUEST=None ):
""" Add a ERP5RoleManager to a Pluggable Auth Service. """ """ Add a ERP5RoleManager to a Pluggable Auth Service. """
erm = ERP5RoleManager(id, title) erm = ERP5RoleManager(id, title)
dispatcher._setObject(erm.getId(), erm) dispatcher._setObject(erm.getId(), erm)
if REQUEST is not None: if REQUEST is not None:
REQUEST['RESPONSE'].redirect( REQUEST['RESPONSE'].redirect(
'%s/manage_workspace' '%s/manage_workspace'
'?manage_tabs_message=' '?manage_tabs_message='
'ERP5RoleManager+added.' 'ERP5RoleManager+added.'
% dispatcher.absolute_url()) % dispatcher.absolute_url())
class ERP5RoleManager( BasePlugin ): class ERP5RoleManager( BasePlugin ):
""" PAS plugin to add 'Member' as default """ PAS plugin to add 'Member' as default
Role for every user. Role for every user.
"""
meta_type = 'ERP5 Role Manager'
security = ClassSecurityInfo()
def __init__(self, id, title=None):
self._id = self.id = id
self.title = title
#
# IRolesPlugin implementation
#
security.declarePrivate( 'getRolesForPrincipal' )
def getRolesForPrincipal( self, principal, request=None ):
""" See IRolesPlugin.
We only ever return Member for every principal
""" """
meta_type = 'ERP5 Role Manager' if principal.getId() == SUPER_USER:
# If this is the super user, give all the roles present in this system.
security = ClassSecurityInfo() # XXX no API to do this in PAS.
rolemakers = self._getPAS().plugins.listPlugins( IRoleEnumerationPlugin )
def __init__(self, id, title=None): roles = []
for rolemaker_id, rolemaker in rolemakers:
self._id = self.id = id roles.extend([role['id'] for role in rolemaker.enumerateRoles()])
self.title = title return tuple(roles)
# return ('Member',)
# IRolesPlugin implementation
#
security.declarePrivate( 'getRolesForPrincipal' )
def getRolesForPrincipal( self, principal, request=None ):
""" See IRolesPlugin.
We only ever return Member for every principal
"""
if principal.getId() == SUPER_USER:
# If this is the super user, give all the roles present in this system.
# XXX no API to do this in PAS.
rolemakers = self._getPAS().plugins.listPlugins( IRoleEnumerationPlugin )
roles = []
for rolemaker_id, rolemaker in rolemakers:
roles.extend([role['id'] for role in rolemaker.enumerateRoles()])
return tuple(roles)
return ('Member',)
classImplements( ERP5RoleManager classImplements( ERP5RoleManager
, IRolesPlugin , IRolesPlugin
......
...@@ -61,7 +61,7 @@ class ERP5User(PropertiedUser): ...@@ -61,7 +61,7 @@ class ERP5User(PropertiedUser):
principal_ids = list( group_ids ) principal_ids = list( group_ids )
principal_ids.insert( 0, user_id ) principal_ids.insert( 0, user_id )
local ={} local = {}
object = aq_inner( object ) object = aq_inner( object )
while 1: while 1:
...@@ -98,102 +98,102 @@ class ERP5User(PropertiedUser): ...@@ -98,102 +98,102 @@ class ERP5User(PropertiedUser):
return list( self.getRoles() ) + local.keys() return list( self.getRoles() ) + local.keys()
def allowed( self, object, object_roles=None ): def allowed( self, object, object_roles=None ):
""" Check whether the user has access to object. """ Check whether the user has access to object.
As for getRolesInContext, we take into account _getAcquireLocalRoles for As for getRolesInContext, we take into account _getAcquireLocalRoles for
ERP5. ERP5.
""" """
if self.getUserName() == SUPER_USER: if self.getUserName() == SUPER_USER:
# super user is allowed to accesss any object # super user is allowed to accesss any object
return 1 return 1
if object_roles is _what_not_even_god_should_do: if object_roles is _what_not_even_god_should_do:
return 0 return 0
# Short-circuit the common case of anonymous access.
if object_roles is None or 'Anonymous' in object_roles:
return 1
# Check for Developer Role, see patches.User for rationale
# XXX-arnau: copy/paste
object_roles = set(object_roles)
if 'Developer' in object_roles:
object_roles.remove('Developer')
product_config = getattr(getConfiguration(), 'product_config', None)
if product_config:
config = product_config.get('erp5')
if config and self.getId() in config.developer_list:
return 1
# Short-circuit the common case of anonymous access. # Provide short-cut access if object is protected by 'Authenticated'
# role and user is not nobody
if 'Authenticated' in object_roles and (
self.getUserName() != 'Anonymous User'):
return 1
# Check for ancient role data up front, convert if found.
# This should almost never happen, and should probably be
# deprecated at some point.
if 'Shared' in object_roles:
object_roles = self._shared_roles(object)
if object_roles is None or 'Anonymous' in object_roles: if object_roles is None or 'Anonymous' in object_roles:
return 1 return 1
# Check for Developer Role, see patches.User for rationale # Check for a role match with the normal roles given to
# XXX-arnau: copy/paste # the user, then with local roles only if necessary. We
object_roles = set(object_roles) # want to avoid as much overhead as possible.
if 'Developer' in object_roles: user_roles = self.getRoles()
object_roles.remove('Developer') for role in object_roles:
product_config = getattr(getConfiguration(), 'product_config', None) if role in user_roles:
if product_config: if self._check_context(object):
config = product_config.get('erp5')
if config and self.getId() in config.developer_list:
return 1
# Provide short-cut access if object is protected by 'Authenticated'
# role and user is not nobody
if 'Authenticated' in object_roles and (
self.getUserName() != 'Anonymous User'):
return 1
# Check for ancient role data up front, convert if found.
# This should almost never happen, and should probably be
# deprecated at some point.
if 'Shared' in object_roles:
object_roles = self._shared_roles(object)
if object_roles is None or 'Anonymous' in object_roles:
return 1 return 1
return None
# Still have not found a match, so check local roles. We do
# this manually rather than call getRolesInContext so that
# we can incur only the overhead required to find a match.
inner_obj = aq_inner( object )
user_id = self.getId()
# [ x.getId() for x in self.getGroups() ]
group_ids = self.getGroups()
principal_ids = list( group_ids )
principal_ids.insert( 0, user_id )
while 1:
local_roles = getattr( inner_obj, '__ac_local_roles__', None )
if local_roles:
if callable( local_roles ):
local_roles = local_roles()
dict = local_roles or {}
for principal_id in principal_ids:
local_roles = dict.get( principal_id, [] )
for role in object_roles:
if role in local_roles:
if self._check_context( object ):
return 1
return 0
# patch by Klaus for LocalRole blocking
if getattr(inner_obj, '_getAcquireLocalRoles', None) is not None:
if not inner_obj._getAcquireLocalRoles():
break
inner = aq_inner( inner_obj )
parent = aq_parent( inner )
if parent is not None:
inner_obj = parent
continue
new = getattr( inner_obj, 'im_self', None )
if new is not None:
inner_obj = aq_inner( new )
continue
break
# Check for a role match with the normal roles given to return None
# the user, then with local roles only if necessary. We
# want to avoid as much overhead as possible.
user_roles = self.getRoles()
for role in object_roles:
if role in user_roles:
if self._check_context(object):
return 1
return None
# Still have not found a match, so check local roles. We do
# this manually rather than call getRolesInContext so that
# we can incur only the overhead required to find a match.
inner_obj = aq_inner( object )
user_id = self.getId()
# [ x.getId() for x in self.getGroups() ]
group_ids = self.getGroups()
principal_ids = list( group_ids )
principal_ids.insert( 0, user_id )
while 1:
local_roles = getattr( inner_obj, '__ac_local_roles__', None )
if local_roles:
if callable( local_roles ):
local_roles = local_roles()
dict = local_roles or {}
for principal_id in principal_ids:
local_roles = dict.get( principal_id, [] )
for role in object_roles:
if role in local_roles:
if self._check_context( object ):
return 1
return 0
# patch by Klaus for LocalRole blocking
if getattr(inner_obj, '_getAcquireLocalRoles', None) is not None:
if not inner_obj._getAcquireLocalRoles():
break
inner = aq_inner( inner_obj )
parent = aq_parent( inner )
if parent is not None:
inner_obj = parent
continue
new = getattr( inner_obj, 'im_self', None )
if new is not None:
inner_obj = aq_inner( new )
continue
break
return None
InitializeClass(ERP5User) InitializeClass(ERP5User)
......
...@@ -38,8 +38,8 @@ from zLOG import LOG, PROBLEM ...@@ -38,8 +38,8 @@ from zLOG import LOG, PROBLEM
SUPER_USER = '__erp5security-=__' SUPER_USER = '__erp5security-=__'
manage_addERP5UserManagerForm = PageTemplateFile( manage_addERP5UserManagerForm = PageTemplateFile(
'www/ERP5Security_addERP5UserManager', globals(), 'www/ERP5Security_addERP5UserManager', globals(),
__name__='manage_addERP5UserManagerForm' ) __name__='manage_addERP5UserManagerForm' )
def addERP5UserManager(dispatcher, id, title=None, REQUEST=None): def addERP5UserManager(dispatcher, id, title=None, REQUEST=None):
""" Add a ERP5UserManager to a Pluggable Auth Service. """ """ Add a ERP5UserManager to a Pluggable Auth Service. """
...@@ -48,11 +48,11 @@ def addERP5UserManager(dispatcher, id, title=None, REQUEST=None): ...@@ -48,11 +48,11 @@ def addERP5UserManager(dispatcher, id, title=None, REQUEST=None):
dispatcher._setObject(eum.getId(), eum) dispatcher._setObject(eum.getId(), eum)
if REQUEST is not None: if REQUEST is not None:
REQUEST['RESPONSE'].redirect( REQUEST['RESPONSE'].redirect(
'%s/manage_workspace' '%s/manage_workspace'
'?manage_tabs_message=' '?manage_tabs_message='
'ERP5UserManager+added.' 'ERP5UserManager+added.'
% dispatcher.absolute_url()) % dispatcher.absolute_url())
class _AuthenticationFailure(Exception): class _AuthenticationFailure(Exception):
"""Raised when authentication failed, to prevent caching the fact that a user """Raised when authentication failed, to prevent caching the fact that a user
...@@ -72,9 +72,9 @@ def getUserByLogin(portal, login, exact_match=True): ...@@ -72,9 +72,9 @@ def getUserByLogin(portal, login, exact_match=True):
if not (portal.portal_catalog.hasColumn('portal_type') and portal.portal_catalog.hasColumn('reference')): if not (portal.portal_catalog.hasColumn('portal_type') and portal.portal_catalog.hasColumn('reference')):
raise RuntimeError('Catalog does not have column information. Make sure RDB is working and disk is not full.') raise RuntimeError('Catalog does not have column information. Make sure RDB is working and disk is not full.')
result = portal.portal_catalog.unrestrictedSearchResults( result = portal.portal_catalog.unrestrictedSearchResults(
select_expression='reference', select_expression='reference',
portal_type="Person", portal_type="Person",
reference=dict(query=login, key=reference_key)) reference=dict(query=login, key=reference_key))
# XXX: Here, we filter catalog result list ALTHOUGH we did pass # XXX: Here, we filter catalog result list ALTHOUGH we did pass
# parameters to unrestrictedSearchResults to restrict result set. # parameters to unrestrictedSearchResults to restrict result set.
# This is done because the following values can match person with # This is done because the following values can match person with
...@@ -95,180 +95,181 @@ def getUserByLogin(portal, login, exact_match=True): ...@@ -95,180 +95,181 @@ def getUserByLogin(portal, login, exact_match=True):
class ERP5UserManager(BasePlugin): class ERP5UserManager(BasePlugin):
""" PAS plugin for managing users in ERP5 """ PAS plugin for managing users in ERP5
""" """
meta_type = 'ERP5 User Manager'
security = ClassSecurityInfo()
def __init__(self, id, title=None):
meta_type = 'ERP5 User Manager' self._id = self.id = id
self.title = title
security = ClassSecurityInfo()
#
def __init__(self, id, title=None): # IAuthenticationPlugin implementation
#
self._id = self.id = id security.declarePrivate( 'authenticateCredentials' )
self.title = title def authenticateCredentials(self, credentials):
""" See IAuthenticationPlugin.
#
# IAuthenticationPlugin implementation o We expect the credentials to be those returned by
# ILoginPasswordExtractionPlugin.
security.declarePrivate( 'authenticateCredentials' ) """
def authenticateCredentials(self, credentials): login = credentials.get('login')
""" See IAuthenticationPlugin. ignore_password = False
if not login:
o We expect the credentials to be those returned by # fallback to support plugins using external tools to extract login
ILoginPasswordExtractionPlugin. # those are not using login/password pair, they just extract login
""" # from remote system (eg. SSL certificates)
login = credentials.get('login') login = credentials.get('external_login')
ignore_password = False ignore_password = True
if not login: # Forbidden the usage of the super user.
# fallback to support plugins using external tools to extract login if login == SUPER_USER:
# those are not using login/password pair, they just extract login return None
# from remote system (eg. SSL certificates)
login = credentials.get('external_login') @UnrestrictedMethod
ignore_password = True def _authenticateCredentials(login, password, path,
# Forbidden the usage of the super user. ignore_password=False):
if login == SUPER_USER: if not login or not (password or ignore_password):
return None return None
@UnrestrictedMethod user_list = self.getUserByLogin(login)
def _authenticateCredentials(login, password, path,
ignore_password=False): if not user_list:
if not login or not (password or ignore_password): raise _AuthenticationFailure()
return None
user = user_list[0]
user_list = self.getUserByLogin(login)
try:
if not user_list: # get assignment
raise _AuthenticationFailure() assignment_list = [x for x in user.contentValues(portal_type="Assignment") if x.getValidationState() == "open"]
valid_assignment_list = []
user = user_list[0] # check dates if exist
login_date = DateTime()
try: for assignment in assignment_list:
# get assignment if assignment.getStartDate() is not None and \
assignment_list = [x for x in user.contentValues(portal_type="Assignment") if x.getValidationState() == "open"] assignment.getStartDate() > login_date:
valid_assignment_list = [] continue
# check dates if exist if assignment.hasStopDate() and \
login_date = DateTime() assignment.getStopDate() < login_date:
for assignment in assignment_list: continue
if assignment.getStartDate() is not None and \ valid_assignment_list.append(assignment)
assignment.getStartDate() > login_date:
continue if (ignore_password or pw_validate(user.getPassword(), password)) and \
if assignment.hasStopDate() and \ len(valid_assignment_list) and user \
assignment.getStopDate() < login_date: .getValidationState() != 'deleted': #user.getCareerRole() == 'internal':
continue return login, login # use same for user_id and login
valid_assignment_list.append(assignment) finally:
pass
if (ignore_password or pw_validate(user.getPassword(), password)) and \ raise _AuthenticationFailure()
len(valid_assignment_list) and user \
.getValidationState() != 'deleted': #user.getCareerRole() == 'internal': _authenticateCredentials = CachingMethod(
return login, login # use same for user_id and login _authenticateCredentials,
finally: id='ERP5UserManager_authenticateCredentials',
pass cache_factory='erp5_content_short')
raise _AuthenticationFailure() try:
authentication_result = _authenticateCredentials(
_authenticateCredentials = CachingMethod(_authenticateCredentials, login=login,
id='ERP5UserManager_authenticateCredentials', password=credentials.get('password'),
cache_factory='erp5_content_short') path=self.getPhysicalPath(),
try: ignore_password=ignore_password)
authentication_result = _authenticateCredentials(
login=login, except _AuthenticationFailure:
password=credentials.get('password'), authentication_result = None
path=self.getPhysicalPath(),
ignore_password=ignore_password) if not self.getPortalObject().portal_preferences.isAuthenticationPolicyEnabled():
# stop here, no authentication policy enabled
except _AuthenticationFailure: # so just return authentication check result
authentication_result = None return authentication_result
if not self.getPortalObject().portal_preferences.isAuthenticationPolicyEnabled(): # authentication policy enabled, we need person object anyway
# stop here, no authentication policy enabled user_list = self.getUserByLogin(credentials.get('login'))
# so just return authentication check result if not user_list:
return authentication_result # not an ERP5 Person object
return None
# authentication policy enabled, we need person object anyway user = user_list[0]
user_list = self.getUserByLogin(credentials.get('login'))
if not user_list: if authentication_result is None:
# not an ERP5 Person object # file a failed authentication attempt
return None user.notifyLoginFailure()
user = user_list[0] return None
if authentication_result is None: # check if password is expired
# file a failed authentication attempt if user.isPasswordExpired():
user.notifyLoginFailure() user.notifyPasswordExpire()
return None return None
# check if password is expired # check if user account is blocked
if user.isPasswordExpired(): if user.isLoginBlocked():
user.notifyPasswordExpire() return None
return None
return authentication_result
# check if user account is blocked
if user.isLoginBlocked(): #
return None # IUserEnumerationPlugin implementation
#
return authentication_result security.declarePrivate( 'enumerateUsers' )
def enumerateUsers(self, id=None, login=None, exact_match=False,
# sort_by=None, max_results=None, **kw):
# IUserEnumerationPlugin implementation """ See IUserEnumerationPlugin.
# """
security.declarePrivate( 'enumerateUsers' ) if id is None:
def enumerateUsers(self, id=None, login=None, exact_match=False, id = login
sort_by=None, max_results=None, **kw): if isinstance(id, str):
""" See IUserEnumerationPlugin. id = (id,)
""" if isinstance(id, list):
if id is None: id = tuple(id)
id = login
if isinstance(id, str): user_info = []
id = (id,) plugin_id = self.getId()
if isinstance(id, list):
id = tuple(id) id_list = []
for user_id in id:
user_info = [] if SUPER_USER == user_id:
plugin_id = self.getId() info = { 'id' : SUPER_USER
, 'login' : SUPER_USER
id_list = [] , 'pluginid' : plugin_id
for user_id in id: }
if SUPER_USER == user_id: user_info.append(info)
info = { 'id' : SUPER_USER else:
, 'login' : SUPER_USER id_list.append(user_id)
, 'pluginid' : plugin_id
} if id_list:
user_info.append(info) for user in self.getUserByLogin(tuple(id_list), exact_match=exact_match):
else: info = { 'id' : user.getReference()
id_list.append(user_id) , 'login' : user.getReference()
, 'pluginid' : plugin_id
if id_list: }
for user in self.getUserByLogin(tuple(id_list), exact_match=exact_match):
info = { 'id' : user.getReference() user_info.append(info)
, 'login' : user.getReference()
, 'pluginid' : plugin_id return tuple(user_info)
}
def getUserByLogin(self, login, exact_match=True):
user_info.append(info) # Search the Catalog for login and return a list of person objects
# login can be a string or a list of strings
return tuple(user_info) # (no docstring to prevent publishing)
if not login:
def getUserByLogin(self, login, exact_match=True): return []
# Search the Catalog for login and return a list of person objects if isinstance(login, list):
# login can be a string or a list of strings login = tuple(login)
# (no docstring to prevent publishing) elif not isinstance(login, tuple):
if not login: login = str(login)
return [] try:
if isinstance(login, list): return getUserByLogin(self.getPortalObject(), login, exact_match)
login = tuple(login) except ConflictError:
elif not isinstance(login, tuple): raise
login = str(login) except:
try: LOG('ERP5Security', PROBLEM, 'getUserByLogin failed', error=sys.exc_info())
return getUserByLogin(self.getPortalObject(), login, exact_match) # Here we must raise an exception to prevent callers from caching
except ConflictError: # a result of a degraded situation.
raise # The kind of exception does not matter as long as it's catched by
except: # PAS and causes a lookup using another plugin or user folder.
LOG('ERP5Security', PROBLEM, 'getUserByLogin failed', error=sys.exc_info()) # As PAS does not define explicitely such exception, we must use
# Here we must raise an exception to prevent callers from caching # the _SWALLOWABLE_PLUGIN_EXCEPTIONS list.
# a result of a degraded situation. raise _SWALLOWABLE_PLUGIN_EXCEPTIONS[0]
# The kind of exception does not matter as long as it's catched by
# PAS and causes a lookup using another plugin or user folder.
# As PAS does not define explicitely such exception, we must use
# the _SWALLOWABLE_PLUGIN_EXCEPTIONS list.
raise _SWALLOWABLE_PLUGIN_EXCEPTIONS[0]
classImplements( ERP5UserManager classImplements( ERP5UserManager
......
...@@ -74,104 +74,104 @@ registerMultiPlugin(ERP5DumbHTTPExtractionPlugin.ERP5DumbHTTPExtractionPlugin.me ...@@ -74,104 +74,104 @@ registerMultiPlugin(ERP5DumbHTTPExtractionPlugin.ERP5DumbHTTPExtractionPlugin.me
def initialize(context): def initialize(context):
context.registerClass( ERP5UserManager.ERP5UserManager context.registerClass( ERP5UserManager.ERP5UserManager
, permission=ManageUsers , permission=ManageUsers
, constructors=( , constructors=(
ERP5UserManager.manage_addERP5UserManagerForm, ERP5UserManager.manage_addERP5UserManagerForm,
ERP5UserManager.addERP5UserManager, ) ERP5UserManager.addERP5UserManager, )
, visibility=None , visibility=None
, icon='www/portal.gif' , icon='www/portal.gif'
) )
context.registerClass( ERP5GroupManager.ERP5GroupManager context.registerClass( ERP5GroupManager.ERP5GroupManager
, permission=ManageGroups , permission=ManageGroups
, constructors=( , constructors=(
ERP5GroupManager.manage_addERP5GroupManagerForm, ERP5GroupManager.manage_addERP5GroupManagerForm,
ERP5GroupManager.addERP5GroupManager, ) ERP5GroupManager.addERP5GroupManager, )
, visibility=None , visibility=None
, icon='www/portal.gif' , icon='www/portal.gif'
) )
context.registerClass( ERP5RoleManager.ERP5RoleManager context.registerClass( ERP5RoleManager.ERP5RoleManager
, permission=ManageUsers , permission=ManageUsers
, constructors=( , constructors=(
ERP5RoleManager.manage_addERP5RoleManagerForm, ERP5RoleManager.manage_addERP5RoleManagerForm,
ERP5RoleManager.addERP5RoleManager, ) ERP5RoleManager.addERP5RoleManager, )
, visibility=None , visibility=None
, icon='www/portal.gif' , icon='www/portal.gif'
) )
context.registerClass( ERP5UserFactory.ERP5UserFactory context.registerClass( ERP5UserFactory.ERP5UserFactory
, permission=ManageUsers , permission=ManageUsers
, constructors=( , constructors=(
ERP5UserFactory.manage_addERP5UserFactoryForm, ERP5UserFactory.manage_addERP5UserFactoryForm,
ERP5UserFactory.addERP5UserFactory, ) ERP5UserFactory.addERP5UserFactory, )
, visibility=None , visibility=None
, icon='www/portal.gif' , icon='www/portal.gif'
) )
context.registerClass( ERP5KeyAuthPlugin.ERP5KeyAuthPlugin context.registerClass( ERP5KeyAuthPlugin.ERP5KeyAuthPlugin
, permission=ManageUsers , permission=ManageUsers
, constructors=( , constructors=(
ERP5KeyAuthPlugin.manage_addERP5KeyAuthPluginForm, ERP5KeyAuthPlugin.manage_addERP5KeyAuthPluginForm,
ERP5KeyAuthPlugin.addERP5KeyAuthPlugin, ) ERP5KeyAuthPlugin.addERP5KeyAuthPlugin, )
, visibility=None , visibility=None
, icon='www/portal.gif' , icon='www/portal.gif'
) )
context.registerClass( ERP5ExternalAuthenticationPlugin.ERP5ExternalAuthenticationPlugin context.registerClass( ERP5ExternalAuthenticationPlugin.ERP5ExternalAuthenticationPlugin
, permission=ManageUsers , permission=ManageUsers
, constructors=( , constructors=(
ERP5ExternalAuthenticationPlugin.manage_addERP5ExternalAuthenticationPluginForm, ERP5ExternalAuthenticationPlugin.manage_addERP5ExternalAuthenticationPluginForm,
ERP5ExternalAuthenticationPlugin.addERP5ExternalAuthenticationPlugin, ) ERP5ExternalAuthenticationPlugin.addERP5ExternalAuthenticationPlugin, )
, visibility=None , visibility=None
, icon='www/portal.gif' , icon='www/portal.gif'
) )
context.registerClass( ERP5BearerExtractionPlugin.ERP5BearerExtractionPlugin context.registerClass( ERP5BearerExtractionPlugin.ERP5BearerExtractionPlugin
, permission=ManageUsers , permission=ManageUsers
, constructors=( , constructors=(
ERP5BearerExtractionPlugin.manage_addERP5BearerExtractionPluginForm, ERP5BearerExtractionPlugin.manage_addERP5BearerExtractionPluginForm,
ERP5BearerExtractionPlugin.addERP5BearerExtractionPlugin, ) ERP5BearerExtractionPlugin.addERP5BearerExtractionPlugin, )
, visibility=None , visibility=None
, icon='www/portal.gif' , icon='www/portal.gif'
) )
context.registerClass( ERP5ExternalOauth2ExtractionPlugin.ERP5FacebookExtractionPlugin context.registerClass( ERP5ExternalOauth2ExtractionPlugin.ERP5FacebookExtractionPlugin
, permission=ManageUsers , permission=ManageUsers
, constructors=( , constructors=(
ERP5ExternalOauth2ExtractionPlugin.manage_addERP5FacebookExtractionPluginForm, ERP5ExternalOauth2ExtractionPlugin.manage_addERP5FacebookExtractionPluginForm,
ERP5ExternalOauth2ExtractionPlugin.addERP5FacebookExtractionPlugin, ) ERP5ExternalOauth2ExtractionPlugin.addERP5FacebookExtractionPlugin, )
, visibility=None , visibility=None
, icon='www/portal.gif' , icon='www/portal.gif'
) )
context.registerClass( ERP5ExternalOauth2ExtractionPlugin.ERP5GoogleExtractionPlugin context.registerClass( ERP5ExternalOauth2ExtractionPlugin.ERP5GoogleExtractionPlugin
, permission=ManageUsers , permission=ManageUsers
, constructors=( , constructors=(
ERP5ExternalOauth2ExtractionPlugin.manage_addERP5GoogleExtractionPluginForm, ERP5ExternalOauth2ExtractionPlugin.manage_addERP5GoogleExtractionPluginForm,
ERP5ExternalOauth2ExtractionPlugin.addERP5GoogleExtractionPlugin, ) ERP5ExternalOauth2ExtractionPlugin.addERP5GoogleExtractionPlugin, )
, visibility=None , visibility=None
, icon='www/portal.gif' , icon='www/portal.gif'
) )
context.registerClass( ERP5AccessTokenExtractionPlugin.ERP5AccessTokenExtractionPlugin context.registerClass( ERP5AccessTokenExtractionPlugin.ERP5AccessTokenExtractionPlugin
, permission=ManageUsers , permission=ManageUsers
, constructors=( , constructors=(
ERP5AccessTokenExtractionPlugin.manage_addERP5AccessTokenExtractionPluginForm, ERP5AccessTokenExtractionPlugin.manage_addERP5AccessTokenExtractionPluginForm,
ERP5AccessTokenExtractionPlugin.addERP5AccessTokenExtractionPlugin, ) ERP5AccessTokenExtractionPlugin.addERP5AccessTokenExtractionPlugin, )
, visibility=None , visibility=None
, icon='www/portal.gif' , icon='www/portal.gif'
) )
context.registerClass( ERP5DumbHTTPExtractionPlugin.ERP5DumbHTTPExtractionPlugin context.registerClass( ERP5DumbHTTPExtractionPlugin.ERP5DumbHTTPExtractionPlugin
, permission=ManageUsers , permission=ManageUsers
, constructors=( , constructors=(
ERP5DumbHTTPExtractionPlugin.manage_addERP5DumbHTTPExtractionPluginForm, ERP5DumbHTTPExtractionPlugin.manage_addERP5DumbHTTPExtractionPluginForm,
ERP5DumbHTTPExtractionPlugin.addERP5DumbHTTPExtractionPlugin, ) ERP5DumbHTTPExtractionPlugin.addERP5DumbHTTPExtractionPlugin, )
, visibility=None , visibility=None
, icon='www/portal.gif' , icon='www/portal.gif'
) )
from AccessControl.SecurityInfo import ModuleSecurityInfo from AccessControl.SecurityInfo import ModuleSecurityInfo
ModuleSecurityInfo('Products.ERP5Security.ERP5UserManager').declarePublic( ModuleSecurityInfo('Products.ERP5Security.ERP5UserManager').declarePublic(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment