3. Dump the output of new ident_value + barcode in CSV format somewhere.
"""
+import os
import sys
import ldap
import oils.utils.utils
import osrf.gateway
import osrf.json
+import osrf.net_obj
import tempfile
import urllib2
import credentials
+class User:
+ """
+ Holds data mapped from LDAP schema to Evergreen attributes
+
+ Less formal than an actual 'au' object
+ """
+
+ def __init__(self, raw_ldap):
+ """
+ Map core LDAP schema attributes to Evergreen user bits
+
+ Easier to replace hard-coded mappings with calls to functions
+ """
+
+ self.raw_ldap = raw_ldap
+
+ if 'mail' not in raw_ldap:
+ print >> sys.stderr, 'mail not found for %s' % raw_ldap['cn']
+ return None
+
+ # Strip leading/ending whitespace; LDAP data can be dirty
+
+ # Using email for username deliberately here
+ self.usrname = raw_ldap['mail'][0].strip().lower()
+ self.email = raw_ldap['mail'][0].strip().lower()
+ self.family_name = raw_ldap['sn'][0].strip()
+ self.ident_type, self.ident_value = self.get_identity()
+ self.home_ou = self.get_home_ou()
+
+ # Randomized password, assuming user will use "Forgot password"
+ # function to set their own password
+ self.passwd = oils.utils.utils.md5sum(os.urandom(10))
+
+ if 'givenName' in raw_ldap:
+ self.first_given_name = raw_ldap['givenName'][0].strip()
+ else:
+ self.first_given_name('LDAP_NULL')
+ print >> sys.stderr, 'No givenName for %s' % (self.usrname)
+
+ self.profile = self.get_profile()
+
+ def get_identity(self):
+ """
+ Map LDAP record to Evergreen identity type and value
+ """
+
+ ident_value = self.raw_ldap['lulColleagueId'][0].strip().lower()
+ if len(ident_value) != 7:
+ print >> sys.stderr, 'Datatel number not 7 chars for %s (%s)' % (
+ self.usrname, ident_value
+ )
+ if len(ident_value) == 6:
+ ident_value = '0%s' % ident_value
+ elif len(ident_value) == 5:
+ ident_value = '00%s' % ident_value
+
+ return 2, ident_value
+
+ def get_profile(self):
+ """
+ Map LDAP record to Evergreen profile
+ """
+
+ if 'lulStudentLevel' in self.raw_ldap:
+ affiliation = self.raw_ldap['lulStudentLevel'][0].strip().lower()
+ elif 'lulPrimaryAffiliation' in self.raw_ldap:
+ affiliation = self.raw_ldap['lulPrimaryAffiliation'][0].strip().lower()
+ else:
+ affiliation = r'\N'
+
+ if affiliation == 'ug' or affiliation == 'student':
+ return 13
+ elif affiliation == 'gr':
+ return 12
+ elif affiliation == 'al':
+ return 14
+ elif affiliation == 'faculty':
+ return 11
+ elif affiliation == 'staff':
+ return 15
+
+ def get_home_ou(self):
+ """
+ Map LDAP record to Evergreen home library
+ """
+
+ if 'laurentian.ca' or 'laurentienne.ca' in self.email:
+ return 103
+ elif 'huntingtonu.ca' in self.email:
+ return 104
+ elif 'usudbury.ca' in self.email:
+ return 107
+
+ # Default to Laurentian
+ return 103
+
+class AuthException(Exception):
+ """
+ Exceptions for authentication events
+ """
+
+ def __init__(self, msg=''):
+ """
+ Initialize the authentication exception
+ """
+ Exception.__init__(self)
+ self.msg = msg
+
+ def __str__(self):
+ """
+ Stringify the authentication exception
+ """
+ return 'AuthException: %s' % self.msg
+
def load_idl():
"""
Loads the fieldmapper IDL, registering class hints for the defined objects
parser.set_IDL(idlfile)
parser.parse_IDL()
-def login(username, password, workstation=None):
+def osrf_login(username, password, workstation=None):
"""
Login to the server and get back an authtoken
"""
__authtoken = None
- print("attempting login with user " + username)
-
- seed = request(
- 'open-ils.auth',
- 'open-ils.auth.authenticate.init', username).send()
+ try:
+ seed = osrf_request(
+ 'open-ils.auth',
+ 'open-ils.auth.authenticate.init', username).send()
+ except Exception, exc:
+ print exc
# generate the hashed password
password = oils.utils.utils.md5sum(seed + oils.utils.utils.md5sum(password))
- result = request(
+ result = osrf_request(
'open-ils.auth',
'open-ils.auth.authenticate.complete',
{ 'workstation' : workstation,
__authtoken = result['payload']['authtoken']
return __authtoken
-def request(service, method, *args):
+def osrf_request(service, method, *args):
"""
Make a JSON request to the OpenSRF gateway
req.setPath(credentials.GATEWAY_URL)
return req
-class AuthException(Exception):
- """
- Exceptions for authentication events
- """
-
- def __init__(self, msg=''):
- """
- Initialize the authentication exception
- """
- Exception.__init__(self)
- self.msg = msg
-
- def __str__(self):
- """
- Stringify the authentication exception
- """
- return 'AuthException: %s' % self.msg
-
def datatel_to_barcode(datatel):
"""
Converts a Datatel Colleague ID into a barcode
return 10 - rem
return rem
-def find_new_ldap_users(con, attributes, create_date):
+def find_new_ldap_users(con, attributes, create_date, auth):
"""
Retrieve personnel accounts from LDAP directory and process'em
"""
break
else:
# dump_data(result_data)
- create_evergreen_user(result_data[0][1])
- except ldap.LDAPError, e:
- print >> sys.stderr, e
+ create_evergreen_user(result_data[0][1], auth)
+ except ldap.LDAPError, exc:
+ print >> sys.stderr, exc
-def create_evergreen_user(result_data):
+def create_evergreen_user(result_data, auth):
"""
- Generate statements to push data into the staging table
+ Map LDAP record to Evergreen user
"""
- if 'mail' not in result_data:
- print >> sys.stderr, 'mail not found for %s' % result_data['cn']
+ user = User(result_data)
+ if not user:
return
- newau = oils.utils.idl.IDLParser.get_class('au')()
+ newau = osrf.net_obj.new_object_from_hint('au')
+
newau.isnew(True)
+ newau.usrname(user.usrname)
+ newau.profile(user.profile)
+ newau.email(user.email)
+ newau.family_name(user.family_name)
+ newau.first_given_name(user.first_given_name)
+ newau.ident_type(user.ident_type)
+ newau.ident_value(user.ident_value)
+ newau.home_ou(user.home_ou)
+ newau.passwd(user.passwd)
+
+ # Create the user
+ try:
+ result = osrf_request(
+ 'open-ils.actor', 'open-ils.actor.patron.update', auth, newau
+ ).send()
+ except Exception, exc:
+ print exc
- # Strip leading/ending whitespace
- newau.usrname(result_data['mail'][0].strip().lower())
- newau.email(result_data['mail'][0].strip().lower())
- newau.family_name(result_data['sn'][0].strip().lower())
- newau.ident_value(result_data['lulColleagueId'][0].strip().lower())
-
- if 'givenName' in result_data:
- newau.given_name(result_data['givenName'][0].strip())
- else:
- newau.given_name('LDAP_NULL')
- print >> sys.stderr, 'No givenName for %s' % (newau.usrname())
-
- if len(newau.ident_value()) != 7:
- print >> sys.stderr, 'Datatel number not 7 chars for %s (%s)' % (
- newau.usrname(), newau.datatel()
- )
- if len(newau.datatel()) == 6:
- newau.datatel('0%s' % newau.datatel())
- elif len(newau.datatel()) == 5:
- newau.datatel('00%s' % newau.datatel())
+ evt = oils.event.Event.parse_event(result)
+ if evt and not evt.success:
+ raise AuthException(evt.text_code)
+
+ # XXX Create barcode... how?
+ # Trigger on actor.usr? New custom API?
+
+ create_stat_cats(newau, result_data)
+
+ print(newau)
+
+def create_stat_cats(user, result_data):
+ """
+ Map statistical categories
+ """
+ # Reasonable default
+ lang = 'E'
if 'preferredLanguage' in result_data:
lang = result_data['preferredLanguage'][0].strip()
- else:
- lang = r'\N'
-
- if 'lulStudentLevel' in result_data:
- affiliation = result_data['lulStudentLevel'][0].strip().lower()
- elif 'lulPrimaryAffiliation' in result_data:
- affiliation = result_data['lulPrimaryAffiliation'][0].strip().lower()
- else:
- affiliation = r'\N'
-
- if affiliation == 'ug' or affiliation == 'student':
- newau.profile(13)
- elif affiliation == 'gr':
- newau.profile(12)
- elif affiliation == 'al':
- newau.profile(14)
- elif affiliation == 'faculty':
- newau.profile(11)
- elif affiliation == 'staff':
- newau.profile(15)
+
+ # XXX Now we should generate stat cats eh?
+
def dump_data(result_data):
"""
for key in result_data[0][1]:
print(key, result_data[0][1][key])
-def generate_ldap_sql(create_date):
+def ldap_create_by_date(create_date, auth):
"""
- Generate the SQL required to create and update Evergreen accounts
+ Connect to LDAP directory and process users created since a given date
"""
con = ldap.initialize(credentials.LDAP_HOST)
con.set_option(ldap.OPT_REFERRALS, 0)
try:
- attributes = ['lulStudentLevel', 'lulPrimaryAffiliation', 'cn', 'mail', 'givenName', 'sn', 'lulColleagueId', 'preferredLanguage']
+ attributes = [
+ 'lulStudentLevel', 'lulPrimaryAffiliation', 'cn', 'mail',
+ 'givenName', 'sn', 'lulColleagueId', 'preferredLanguage'
+ ]
con.simple_bind_s(credentials.LDAP_DN, credentials.LDAP_PW)
- find_new_ldap_users(con, attributes, create_date)
- except ldap.LDAPError, e:
- print >> sys.stderr, "Could not connect: " + e.message['info']
- if type(e.message) == dict and e.message.has_key('desc'):
- print >> sys.stderr, e.message['desc']
+ find_new_ldap_users(con, attributes, create_date, auth)
+ except ldap.LDAPError, exc:
+ print >> sys.stderr, "Could not connect: " + exc.message['info']
+ if type(exc.message) == dict and exc.message.has_key('desc'):
+ print >> sys.stderr, exc.message['desc']
else:
- print >> sys.stderr, e
+ print >> sys.stderr, exc
sys.exit()
finally:
con.unbind()
if __name__ == '__main__':
import doctest
doctest.testmod()
- exit()
# Set the host for our requests
osrf.gateway.GatewayRequest.setDefaultHost(credentials.OSRF_HOST)
load_idl()
# Log in and get an authtoken
- authtoken = login(credentials.OSRF_USER, credentials.OSRF_PW)
-
- generate_ldap_sql('20110701')
+ AUTHTOKEN = osrf_login(credentials.OSRF_USER, credentials.OSRF_PW)
+
+ UDATA = {
+ 'mail': ['dan@example.com'],
+ 'givenName': ['Dan'],
+ 'sn': ['Scott'],
+ 'lulColleagueId': ['0123456'],
+ 'lulStudentLevel': ['GR'],
+ }
+ create_evergreen_user(UDATA, AUTHTOKEN)
+
+# ldap_create_by_date('20110701')
# vim: et:ts=4:sw=4:tw=78: