2014-09-15 10:48:46 +02:00
|
|
|
|
2014-09-17 19:19:07 +02:00
|
|
|
import json
|
2014-09-15 10:48:46 +02:00
|
|
|
import ldap
|
|
|
|
import ldap.modlist
|
|
|
|
import random
|
|
|
|
|
2014-09-19 16:24:53 +02:00
|
|
|
from datetime import datetime
|
|
|
|
|
2014-09-15 10:48:46 +02:00
|
|
|
from mandaye import config
|
|
|
|
from mandaye.log import logger
|
|
|
|
from mandaye.backends.default import storage_conn
|
|
|
|
|
2014-11-21 14:43:37 +01:00
|
|
|
def cmp_reverse_last_connection_date(x, y):
|
|
|
|
return -cmp(x[1]['lastConnectionDate'][0], y[1]['lastConnectionDate'][0])
|
|
|
|
|
2014-09-15 10:48:46 +02:00
|
|
|
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],
|
2014-09-17 19:19:07 +02:00
|
|
|
'sp_post_values': json.loads(ldap_object['spPostValues'][0]),
|
2014-09-15 10:48:46 +02:00
|
|
|
'idp_unique_id': ldap_object['idpUniqueID'][0],
|
|
|
|
'idp_name': ldap_object['idpName'][0],
|
2014-09-19 16:24:53 +02:00
|
|
|
'last_connection': datetime.strptime(
|
2014-09-15 10:48:46 +02:00
|
|
|
ldap_object['lastConnectionDate'][0][:14],
|
|
|
|
'%Y%m%d%H%M%S'),
|
2014-09-19 16:24:53 +02:00
|
|
|
'creation_date': datetime.strptime(
|
2014-09-15 10:48:46 +02:00
|
|
|
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 """
|
2014-09-15 10:48:46 +02:00
|
|
|
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
|
2014-09-19 16:24:53 +02:00
|
|
|
def update_or_create(sp_name, sp_login, sp_post_values, idp_unique_id,
|
|
|
|
idp_name='default', creation_date=None, last_connection_date=None):
|
2014-09-15 10:48:46 +02:00
|
|
|
""" 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:
|
2014-09-19 16:24:53 +02:00
|
|
|
creation_date = creation_date or datetime.utcnow()
|
|
|
|
last_connection_date = last_connection_date or datetime.utcnow()
|
2014-09-17 19:19:07 +02:00
|
|
|
association = {'spName': str(sp_name),
|
|
|
|
'spLogin': str(sp_login),
|
|
|
|
'spPostValues': json.dumps(sp_post_values),
|
|
|
|
'idpUniqueID': str(idp_unique_id),
|
|
|
|
'idpName': str(idp_name),
|
2014-09-19 16:24:53 +02:00
|
|
|
'creationDate': creation_date.strftime('%Y%m%d%H%M%SZ'),
|
|
|
|
'lastConnectionDate': last_connection_date.strftime('%Y%m%d%H%M%SZ'),
|
2014-09-15 10:48:46 +02:00
|
|
|
'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:
|
2014-11-21 14:43:37 +01:00
|
|
|
results.sort(cmp_reverse_last_connection_date)
|
|
|
|
dn = results[0][0]
|
2014-09-17 19:19:07 +02:00
|
|
|
mod_list = [(ldap.MOD_REPLACE, 'spPostValues', json.dumps(sp_post_values))]
|
2014-09-15 10:48:46 +02:00
|
|
|
storage_conn.modify_s(dn, mod_list)
|
|
|
|
logger.info("Update post values for %r (%r)", sp_login, idp_unique_id)
|
2014-11-21 14:43:37 +01:00
|
|
|
return results[0][1]['uniqueID'][0]
|
2014-09-15 10:48:46 +02:00
|
|
|
|
|
|
|
@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:
|
2014-11-21 14:43:37 +01:00
|
|
|
results.sort(cmp_reverse_last_connection_date)
|
|
|
|
return Association.ldap2association(results[0][1])
|
2014-09-15 10:48:46 +02:00
|
|
|
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
|
|
|
|
"""
|
2014-09-19 16:24:53 +02:00
|
|
|
last_connection = datetime.utcnow().strftime("%Y%m%d%H%M%SZ")
|
2014-09-15 10:48:46 +02:00
|
|
|
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)
|
|
|
|
|
2015-01-21 17:05:09 +01:00
|
|
|
@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
|