[gen] Added the possiblity to synchronize external users from a LDAP.

This commit is contained in:
Gaetan Delannay 2014-12-17 16:19:45 +01:00
parent 6cd64fdc50
commit 865e6bf08e
4 changed files with 129 additions and 50 deletions

View file

@ -861,45 +861,6 @@ class ToolMixin(BaseMixin):
login = 'anon'
return login, password
def getLdapUser(self, login, password):
'''Returns a local User instance corresponding to a LDAP user if p_login
and p_password correspong to a valid LDAP user.'''
# Check if LDAP is configured
cfg = self.getProductConfig(True).ldap
if not cfg or not cfg.enabled: return
# Get a connector to the LDAP server and connect to the LDAP server
serverUri = cfg.getServerUri()
connector = LdapConnector(serverUri, tool=self)
success, msg = connector.connect(cfg.adminLogin, cfg.adminPassword)
if not success: return
# Check if the user corresponding to p_login exists in the LDAP.
filter = connector.getFilter(cfg.getUserFilterValues(login))
params = cfg.getUserAttributes()
ldapData = connector.search(cfg.baseDn, cfg.scope, filter, params)
if not ldapData: return
# The user exists. Try to connect to the LDAP with this user in order
# to validate its password.
userConnector = LdapConnector(serverUri, tool=self)
success, msg = userConnector.connect(ldapData[0][0], password)
if not success: return
# The password is correct. We can create/update our local user
# corresponding to this LDAP user.
userParams = cfg.getUserParams(ldapData[0][1])
tool = self.appy()
user = tool.search1('User', noSecurity=True, login=login)
if user:
# Update the user with fresh info about him from the LDAP
for name, value in userParams.iteritems():
setattr(user, name, value)
# Update user password
user.setPassword(password, log=False)
user.reindex()
else:
# Create the user
user = tool.create('users', noSecurity=True, login=login,
password1=password, source='ldap', **userParams)
return user
def getUser(self, authentify=False, source='zodb'):
'''Gets the current user. If p_authentify is True, in addition to
finding the logged user and returning it (=identification), we check
@ -928,7 +889,9 @@ class ToolMixin(BaseMixin):
user = tool.search1('User', noSecurity=True, login=login)
if user and (user.source != 'zodb'): user = None # Not a local one.
elif source == 'ldap':
user = self.getLdapUser(login, password)
user = None
cfg = self.getProductConfig(True).ldap
if cfg: user = cfg.getUser(self.appy(), login, password)
elif source == 'any':
# Get the user object, be it really local or a copy of a LDAP user.
user = tool.search1('User', noSecurity=True, login=login)

View file

@ -244,12 +244,12 @@ setattr(Page, Page.pages.back.attribute, Page.pages.back)
defaultToolFields = ('title', 'mailHost', 'mailEnabled', 'mailFrom',
'appyVersion', 'dateFormat', 'hourFormat',
'unoEnabledPython', 'openOfficePort',
'numberOfResultsPerPage', 'users', 'connectedUsers',
'groups', 'translations', 'loadTranslationsAtStartup',
'pages')
'numberOfResultsPerPage', 'users',
'connectedUsers', 'synchronizeExternalUsers', 'groups',
'translations', 'loadTranslationsAtStartup', 'pages')
class Tool(ModelClass):
# In a ModelClass we need to declare attributes in the following list.
# In a ModelClass we need to declare attributes in the following list
_appy_attributes = list(defaultToolFields)
folder = True
@ -269,16 +269,22 @@ class Tool(ModelClass):
openOfficePort = gen.Integer(default=2002, **lf)
numberOfResultsPerPage = gen.Integer(default=30, **lf)
# Ref(User) will maybe be transformed into Ref(CustomUserClass).
# Ref(User) will maybe be transformed into Ref(CustomUserClass)
userPage = gen.Page('users', show=isManager)
users = gen.Ref(User, multiplicity=(0,None), add=True, link=False,
back=gen.Ref(attribute='toTool', show=False), page=userPage,
queryable=True, queryFields=('title', 'login'),
show=isManager, showHeaders=True,
shownInfo=('title', 'login*120px', 'roles*120px'))
def computeConnectedUsers(self): pass
connectedUsers = gen.Computed(method=computeConnectedUsers, page=userPage,
plainText=False, show=isManager)
def doSynchronizeExternalUsers(self): pass
def showSynchronizeUsers(self): pass
synchronizeExternalUsers = gen.Action(action=doSynchronizeExternalUsers,
show=showSynchronizeUsers, confirm=True, page=userPage)
groups = gen.Ref(Group, multiplicity=(0,None), add=True, link=False,
back=gen.Ref(attribute='toTool2', show=False),
page=gen.Page('groups', show=isManager), show=isManager,

View file

@ -5,6 +5,7 @@ from appy.px import Px
from appy.gen.mail import sendMail
from appy.gen.wrappers import AbstractWrapper
from appy.shared.utils import executeCommand
from appy.shared.ldap_connector import LdapConnector
# ------------------------------------------------------------------------------
class ToolWrapper(AbstractWrapper):
@ -712,4 +713,17 @@ class ToolWrapper(AbstractWrapper):
def _login(self, login):
'''Performs a login programmatically. Used by the test system.'''
self.request.user = self.search1('User', noSecurity=True, login=login)
def doSynchronizeExternalUsers(self):
'''Synchronizes the local User copies with a distant LDAP user base.'''
cfg = self.o.getProductConfig(True).ldap
if not cfg: raise Exception('LDAP config not found.')
counts = cfg.synchronizeUsers(self)
msg = 'LDAP users: %d created, %d updated, %d untouched.' % counts
return True, msg
def showSynchronizeUsers(self):
'''Show this button only if a LDAP connection exists and is enabled.'''
cfg = self.o.getProductConfig(True).ldap
if cfg and cfg.enabled: return 'view'
# ------------------------------------------------------------------------------