diff --git a/bin/ceoquery b/bin/ceoquery index 629bb14ba..454191e4d 100755 --- a/bin/ceoquery +++ b/bin/ceoquery @@ -15,9 +15,9 @@ for key in os.environ.keys(): os.environ['PATH'] = '/usr/sbin:/usr/bin:/sbin:/bin' -for pathent in sys.path[:]: - if not pathent.find('/usr') == 0: - sys.path.remove(pathent) +#for pathent in sys.path[:]: +# if not pathent.find('/usr') == 0: +# sys.path.remove(pathent) euid = os.geteuid() egid = os.getegid() @@ -37,7 +37,7 @@ except Exception, e: sys.exit(1) def usage(): - print "Usage: ceoquery memberlist|booklist|allmembers|allusers|termusers" + print "Usage: ceoquery memberlist|booklist|allusers|termusers" if len(sys.argv) < 2: usage() @@ -46,14 +46,16 @@ elif sys.argv[1] == 'memberlist': current_term = terms.current() members = members.list_term(current_term) - for member in members: - print "%(memberid)s|%(name)s|%(program)s|%(userid)s" % member + for member in members.values(): + if 'program' in member: + program = member['program'][0] + else: + program = '' + print "%s|%s|%s" % (member['cn'][0], program, member['uid'][0]) elif sys.argv[1] == 'allmembers': - members = members.list_all() - for member in members: - print "%(memberid)s|%(name)s|%(program)s|%(userid)s" % member + pass elif sys.argv[1] == 'booklist': diff --git a/pylib/csc/adm/accounts.py b/pylib/csc/adm/accounts.py index fc9f05f72..2b28750f3 100644 --- a/pylib/csc/adm/accounts.py +++ b/pylib/csc/adm/accounts.py @@ -655,18 +655,14 @@ def remove_member(username, groupname): ### Account Types ### -def create_member(username, password, name, memberid): +def create_member(username, password, name): """ Creates a UNIX user account with options tailored to CSC members. - Note: The 'other' section of the GECOS field is filled with the CSC - memberid. This section cannot be changed by the user via chfn(1). - Parameters: username - the desired UNIX username password - the desired UNIX password name - the member's real name - memberid - the CSC member id number Exceptions: InvalidArgument - on bad account attributes provided @@ -692,24 +688,20 @@ def create_member(username, password, name, memberid): maximum_id = cfg['member_max_id'] home = cfg['member_home'] + '/' + username description = cfg['member_desc'] - gecos_field = build_gecos(name, other=memberid) + gecos_field = build_gecos(name) shell = cfg['member_shell'] group = cfg['member_group'] return create(username, name, minimum_id, maximum_id, home, password, description, gecos_field, shell, group) -def create_club(username, name, memberid): +def create_club(username, name): """ Creates a UNIX user account with options tailored to CSC-hosted clubs. - Note: The 'other' section of the GECOS field is filled with the CSC - memberid. This section cannot be changed by the user via chfn(1). - Parameters: username - the desired UNIX username name - the club name - memberid - the CSC member id number Exceptions: InvalidArgument - on bad account attributes provided @@ -732,7 +724,7 @@ def create_club(username, name, memberid): maximum_id = cfg['club_max_id'] home = cfg['club_home'] + '/' + username description = cfg['club_desc'] - gecos_field = build_gecos(name, other=memberid) + gecos_field = build_gecos(name) shell = cfg['club_shell'] group = cfg['club_group'] diff --git a/pylib/csc/adm/members.py b/pylib/csc/adm/members.py index a9c3f62d6..b87f856ed 100644 --- a/pylib/csc/adm/members.py +++ b/pylib/csc/adm/members.py @@ -11,7 +11,7 @@ must also be moved into this module. """ import re from csc.adm import terms -from csc.backends import db, ldapi +from csc.backends import ldapi from csc.common import conf from csc.common.excep import InvalidArgument @@ -42,7 +42,6 @@ def load_configuration(): ### Exceptions ### -DBException = db.DBException ConfigurationException = conf.ConfigurationException class MemberException(Exception): @@ -87,9 +86,6 @@ class NoSuchMember(MemberException): ### Connection Management ### -# global database connection -db_connection = db.DBConnection() - # global directory connection ldap_connection = ldapi.LDAPConnection() @@ -97,27 +93,25 @@ def connect(): """Connect to PostgreSQL.""" load_configuration() - db_connection.connect(cfg['server'], cfg['database']) ldap_connection.connect(cfg['server_url'], cfg['admin_bind_dn'], cfg['admin_bind_pw'], cfg['users_base'], cfg['groups_base']) def disconnect(): """Disconnect from PostgreSQL.""" - db_connection.disconnect() ldap_connection.disconnect() def connected(): - """Determine whether the db_connection has been established.""" + """Determine whether the connection has been established.""" - return db_connection.connected() and ldap_connection.connected() + return ldap_connection.connected() ### Member Table ### -def new(uid, realname, studentid=None, program=None, mtype='user'): +def new(uid, realname, studentid=None, program=None): """ Registers a new CSC member. The member is added to the members table and registered for the current term. @@ -127,23 +121,21 @@ def new(uid, realname, studentid=None, program=None, mtype='user'): realname - the full real name of the member studentid - the student id number of the member program - the program of study of the member - mtype - a string describing the type of member ('user', 'club') - Returns: the memberid of the new member + Returns: the username of the new member Exceptions: DuplicateStudentID - if the student id already exists in the database InvalidStudentID - if the student id is malformed InvalidRealName - if the real name is malformed - Example: new("Michael Spang", program="CS") -> 3349 + Example: new("Michael Spang", program="CS") -> "mspang" """ # blank attributes should be NULL if studentid == '': studentid = None if program == '': program = None if uid == '': uid = None - if mtype == '': mtype = None # check the student id format if studentid is not None and not re.match(cfg['studentid_regex'], str(studentid)): @@ -154,92 +146,61 @@ def new(uid, realname, studentid=None, program=None, mtype='user'): raise InvalidRealName(realname) # check for duplicate student id - member = db_connection.select_member_by_studentid(studentid) or \ - ldap_connection.member_search_studentid(studentid) + member = ldap_connection.member_search_studentid(studentid) if member: raise DuplicateStudentID(studentid) # check for duplicate userid - member = db_connection.select_member_by_userid(uid) or \ - ldap_connection.user_lookup(uid) + member = ldap_connection.user_lookup(uid) if member: raise InvalidArgument("uid", uid, "duplicate uid") - # add the member to the database - memberid = db_connection.insert_member(realname, studentid, program, userid=uid) - # add the member to the directory ldap_connection.member_add(uid, realname, studentid, program) - # register them for this term in the database - db_connection.insert_term(memberid, terms.current()) - # register them for this term in the directory member = ldap_connection.member_lookup(uid) member['term'] = [ terms.current() ] ldap_connection.user_modify(uid, member) - # commit the database transaction - db_connection.commit() - - return memberid + return uid -def get(memberid): - """ - Look up attributes of a member by memberid. - - Returns: a dictionary of attributes - - Example: get(3349) -> { - 'memberid': 3349, - 'name': 'Michael Spang', - 'program': 'Computer Science', - ... - } - """ - - return db_connection.select_member_by_id(memberid) - - -def get_userid(userid): +def get(userid): """ Look up attributes of a member by userid. - Parameters: - userid - the UNIX user id - Returns: a dictionary of attributes Example: get('mspang') -> { - 'memberid': 3349, - 'name': 'Michael Spang', - 'program': 'Computer Science', + 'cn': [ 'Michael Spang' ], + 'program': [ 'Computer Science' ], ... } """ - return db_connection.select_member_by_userid(userid) + return ldap_connection.user_lookup(userid) def get_studentid(studentid): """ - Look up attributes of a member by studnetid. + Look up attributes of a member by studentid. Parameters: studentid - the student ID number - Returns: a dictionary of attributes + Returns: a dict of members Example: get(...) -> { - 'memberid': 3349, - 'name': 'Michael Spang', - 'program': 'Computer Science', + 'mspang': { + 'name': [ 'Michael Spang' ], + 'program': [ 'Computer Science' ], + } ... } """ - return db_connection.select_member_by_studentid(studentid) + return ldap_connection.member_search_studentid(studentid) def list_term(term): @@ -249,19 +210,16 @@ def list_term(term): Parameters: term - the term to match members against - Returns: a list of member dictionaries + Returns: a list of members - Example: list_term('f2006'): -> [ - { 'memberid': 3349, ... }, - { 'memberid': ... }. + Example: list_term('f2006'): -> { + 'mspang': { 'cn': 'Michael Spang', ... }, + 'ctdalek': { 'cn': 'Calum T. Dalek', ... }, ... - ] + } """ - # retrieve a list of memberids in term - memberlist = db_connection.select_members_by_term(term) - - return memberlist.values() + return ldap_connection.member_search_term(term) def list_name(name): @@ -273,123 +231,52 @@ def list_name(name): Returns: a list of member dictionaries - Example: list_name('Spang'): -> [ - { 'memberid': 3349, ... }, - { 'memberid': ... }, + Example: list_name('Spang'): -> { + 'mspang': { 'cn': 'Michael Spang', ... }, ... ] """ - # retrieve a list of memberids matching name - memberlist = db_connection.select_members_by_name(name) - - return memberlist.values() + return ldap_connection.member_search_name(name) -def list_all(): - """ - Builds a list of all members. - - Returns: a list of member dictionaries - """ - - # retrieve a list of members - memberlist = db_connection.select_all_members() - - return memberlist.values() - - -def delete(memberid): +def delete(userid): """ Erase all records of a member. Note: real members are never removed from the database - Returns: attributes and terms of the member in a tuple + Returns: ldap entry of the member Exceptions: - NoSuchMember - if the member id does not exist + NoSuchMember - if the user id does not exist - Example: delete(0) -> ({ 'memberid': 0, name: 'Calum T. Dalek' ...}, ['s1993']) + Example: delete('ctdalek') -> { 'cn': [ 'Calum T. Dalek' ], 'term': ['s1993'], ... } """ # save member data - member = db_connection.select_member_by_id(memberid) + member = ldap_connection.user_lookup(userid) # bail if not found if not member: - raise NoSuchMember(memberid) - - term_list = db_connection.select_terms(memberid) - - # remove data from the db - db_connection.delete_term_all(memberid) - db_connection.delete_member(memberid) - db_connection.commit() + raise NoSuchMember(userid) # remove data from the directory - if member and member['userid']: - uid = member['userid'] - ldap_connection.user_delete(uid) + uid = member['uid'][0] + ldap_connection.user_delete(uid) - return (member, term_list) - - -def update(member): - """ - Update CSC member attributes. - - Parameters: - member - a dictionary with member attributes as returned by get, - possibly omitting some attributes. member['memberid'] - must exist and be valid. None is NULL. - - Exceptions: - NoSuchMember - if the member id does not exist - InvalidStudentID - if the student id number is malformed - DuplicateStudentID - if the student id number exists - - Example: update( {'memberid': 3349, userid: 'mspang'} ) - """ - - if member.has_key('studentid') and member['studentid'] is not None: - - studentid = member['studentid'] - - # check the student id format - if studentid is not None and not re.match(cfg['studentid_regex'], str(studentid)): - raise InvalidStudentID(studentid) - - # check for duplicate student id - dupmember = db_connection.select_member_by_studentid(studentid) - if dupmember: - raise DuplicateStudentID(studentid) - - # not specifying memberid is a bug - if not member.has_key('memberid'): - raise Exception("no member specified in call to update") - memberid = member['memberid'] - - # see if member exists - if not get(memberid): - raise NoSuchMember(memberid) - - # do the update - db_connection.update_member(member) - - # commit the transaction - db_connection.commit() + return member ### Term Table ### -def register(memberid, term_list): +def register(userid, term_list): """ Registers a member for one or more terms. Parameters: - memberid - the member id number + userid - the member's username term_list - the term to register for, or a list of terms Exceptions: @@ -403,13 +290,12 @@ def register(memberid, term_list): if type(term_list) in (str, unicode): term_list = [ term_list ] - ldap_member = None - db_member = get(memberid) - if db_member['userid']: - uid = db_member['userid'] - ldap_member = ldap_connection.member_lookup(uid) - if ldap_member and 'term' not in ldap_member: - ldap_member['term'] = [] + ldap_member = ldap_connection.member_lookup(userid) + if ldap_member and 'term' not in ldap_member: + ldap_member['term'] = [] + + if not ldap_member: + raise NoSuchMember(userid) for term in term_list: @@ -417,52 +303,48 @@ def register(memberid, term_list): if not re.match('^[wsf][0-9]{4}$', term): raise InvalidTerm(term) - # add term to database - db_connection.insert_term(memberid, term) - # add the term to the directory - if ldap_member: - ldap_member['term'].append(term) + ldap_member['term'].append(term) - if ldap_member: - ldap_connection.user_modify(uid, ldap_member) - - db_connection.commit() + ldap_connection.user_modify(userid, ldap_member) -def registered(memberid, term): +def registered(userid, term): """ Determines whether a member is registered for a term. Parameters: - memberid - the member id number + userid - the member's username term - the term to check Returns: whether the member is registered - Example: registered(3349, "f2006") -> True + Example: registered("mspang", "f2006") -> True """ - return db_connection.select_term(memberid, term) is not None + member = ldap_connection.member_lookup(userid) + return 'term' in member and term in member['term'] -def member_terms(memberid): +def member_terms(userid): """ Retrieves a list of terms a member is registered for. Parameters: - memberid - the member id number + userid - the member's username Returns: list of term strings - Example: registered(0) -> 's1993' + Example: registered('ctdalek') -> 's1993' """ - terms_list = db_connection.select_terms(memberid) - terms_list.sort(terms.compare) - return terms_list + member = ldap_connection.member_lookup(userid) + if not 'term' in member: + return [] + else: + return member['term'] @@ -484,9 +366,9 @@ if __name__ == '__main__': tm2usid = '00000002' tm2uprogram = 'Pseudoscience' - tmdict = {'name': tmname, 'userid': tmuid, 'program': tmprogram, 'type': 'user', 'studentid': tmsid } - tm2dict = {'name': tm2name, 'userid': tm2uid, 'program': None, 'type': 'user', 'studentid': tm2sid } - tm2udict = {'name': tm2uname, 'userid': tm2uid, 'program': tm2uprogram, 'type': 'user', 'studentid': tm2usid } + tmdict = {'cn': [tmname], 'uid': [tmuid], 'program': [tmprogram], 'studentid': [tmsid] } + tm2dict = {'cn': [tm2name], 'uid': [tm2uid], 'studentid': [tm2sid] } + tm2udict = {'cn': [tm2uname], 'uid': [tm2uid], 'program': [tm2uprogram], 'studentid': [tm2usid] } thisterm = terms.current() nextterm = terms.next(thisterm) @@ -500,21 +382,17 @@ if __name__ == '__main__': success() dmid = get_studentid(tmsid) - if dmid: delete(dmid['memberid']) + if tmuid in dmid: delete(dmid[tmuid]['uid'][0]) dmid = get_studentid(tm2sid) - if dmid: delete(dmid['memberid']) + if tm2uid in dmid: delete(dmid[tm2uid]['uid'][0]) dmid = get_studentid(tm2usid) - if dmid: delete(dmid['memberid']) + if tm2uid in dmid: delete(dmid[tm2uid]['uid'][0]) test(new) tmid = new(tmuid, tmname, tmsid, tmprogram) tm2id = new(tm2uid, tm2name, tm2sid) success() - tmdict['memberid'] = tmid - tm2dict['memberid'] = tm2id - tm2udict['memberid'] = tm2id - test(registered) assert_equal(True, registered(tmid, thisterm)) assert_equal(True, registered(tm2id, thisterm)) @@ -522,19 +400,19 @@ if __name__ == '__main__': success() test(get) - assert_equal(tmdict, get(tmid)) - assert_equal(tm2dict, get(tm2id)) + tmp = get(tmid) + del tmp['objectClass'] + del tmp['term'] + assert_equal(tmdict, tmp) + tmp = get(tm2id) + del tmp['objectClass'] + del tmp['term'] + assert_equal(tm2dict, tmp) success() test(list_name) - assert_equal(True, tmid in [ x['memberid'] for x in list_name(tmname) ]) - assert_equal(True, tm2id in [ x['memberid'] for x in list_name(tm2name) ]) - success() - - test(list_all) - allmembers = list_all() - assert_equal(True, tmid in [ x['memberid'] for x in allmembers ]) - assert_equal(True, tm2id in [ x['memberid'] for x in allmembers ]) + assert_equal(True, tmid in list_name(tmname).keys()) + assert_equal(True, tm2id in list_name(tm2name).keys()) success() test(register) @@ -548,24 +426,28 @@ if __name__ == '__main__': success() test(list_term) - assert_equal(True, tmid in [ x['memberid'] for x in list_term(thisterm) ]) - assert_equal(True, tmid in [ x['memberid'] for x in list_term(nextterm) ]) - assert_equal(True, tm2id in [ x['memberid'] for x in list_term(thisterm) ]) - assert_equal(False, tm2id in [ x['memberid'] for x in list_term(nextterm) ]) + assert_equal(True, tmid in list_term(thisterm).keys()) + assert_equal(True, tmid in list_term(nextterm).keys()) + assert_equal(True, tm2id in list_term(thisterm).keys()) + assert_equal(False, tm2id in list_term(nextterm).keys()) success() - test(update) - update(tm2udict) - assert_equal(tm2udict, get(tm2id)) - success() - - test(get_userid) - assert_equal(tm2udict, get_userid(tm2uid)) + test(get) + tmp = get(tm2id) + del tmp['objectClass'] + del tmp['term'] + assert_equal(tm2dict, tmp) success() test(get_studentid) - assert_equal(tm2udict, get_studentid(tm2usid)) - assert_equal(tmdict, get_studentid(tmsid)) + tmp = get_studentid(tm2sid)[tm2uid] + del tmp['objectClass'] + del tmp['term'] + assert_equal(tm2dict, tmp) + tmp = get_studentid(tmsid)[tmuid] + del tmp['objectClass'] + del tmp['term'] + assert_equal(tmdict, tmp) success() test(delete) diff --git a/pylib/csc/apps/legacy/main.py b/pylib/csc/apps/legacy/main.py index 64b2d50e0..8ac4b24d5 100644 --- a/pylib/csc/apps/legacy/main.py +++ b/pylib/csc/apps/legacy/main.py @@ -18,21 +18,56 @@ from csc.common.excep import InvalidArgument BORDER_COLOR = curses.COLOR_RED +def read_uid(wnd): + """Read a username.""" + + prompt = 'Username:' + return inputbox(wnd, prompt, 36) + +def read_member(wnd): + """Looks up a member.""" + + # connect the members module to its backend if necessary + if not members.connected(): members.connect() + + uid = read_uid(wnd) + if not uid or uid.lower() == 'exit': + return + + member = members.get(uid) + if not member: + msgbox(wnd, "Invalid username: %s" % uid) + return + + # display user + display_member_details(wnd, member) + + return member + + +def action_library(wnd): + """Display a link to the library.""" + msgbox(wnd, "Please visit library.csclub.uwaterloo.ca") + def action_new_member(wnd): """Interactively add a new member.""" userid, studentid, program = '', None, '' + msgbox(wnd, "Membership is $2.00 CDN. Please ensure\n" + "the money is desposited in the safe\n" + "before continuing.") + # read the name - prompt = " Name: " + prompt = "New member's full name: " realname = inputbox(wnd, prompt, 18) - # abort if no username is entered + # abort if no name is entered if not realname or realname.lower() == 'exit': return False # read the student id - prompt = "Student id:" + prompt = "New member's student ID:" while studentid is None or (re.search("[^0-9]", studentid) and not studentid.lower() == 'exit'): studentid = inputbox(wnd, prompt, 18) @@ -44,7 +79,7 @@ def action_new_member(wnd): studentid = None # read the program of study - prompt = " Program:" + prompt = "New member's program of study:" program = inputbox(wnd, prompt, 18) # abort if exit is entered @@ -52,7 +87,7 @@ def action_new_member(wnd): return False # read user id - prompt = "Userid:" + prompt = "New member's UWdir username:" while userid == '': userid = inputbox(wnd, prompt, 18) @@ -65,10 +100,10 @@ def action_new_member(wnd): # attempt to create the member try: - memberid = members.new(userid, realname, studentid, program) + members.new(userid, realname, studentid, program) - msgbox(wnd, "Success! Your memberid is %s. You are now registered\n" - % memberid + "for the " + terms.current() + " term.") + msgbox(wnd, "Success! Your username is %s. You are now registered\n" + % userid + "for the " + terms.current() + " term.") except members.InvalidStudentID: msgbox(wnd, "Invalid student ID: %s" % studentid) @@ -90,26 +125,25 @@ def action_new_member(wnd): def action_term_register(wnd): """Interactively register a member for a term.""" - memberid, term = '', '' + term = '' - # read the member id - prompt = 'Enter memberid ("exit" to cancel):' - memberuserid = inputbox(wnd, prompt, 36) + member = read_member(wnd) + if not member: + return False + uid = member['uid'][0] - if not memberuserid or memberuserid.lower() == 'exit': + # verify member + prompt = "Is this the correct member?" + answer = None + while answer != "yes" and answer != "y" and answer != "n" and answer != "no" and answer != "exit": + answer = inputbox(wnd, prompt, 28) + + # user abort + if answer == "exit": return False - member = get_member_memberid_userid(wnd, memberuserid) - if not member: return False - - memberid = member['memberid'] - term_list = members.member_terms(memberid) - - # display user - display_member_details(wnd, member, term_list) - # read the term - prompt = "Which term to register for ([fws]20nn):" + prompt = "Which term to register for ([wsf]20nn):" while not re.match('^[wsf][0-9]{4}$', term) and not term == 'exit': term = inputbox(wnd, prompt, 41) @@ -118,17 +152,17 @@ def action_term_register(wnd): return False # already registered? - if members.registered(memberid, term): + if members.registered(uid, term): msgbox(wnd, "You are already registered for term " + term) return False try: # attempt to register - members.register(memberid, term) + members.register(uid, term) - # display success message [sic] - msgbox(wnd, "Your are now registered for term " + term) + # display success message + msgbox(wnd, "You are now registered for term " + term) except members.InvalidTerm: msgbox(wnd, "Term is not valid: %s" % term) @@ -139,23 +173,22 @@ def action_term_register(wnd): def action_term_register_multiple(wnd): """Interactively register a member for multiple terms.""" - memberid, base, num = '', '', None + base, num = '', None - # read the member id - prompt = 'Enter memberid ("exit" to cancel):' - memberuserid = inputbox(wnd, prompt, 36) - - if not memberuserid or memberuserid.lower() == 'exit': + member = read_member(wnd) + if not member: return False + uid = member['uid'][0] - member = get_member_memberid_userid(wnd, memberuserid) - if not member: return False + # verify member + prompt = "Is this the correct member?" + answer = None + while answer != "yes" and answer != "y" and answer != "n" and answer != "no" and answer != "exit": + answer = inputbox(wnd, prompt, 28) - memberid = member['memberid'] - term_list = members.member_terms(memberid) - - # display user - display_member_details(wnd, member, term_list) + # user abort + if answer == "exit": + return False # read the base prompt = "Which term to start registering ([fws]20nn):" @@ -182,14 +215,14 @@ def action_term_register_multiple(wnd): # already registered? for term in term_list: - if members.registered(memberid, term): + if members.registered(uid, term): msgbox(wnd, "You are already registered for term " + term) return False try: # attempt to register all terms - members.register(memberid, term_list) + members.register(uid, term_list) # display success message [sic] msgbox(wnd, "Your are now registered for terms: " + ", ".join(term_list)) @@ -200,30 +233,6 @@ def action_term_register_multiple(wnd): return False -def repair_account(wnd, memberid, userid): - """Attemps to repair an account.""" - - if not accounts.connected(): accounts.connect() - - member = members.get(memberid) - exists, haspw = accounts.status(userid) - - if not exists: - password = input_password(wnd) - accounts.create_member(userid, password, member['name'], memberid) - msgbox(wnd, "Account created (where the hell did it go, anyway?)\n" - "If your homedir still exists, it will not be inaccessible to you,\n" - "please contact systems-committee@csclub.uwaterloo.ca to get this resolved.\n") - - elif not haspw: - password = input_password(wnd) - accounts.add_password(userid, password) - msgbox(wnd, "Password added to account.") - - else: - msgbox(wnd, "No problems to repair.") - - def input_password(wnd): # password input loop @@ -249,24 +258,16 @@ def input_password(wnd): def action_create_account(wnd): """Interactively create an account for a member.""" - memberid, userid = '', '' - - # read the member id - prompt = 'Enter member ID (exit to cancel):' - memberid = inputbox(wnd, prompt, 35) - - if not memberid or memberid.lower() == 'exit': + member = read_member(wnd) + if not member: return False - member = get_member_memberid_userid(wnd, memberid) - if not member: return False + # member already has an account? + if not accounts.connected(): accounts.connect() + if 'posixAccount' in member['objectClass']: + msgbox(wnd, "Account already exists.") + return False - memberid = member['memberid'] - term_list = members.member_terms(memberid) - - # display the member - display_member_details(wnd, member, term_list) - # verify member prompt = "Is this the correct member?" answer = None @@ -282,30 +283,9 @@ def action_create_account(wnd): msgbox(wnd, "I suggest searching for the member by userid or name from the main menu.") return False - # member already has an account? - if not accounts.connected(): accounts.connect() - if member['userid'] and accounts.status(member['userid'])[0]: - - userid = member['userid'] - msgbox(wnd, "Member " + str(memberid) + " already has an account: " + member['userid'] + "\n" - "Attempting to repair it. Contact the sysadmin if there are still problems." ) - - repair_account(wnd, memberid, userid) - - return False - - - if member['userid']: - userid = member['userid'] - - # read user id - prompt = "Userid:" - while userid == '': - userid = inputbox(wnd, prompt, 18) - - # user abort - if userid is None or userid.lower() == 'exit': - return False + msgbox(wnd, "Ensure the member has signed the machine\n" + "usage policy. Accounts of users who have\n" + "not signed will be suspended if discovered.") # read password password = input_password(wnd) @@ -313,7 +293,7 @@ def action_create_account(wnd): # create the UNIX account try: if not accounts.connected(): accounts.connect() - accounts.create_member(userid, password, member['name'], memberid) + accounts.create_member(member['uid'][0], password, member['cn'][0]) except accounts.NameConflict, e: msgbox(wnd, str(e)) return False @@ -329,86 +309,53 @@ def action_create_account(wnd): except accounts.KrbException, e: msgbox(wnd, "Error creating Kerberos principal - Contact the Systems Administrator: %s" % e) return False - - # now update the CEO database with the username - members.update( {'memberid': memberid, 'userid': userid} ) # success - msgbox(wnd, "Please run 'addhomedir " + userid + "'.") + msgbox(wnd, "Please run 'addhomedir " + member['uid'][0] + "'.") msgbox(wnd, "Success! Your account has been added") return False -def display_member_details(wnd, member, term_list): +def display_member_details(wnd, member): """Display member attributes in a message box.""" # clone and sort term_list - term_list = list(term_list) + if 'term' in member: + term_list = list(member['term']) + else: + term_list = [] term_list.sort( terms.compare ) # labels for data id_label, studentid_label, name_label = "ID:", "StudentID:", "Name:" - program_label, userid_label, terms_label = "Program:", "User ID:", "Terms:" + program_label, terms_label = "Program:", "Terms:" + + if 'program' in member: + program = member['program'][0] + else: + program = None + + if 'studentid' in member: + studentid = member['studentid'][0] + else: + studentid = None # format it all into a massive string - message = "%8s %-20s %10s %-10s (user)\n" % (name_label, member['name'], id_label, member['memberid']) + \ - "%8s %-20s %10s %-10s\n" % (program_label, member['program'], studentid_label, member['studentid']) - - if member['userid']: - message += "%8s %s\n" % (userid_label, member['userid']) - else: - message += 'No user ID.\n' + message = "%8s %-20s %10s %-10s\n" % (name_label, member['cn'][0], id_label, member['uid'][0]) + \ + "%8s %-20s %10s %-10s\n" % (program_label, program, studentid_label, studentid) message += "%s %s" % (terms_label, " ".join(term_list)) # display the string in a message box msgbox(wnd, message) - - -def get_member_memberid_userid(wnd, memberuserid): - """Retrieve member attributes by member of user id.""" - - # connect the members module to its backends - if not members.connected(): members.connect() - - # retrieve member data - - if re.match('^[0-9]*$', memberuserid): - - # numeric memberid, look it up - memberid = int(memberuserid) - member = members.get( memberid ) - if not member: - msgbox(wnd, '%s is an invalid memberid' % memberuserid) - - else: - - # non-numeric memberid: try userids - member = members.get_userid( memberuserid ) - if not member: - msgbox(wnd, "%s is an invalid account userid" % memberuserid) - - return member def action_display_member(wnd): """Interactively display a member.""" - # read the member id - prompt = 'Memberid: ' - memberid = inputbox(wnd, prompt, 36) - - if not memberid or memberid.lower() == 'exit': - return False - - member = get_member_memberid_userid(wnd, memberid) - if not member: return False - term_list = members.member_terms( member['memberid'] ) - - # display the details in a window - display_member_details(wnd, member, term_list) - + if not members.connected(): members.connect() + member = read_member(wnd) return False @@ -430,14 +377,26 @@ def format_members(member_list): # clone and sort member_list member_list = list(member_list) - member_list.sort( lambda x, y: x['memberid']-y['memberid'] ) + member_list.sort( lambda x, y: cmp(x['uid'], y['uid']) ) buf = '' for member in member_list: - attrs = ( member['memberid'], member['name'], member['studentid'], - member['type'], member['program'], member['userid'] ) - buf += "%4d %50s %10s %10s \n%55s %10s\n\n" % attrs + if 'uid' in member: + uid = member['uid'][0] + else: + uid = None + if 'program' in member: + program = member['program'][0] + else: + program = None + if 'studentid' in member: + studentid = member['studentid'][0] + else: + studentid = None + attrs = ( uid, member['cn'][0], + studentid, program ) + buf += "%10s %30s %10s\n%41s\n\n" % attrs return buf @@ -463,7 +422,7 @@ def action_list_term(wnd): member_list = members.list_term(term) # format the data into a mess of text - buf = format_members(member_list) + buf = format_members(member_list.values()) # display the mass of text with a pager page( buf ) @@ -491,7 +450,7 @@ def action_list_name(wnd): member_list = members.list_name(name) # format the data into a mess of text - buf = format_members(member_list) + buf = format_members(member_list.values()) # display the mass of text with a pager page( buf ) @@ -516,14 +475,10 @@ def action_list_studentid(wnd): if not members.connected(): members.connect() # retrieve a list of members for term - member = members.get_studentid(studentid) - if member != None: - member_list = [ members.get_studentid(studentid) ] - else: - member_list = [] + member_list = members.get_studentid(studentid) # format the data into a mess of text - buf = format_members(member_list) + buf = format_members(member_list.values()) # display the mass of text with a pager page( buf ) @@ -551,8 +506,7 @@ top_menu = [ ( "Search for a member by name", action_list_name ), ( "Search for a member by student id", action_list_studentid ), ( "Create an account", action_create_account ), - ( "Re Create an account", action_create_account ), - ( "Library functions", null_callback ), + ( "Library functions", action_library ), ( "Exit", exit_callback ), ]