Generate barcodes and push them into LDAP
authorDan Scott <dscott@laurentian.ca>
Tue, 7 May 2013 18:48:51 +0000 (14:48 -0400)
committerDan Scott <dscott@laurentian.ca>
Tue, 7 May 2013 18:48:51 +0000 (14:48 -0400)
Call the new custom API to open-ils.actor for generating barcodes;
accepts one argument, user ID, which gets the barcode set to their new
value. If no arg is passed, just generates a new barcode and returns it
(should be useful on the patron editor screen).

As far as pushing the barcodes into LDAP goes, I can't confirm that the
updates are actually working, because I can't see them, but the lack of
errors suggests that it's working.

Signed-off-by: Dan Scott <dscott@laurentian.ca>
tools/patron-load/ldap_osrf_sync

index c60d3f9..f305d14 100644 (file)
@@ -332,18 +332,20 @@ def find_ldap_users(con, ldap_filter, attributes, auth):
     base_dn = 'o=lul'
     search_scope = ldap.SCOPE_SUBTREE
 
-    print ldap_filter
     try:
         result_id = con.search(base_dn, search_scope, ldap_filter, attributes)
         while 1:
             result_type, result_data = con.result(result_id, 0)
             if result_data == []:
                 break
-            else:
-                if ARGS.dump_ldap:
-                    dump_data(result_data)
-                if ARGS.create_users:
-                    create_evergreen_user(auth, result_data[0][1])
+
+            if ARGS.dump_ldap:
+                dump_data(result_data)
+            if ARGS.create_users:
+                (ident, code) = create_evergreen_user(auth, result_data[0][1])
+                # Push the barcode into LDAP
+                update_ldap_barcode(con, ident, code)
+
     except ldap.LDAPError, exc:
         print >> sys.stderr, exc
 
@@ -424,31 +426,68 @@ def create_evergreen_user(auth, result_data):
 
     # Create the user
     try:
