This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
mandaye/mandaye/backends/ldap_back.py

156 lines
6.7 KiB
Python
Raw Normal View History

import json
import ldap
import ldap.modlist
import random
from datetime import datetime
from mandaye import config
from mandaye.log import logger
from mandaye.backends.default import storage_conn
def cmp_reverse_last_connection_date(x, y):
return -cmp(x[1]['lastConnectionDate'][0], y[1]['lastConnectionDate'][0])
class Association(object):
"""
association dictionary return by the following methods:
{
'id': '', # identifier of your association (must be unique)
'sp_name': '', # name of the service provider (defined in the mappers)
'sp_login': '', # login on the service provider
'sp_post_values': '', # the post values for sp login form
'idp_unique_id:': '', # the unique identifier of the identity provider (ex.: a saml NameID)
'idp_name': '', # identity provide name
'last_connection': datetime.datetime, # last connection with this association
'creation_date': datetime.datetime, # creation date of this association
}
"""
@staticmethod
def ldap2association(ldap_object):
return {
'id': ldap_object['uniqueID'][0],
'sp_name': ldap_object['spName'][0],
'sp_login': ldap_object['spLogin'][0],
'sp_post_values': json.loads(ldap_object['spPostValues'][0]),
'idp_unique_id': ldap_object['idpUniqueID'][0],
'idp_name': ldap_object['idpName'][0],
'last_connection': datetime.strptime(
ldap_object['lastConnectionDate'][0][:14],
'%Y%m%d%H%M%S'),
'creation_date': datetime.strptime(
ldap_object['creationDate'][0][:14],
'%Y%m%d%H%M%S'),
}
@staticmethod
def get(sp_name, idp_unique_id, idp_name='default'):
""" return a list of dict with associations matching all of this options """
associations = []
results = storage_conn.search_s(config.ldap_base_dn, ldap.SCOPE_ONELEVEL,
filterstr='(&(objectClass=MandayeUser)(spName=%s)(idpUniqueID=%s)(idpName=%s))' % (sp_name, idp_unique_id, idp_name))
for result in results:
associations.append(Association.ldap2association(result[1]))
return associations
@staticmethod
def get_by_id(asso_id):
2014-09-19 10:56:04 +02:00
""" return a dict of the association with the id or None if it doesn't exist """
results = storage_conn.search_s(config.ldap_base_dn, ldap.SCOPE_ONELEVEL,
filterstr='(&(objectClass=MandayeUser)(uniqueID=%s))' %\
(asso_id))
if results:
return Association.ldap2association(results[0][1])
return None
@staticmethod
def has_id(asso_id):
""" check the given user is present in the directory """
results = storage_conn.search_s(config.ldap_base_dn, ldap.SCOPE_ONELEVEL,
filterstr='(&(objectClass=MandayeUser)(uniqueID=%s))' %\
(asso_id))
if results:
return True
return False
@staticmethod
def update_or_create(sp_name, sp_login, sp_post_values, idp_unique_id,
idp_name='default', creation_date=None, last_connection_date=None):
""" update or create an associtaion which match the following values
return the association id
"""
results = storage_conn.search_s(config.ldap_base_dn, ldap.SCOPE_ONELEVEL,
filterstr='(&(objectClass=MandayeUser)(spName=%s)(spLogin=%s)(idpUniqueID=%s)(idpName=%s))' %\
(sp_name, sp_login, idp_unique_id, idp_name))
if not results:
creation_date = creation_date or datetime.utcnow()
last_connection_date = last_connection_date or datetime.utcnow()
association = {'spName': str(sp_name),
'spLogin': str(sp_login),
'spPostValues': json.dumps(sp_post_values),
'idpUniqueID': str(idp_unique_id),
'idpName': str(idp_name),
'creationDate': creation_date.strftime('%Y%m%d%H%M%SZ'),
'lastConnectionDate': last_connection_date.strftime('%Y%m%d%H%M%SZ'),
'objectClass': 'MandayeUser'
}
mod_list = ldap.modlist.addModlist(association)
while True:
unique_id = random.randint(1, 5000000)
dn = "uniqueID=%s,%s" % (unique_id, config.ldap_base_dn)
try:
result = storage_conn.add_s(dn, mod_list)
except ldap.ALREADY_EXISTS:
continue
break
logger.info("New association %r with %r", sp_login, idp_unique_id)
return unique_id
else:
results.sort(cmp_reverse_last_connection_date)
dn = results[0][0]
mod_list = [(ldap.MOD_REPLACE, 'spPostValues', json.dumps(sp_post_values))]
storage_conn.modify_s(dn, mod_list)
logger.info("Update post values for %r (%r)", sp_login, idp_unique_id)
return results[0][1]['uniqueID'][0]
@staticmethod
def delete(asso_id):
""" delete the association which has the following asso_id """
dn = "uniqueID=%s,%s" % (asso_id, config.ldap_base_dn)
storage_conn.delete_s(dn)
logger.info('Delete %r association', dn)
@staticmethod
def get_last_connected(sp_name, idp_unique_id, idp_name='default'):
""" get the last connecting association which match the parameters
return a dict of the association
"""
results = storage_conn.search_s(config.ldap_base_dn, ldap.SCOPE_ONELEVEL,
filterstr='(&(objectClass=MandayeUser)(spName=%s)(idpUniqueID=%s)(idpName=%s))' % (sp_name, idp_unique_id, idp_name))
if results:
results.sort(cmp_reverse_last_connection_date)
return Association.ldap2association(results[0][1])
return None
@staticmethod
def update_last_connection(asso_id):
""" update the association last connection time with the current time
return a dict of the association
"""
last_connection = datetime.utcnow().strftime("%Y%m%d%H%M%SZ")
dn = "uniqueID=%s,%s" % (asso_id, config.ldap_base_dn)
mod_list = [(ldap.MOD_REPLACE, 'lastConnectionDate', last_connection)]
storage_conn.modify_s(dn, mod_list)
@staticmethod
def has_sp_login(sp_login, sp_name):
results = storage_conn.search_s(config.ldap_base_dn, ldap.SCOPE_ONELEVEL,
filterstr='(&(objectClass=MandayeUser)(spName=%s)(spLogin=%s))' %\
(sp_name, sp_login))
if results:
return True
return False