diff --git a/ceo/ldapi.py b/ceo/ldapi.py index c2fc690..1b881ad 100644 --- a/ceo/ldapi.py +++ b/ceo/ldapi.py @@ -111,6 +111,17 @@ def make_modlist(old, new): return mlist +def format_ldaperror(ex): + desc = ex[0].get('desc', '') + info = ex[0].get('info', '') + if desc and info: + return "%s: %s" % (desc, info) + elif desc: + return desc + else: + return str(ex) + + class Sasl: def __init__(self, mech, realm): diff --git a/ceo/members.py b/ceo/members.py index 21013dc..c8b1f7a 100644 --- a/ceo/members.py +++ b/ceo/members.py @@ -43,11 +43,13 @@ def configure(): ### Exceptions ### -LDAPException = ldap.LDAPError -ConfigurationException = conf.ConfigurationException - class MemberException(Exception): """Base exception class for member-related errors.""" + def __init__(self, ex): + Exception.__init__(self) + self.ex = ex + def __str__(self): + return str(self.ex) class InvalidTerm(MemberException): """Exception class for malformed terms.""" @@ -134,10 +136,13 @@ def create_member(username, password, name, program): if not password or len(password) < cfg['min_password_length']: raise InvalidArgument("password", "", "too short (minimum %d characters)" % cfg['min_password_length']) - args = [ "/usr/bin/addmember", "--stdin", username, name, program ] - addmember = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - out, err = addmember.communicate(password) - status = addmember.wait() + try: + args = [ "/usr/bin/addmember", "--stdin", username, name, program ] + addmember = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = addmember.communicate(password) + status = addmember.wait() + except OSError, e: + raise MemberException(e) if status: raise ChildFailed("addmember", status, out+err) @@ -324,10 +329,13 @@ def create_club(username, name): if not username or not re.match(cfg['username_regex'], username): raise InvalidArgument("username", username, "expected format %s" % repr(cfg['username_regex'])) - args = [ "/usr/bin/addclub", username, name ] - addclub = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - out, err = addclub.communicate() - status = addclub.wait() + try: + args = [ "/usr/bin/addclub", username, name ] + addclub = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = addclub.communicate() + status = addclub.wait() + except OSError, e: + raise MemberException(e) if status: raise ChildFailed("addclub", status, out+err) diff --git a/ceo/urwid/main.py b/ceo/urwid/main.py index b923a9f..6f95c68 100644 --- a/ceo/urwid/main.py +++ b/ceo/urwid/main.py @@ -1,5 +1,5 @@ import random, ldap, urwid.curses_display -from ceo import members +from ceo import members, ldapi from ceo.urwid.widgets import * from ceo.urwid.window import * from ceo.urwid import newmember, renew, info, search, positions, groups @@ -146,8 +146,12 @@ def start(): try: ui.run_wrapper( run ) except ldap.LOCAL_ERROR, e: - print e[0]['info'] + print ldapi.format_ldaperror(e) print "Hint: You may need to run 'kinit'" + except ldap.INSUFFICIENT_ACCESS, e: + print ldapi.format_ldaperror(e) + print "You probably aren't permitted to do whatever you just tried." + print "Admittedly, ceo probably shouldn't have crashed either." if __name__ == '__main__': start() diff --git a/ceo/urwid/newmember.py b/ceo/urwid/newmember.py index cb42e4f..4281cc4 100644 --- a/ceo/urwid/newmember.py +++ b/ceo/urwid/newmember.py @@ -1,4 +1,4 @@ -import urwid +import ldap, urwid from ceo import members, terms from ceo.urwid.widgets import * from ceo.urwid.window import * @@ -159,15 +159,16 @@ class EndPage(WizardPanel): raise Exception("Internal Error") except members.InvalidArgument, e: problem = str(e) - except members.LDAPException, e: + except ldap.LDAPError, e: problem = str(e) - except members.ChildFailed, e: + except members.MemberException, e: problem = str(e) if problem: self.headtext.set_text("Failures Occured Adding User") - self.midtext.set_text("The error was:\n%s\nThe account may be partially added " - "and you may or may not be able to log in. Please contact systems committee." % problem) + self.midtext.set_text("The error was:\n\n%s\n\nThe account may be partially added " + "and you may or may not be able to log in. Or perhaps you are not office staff. " + "If this was not expected please contact systems committee." % problem) return else: self.headtext.set_text("User Added") diff --git a/ceo/urwid/renew.py b/ceo/urwid/renew.py index cc66607..f68ab9b 100644 --- a/ceo/urwid/renew.py +++ b/ceo/urwid/renew.py @@ -1,5 +1,5 @@ -import urwid -from ceo import members, terms +import urwid, ldap +from ceo import members, terms, ldapi from ceo.urwid.widgets import * from ceo.urwid.window import * @@ -102,14 +102,20 @@ class EndPage(WizardPanel): def focusable(self): return False def activate(self): + problem = None try: members.register( self.state['userid'], self.state['terms'] ) self.headtext.set_text("Registration Succeeded") self.midtext.set_text("The member has been registered for the following " "terms: " + ", ".join(self.state['terms']) + ".") - except Exception, e: + except ldap.LDAPError, e: + problem = ldapi.format_ldaperror(e) + except members.MemberException, e: + problem = str(e) + if problem: self.headtext.set_text("Failed to Register") - self.midtext.set_text("You may refund any fees paid or retry." - "The error was: '%s'" % e) + self.midtext.set_text("You may refund any fees paid or retry. " + "The error was:\n\n%s" % problem) + def check(self): pop_window()