-        result = osrf_request(
+        usr = osrf_request(
             'open-ils.actor', 'open-ils.actor.patron.update', auth, newau
         ).send()
     except Exception, exc:
         print exc
 
-    evt = oils.event.Event.parse_event(result)
+    evt = oils.event.Event.parse_event(usr)
     if evt and not evt.success:
         raise AuthException(evt.text_code)
 
-    # XXX Create barcode... how?
-    # Trigger on actor.usr? New custom API?
-    # Currently doing the horrible thing of:
-    # SELECT evergreen.lu_update_barcode(id)
-    #   FROM actor.usr
-    #   WHERE create_date > %s
-    #   AND barcode IS NULL
-    #   AND home_ou IN (
-    #     SELECT id FROM actor.org_unit WHERE parent_ou = 105
-    #   )
-    # ;
+    # Generate a barcode for the user
+    try:
+        barcode = osrf_request(
+            'open-ils.actor', 'open-ils.actor.generate_patron_barcode', 
+            auth, usr.id()
+        ).send()
+    except Exception, exc:
+        print exc
+
+    evt = oils.event.Event.parse_event(barcode)
+    if evt and not evt.success:
+        raise AuthException(evt.text_code)
+    barcode = barcode['evergreen.lu_update_barcode']
 
     create_stat_cats(newau, result_data)
 
-    print("Created: %s" % newau.usrname())
+    print("Created: %s with barcode %s" % (newau.usrname(), barcode))
+
+    return (newau.ident_value(), barcode)
+
+def update_ldap_barcode(con, ident, barcode):
+    """
+    Updates the LDAP directory with the new barcode for a given user
+
+    We need to retrieve the qualified CN for the ldap.modify_s operation,
+    first, so take the first match we get. Reckless, I know.
+    """
+
+    base_dn = 'o=lul'
+    search_scope = ldap.SCOPE_SUBTREE
+
+    try:
+        ldap_filter = '(&%s(lulColleagueId=%s))' % (
+            '(objectclass=lulEduPerson)', ident
+        )
+        result_id = con.search(base_dn, search_scope, ldap_filter)
+        while 1:
+            result_type, result_data = con.result(result_id, 0)
+            if result_data == []:
+                break
+
+            if 'lulColleagueId' not in result_data[0][1]:
+                continue
+
+            cname = result_data[0][1]['cn'][0]
+            mod_attrs = [(ldap.MOD_REPLACE, 'lulLibraryBarcode', barcode)]
+            con.modify(cname, mod_attrs)
+    except Exception, exc:
+        print >> sys.stderr, exc
+
+    return True
 
 def create_stat_cats(user, result_data):
     """
@@ -473,49 +512,34 @@ def dump_data(result_data):
     for key in result_data[0][1]:
         print(key, result_data[0][1][key])
 
-def ldap_create_by_date(auth):
+def ldap_query(con, auth):
     """
-    Connect to LDAP directory and process users created since a given date
+    Process LDAP users created since a given date
     """
-
-    con = ldap.initialize(ARGS.ldap_server)
-    con.set_option(ldap.OPT_REFERRALS, 0)
-
-    try:
-        attributes = [
-            'lulStudentLevel', 'lulPrimaryAffiliation', 'cn', 'mail',
-            'givenName', 'sn', 'lulColleagueId', 'preferredLanguage'
-        ]
-        con.simple_bind_s(ARGS.ldap_user, ARGS.ldap_password)
-
-        if (ARGS.query_date):
-            ldap_filter = '(&%s(lulPrimaryAffiliation=*)(createTimestamp>=%s))' % (
-                '(objectclass=lulEduPerson)', ARGS.query_date
-            )
-        elif (ARGS.query_cn):
-            ldap_filter = '(&%s(cn=%s))' % (
-                '(objectclass=lulEduPerson)', ARGS.query_cn
-            )
-        elif (ARGS.query_sn):
-            ldap_filter = '(&%s(sn=%s))' % (
-                '(objectclass=lulEduPerson)', ARGS.query_sn
-            )
-        elif (ARGS.query_id):
-            ldap_filter = '(&%s(lulColleagueId=%s))' % (
-                '(objectclass=lulEduPerson)', ARGS.query_id
-            )
-        
-        find_ldap_users(con, ldap_filter, attributes, 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, exc
-        sys.exit()
-    finally:
-        con.unbind()
+    attributes = [
+        'lulLibraryBarcode',
+        'lulStudentLevel', 'lulPrimaryAffiliation', 'cn', 'mail',
+        'givenName', 'sn', 'lulColleagueId', 'preferredLanguage'
+    ]
+
+    if (ARGS.query_date):
+        ldap_filter = '(&%s(lulPrimaryAffiliation=*)(createTimestamp>=%s))' % (
+            '(objectclass=lulEduPerson)', ARGS.query_date
+        )
+    elif (ARGS.query_cn):
+        ldap_filter = '(&%s(cn=%s))' % (
+            '', ARGS.query_cn
+        )
+    elif (ARGS.query_sn):
+        ldap_filter = '(&%s(sn=%s))' % (
+            '(objectclass=lulEduPerson)', ARGS.query_sn
+        )
+    elif (ARGS.query_id):
+        ldap_filter = '(&%s(lulColleagueId=%s))' % (
+            '(objectclass=lulEduPerson)', ARGS.query_id
+        )
+    
+    find_ldap_users(con, ldap_filter, attributes, auth)
 
 def parse_args():
     """
@@ -565,10 +589,13 @@ def parse_args():
     args = parser.parse_args()
     return args
 
-if __name__ == '__main__':
-    import doctest
-    doctest.testmod()
+def main():
+    """
+    Set up connections and run code
+    """
 
+    global ARGS
+    global AUTHTOKEN
     ARGS = parse_args()
 
     # Set the host for our requests
@@ -578,9 +605,23 @@ if __name__ == '__main__':
     load_idl()
 
     # Log in and get an authtoken
-    AUTHTOKEN = osrf_login(
-        ARGS.eg_user, ARGS.eg_password, ARGS.eg_workstation
-    )
+    AUTHTOKEN = osrf_login(ARGS.eg_user, ARGS.eg_password, ARGS.eg_workstation)
+
+    try:
+        con = ldap.initialize(ARGS.ldap_server)
+        con.set_option(ldap.OPT_REFERRALS, 0)
+        con.simple_bind_s(ARGS.ldap_user, ARGS.ldap_password)
+        ldap_query(con, AUTHTOKEN)
+
+    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, exc
+        sys.exit()
+    finally:
+        con.unbind()
 
 #    UDATA = {
 #        'mail': ['dan@example.com'],
@@ -591,6 +632,13 @@ if __name__ == '__main__':
 #    }
 #    create_evergreen_user(AUTHTOKEN, UDATA)
 
-    ldap_create_by_date(AUTHTOKEN)
 
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()
+
+    ARGS = None
+    AUTHTOKEN = None
+
+    main()
 # vim: et:ts=4:sw=4:tw=78: