Add club representative support

The only difference between a club representative account and a member account
is how they are registered for terms.  If you are already a representative for
the current term, you need only go through the membership renewal process to
become a full fledged member.
This commit is contained in:
Michael Spang 2007-12-20 16:43:33 -05:00
parent e28b159cdc
commit 34b2aa1028
5 changed files with 126 additions and 17 deletions

View File

@ -426,6 +426,41 @@ def register(userid, term_list):
ld.modify_s(user_dn, mlist) ld.modify_s(user_dn, mlist)
def register_nonmember(userid, term_list):
"""Registers a non-member for one or more terms."""
user_dn = 'uid=%s,%s' % (ldapi.escape(userid), cfg['users_base'])
if type(term_list) in (str, unicode):
term_list = [ term_list ]
ldap_member = get(userid)
if not ldap_member:
raise NoSuchMember(userid)
if 'term' not in ldap_member:
ldap_member['term'] = []
if 'nonMemberTerm' not in ldap_member:
ldap_member['nonMemberTerm'] = []
new_member = ldap_member.copy()
new_member['nonMemberTerm'] = new_member['nonMemberTerm'][:]
for term in term_list:
# check term syntax
if not re.match('^[wsf][0-9]{4}$', term):
raise InvalidTerm(term)
# add the term to the entry
if not term in ldap_member['nonMemberTerm'] \
and not term in ldap_member['term']:
new_member['nonMemberTerm'].append(term)
mlist = ldapi.make_modlist(ldap_member, new_member)
ld.modify_s(user_dn, mlist)
def registered(userid, term): def registered(userid, term):
""" """
Determines whether a member is registered Determines whether a member is registered

View File

@ -55,8 +55,10 @@ syscom_data = {
def main_menu(): def main_menu():
menu = [ menu = [
("New Member", new_member, None), ("New Member", new_member, None),
("New Club Rep", new_club_user, None),
("Renew Membership", renew_member, None), ("Renew Membership", renew_member, None),
("Create Club Account", new_club, None), ("Renew Club Rep", renew_club_user, None),
("New Club", new_club, None),
("Display Member", display_member, None), ("Display Member", display_member, None),
("Change Shell", change_shell, None), ("Change Shell", change_shell, None),
("Search", search_members, None), ("Search", search_members, None),
@ -86,6 +88,15 @@ def new_club(*args, **kwargs):
(newmember.EndPage, "club"), (newmember.EndPage, "club"),
], (60, 15)) ], (60, 15))
def new_club_user(*args, **kwargs):
push_wizard("New Club Rep Account", [
newmember.ClubUserIntroPage,
newmember.InfoPage,
newmember.SignPage,
newmember.PassPage,
(newmember.EndPage, "clubuser"),
], (60, 15))
def manage_group(*args, **kwargs): def manage_group(*args, **kwargs):
push_wizard("Manage Club or Group Members", [ push_wizard("Manage Club or Group Members", [
groups.IntroPage, groups.IntroPage,
@ -101,6 +112,14 @@ def renew_member(*args, **kwargs):
renew.EndPage, renew.EndPage,
]) ])
def renew_club_user(*args, **kwargs):
push_wizard("Renew Club Rep Account", [
renew.ClubUserIntroPage,
renew.UserPage,
(renew.TermPage, "clubuser"),
(renew.EndPage, "clubuser"),
], (60, 15))
def display_member(data): def display_member(data):
push_wizard("Display Member", [ push_wizard("Display Member", [
renew.UserPage, renew.UserPage,

View File

@ -17,19 +17,32 @@ class IntroPage(WizardPanel):
class ClubIntroPage(WizardPanel): class ClubIntroPage(WizardPanel):
def init_widgets(self): def init_widgets(self):
self.widgets = [ self.widgets = [
urwid.Text( "Club Services" ), urwid.Text( "Club Accounts" ),
urwid.Divider(), urwid.Divider(),
urwid.Text( "We provide other UW clubs accounts for email and " urwid.Text( "We provide other UW clubs accounts for email and "
"web hosting, free of charge. Like members, clubs " "web hosting, free of charge. Like members, clubs "
"get web hosting at %s. We can also arrange for " "get web hosting at %s. We can also arrange for "
"uwaterloo.ca subdomains; please instruct the club " "uwaterloo.ca subdomains; please instruct the club "
"representative to contact the systems committee " "representative to contact the systems committee "
"for more information." "for more information. Club accounts do not have "
"\n\nNote: This is not complete. Authorizing members " "passwords, and exist primarily to own club data. "
"to access the club account still requires manual " % "http://csclub.uwaterloo.ca/~clubid/" ),
"intervention." ]
% "http://csclub.uwaterloo.ca/~clubid/" def focusable(self):
) return False
class ClubUserIntroPage(WizardPanel):
def init_widgets(self):
self.widgets = [
urwid.Text( "Club Rep Account" ),
urwid.Divider(),
urwid.Text( "This is for people who need access to a club account, "
"but are not currently interested in full CSC membership. "
"Registering a user in this way grants one term of free "
"access to our machines, without any other membership "
"privileges (they can't vote, hold office, etc). If such "
"a user later decides to join, use the Renew Membership "
"option." ),
] ]
def focusable(self): def focusable(self):
return False return False
@ -150,6 +163,9 @@ class EndPage(WizardPanel):
if self.utype == 'member': if self.utype == 'member':
members.create_member( self.state['userid'], self.state['password'], self.state['name'], self.state['program'] ) members.create_member( self.state['userid'], self.state['password'], self.state['name'], self.state['program'] )
members.register( self.state['userid'], terms.current() ) members.register( self.state['userid'], terms.current() )
elif self.utype == 'clubuser':
members.create_member( self.state['userid'], self.state['password'], self.state['name'], self.state['program'] )
members.register_nonmember( self.state['userid'], terms.current() )
elif self.utype == 'club': elif self.utype == 'club':
members.create_club( self.state['userid'], self.state['name'] ) members.create_club( self.state['userid'], self.state['name'] )
else: else:

View File

@ -14,6 +14,21 @@ class IntroPage(WizardPanel):
def focusable(self): def focusable(self):
return False return False
class ClubUserIntroPage(IntroPage):
def init_widgets(self):
self.widgets = [
urwid.Text( "Renewing Club User Account" ),
urwid.Divider(),
urwid.Text( "In order for clubs to maintain websites hosted by "
"the Computer Science Club, they need access to our "
"machines. We grant accounts to club users at no charge "
"in order to provide this access. Registering a user "
"in this way grants one term of free access to our "
"machines, without any other membership privileges "
"(they can't vote, hold office, etc). If such a user "
"decides to join, use the Renew Membership option." )
]
class UserPage(WizardPanel): class UserPage(WizardPanel):
def init_widgets(self): def init_widgets(self):
self.userid = LdapWordEdit(csclub_uri, csclub_base, 'uid', self.userid = LdapWordEdit(csclub_uri, csclub_base, 'uid',
@ -35,6 +50,9 @@ class UserPage(WizardPanel):
return True return True
class TermPage(WizardPanel): class TermPage(WizardPanel):
def __init__(self, state, utype='member'):
self.utype = utype
WizardPanel.__init__(self, state)
def init_widgets(self): def init_widgets(self):
self.start = SingleEdit("Start: ") self.start = SingleEdit("Start: ")
self.count = SingleIntEdit("Count: ") self.count = SingleIntEdit("Count: ")
@ -47,10 +65,14 @@ class TermPage(WizardPanel):
] ]
def activate(self): def activate(self):
if not self.start.get_edit_text(): if not self.start.get_edit_text():
old_terms = [] self.terms = self.state['member'].get('term', [])
if 'term' in self.state['member']: self.nmterms = self.state['member'].get('nonMemberTerm', [])
old_terms = self.state['member']['term']
self.start.set_edit_text( terms.next_unregistered( old_terms ) ) if self.utype == 'member':
self.start.set_edit_text( terms.next_unregistered( self.terms ) )
else:
self.start.set_edit_text( terms.next_unregistered( self.terms + self.nmterms ) )
self.count.set_edit_text( "1" ) self.count.set_edit_text( "1" )
def check(self): def check(self):
try: try:
@ -60,7 +82,12 @@ class TermPage(WizardPanel):
set_status( "Invalid start term" ) set_status( "Invalid start term" )
return True return True
for term in self.state['terms']: for term in self.state['terms']:
if members.registered( self.state['userid'], term): if self.utype == 'member':
already = term in self.terms
else:
already = term in self.terms or term in self.nmterms
if already:
self.focus_widget( self.start ) self.focus_widget( self.start )
set_status( "Already registered for " + term ) set_status( "Already registered for " + term )
return True return True
@ -91,6 +118,9 @@ class PayPage(WizardPanel):
"continuing. " % ( len(regterms), plural, len(regterms * 2))) "continuing. " % ( len(regterms), plural, len(regterms * 2)))
class EndPage(WizardPanel): class EndPage(WizardPanel):
def __init__(self, state, utype='member'):
self.utype = utype
WizardPanel.__init__(self, state)
def init_widgets(self): def init_widgets(self):
self.headtext = urwid.Text("") self.headtext = urwid.Text("")
self.midtext = urwid.Text("") self.midtext = urwid.Text("")
@ -105,10 +135,15 @@ class EndPage(WizardPanel):
def activate(self): def activate(self):
problem = None problem = None
try: try:
members.register( self.state['userid'], self.state['terms'] )
self.headtext.set_text("Registration Succeeded") self.headtext.set_text("Registration Succeeded")
self.midtext.set_text("The member has been registered for the following " if self.utype == 'member':
"terms: " + ", ".join(self.state['terms']) + ".") members.register( self.state['userid'], self.state['terms'] )
self.midtext.set_text("The member has been registered for the following "
"terms: " + ", ".join(self.state['terms']) + ".")
else:
members.register_nonmember( self.state['userid'], self.state['terms'] )
self.midtext.set_text("The club user has been registered for the following "
"terms: " + ", ".join(self.state['terms']) + ".")
except ldap.LDAPError, e: except ldap.LDAPError, e:
problem = ldapi.format_ldaperror(e) problem = ldapi.format_ldaperror(e)
except members.MemberException, e: except members.MemberException, e:

View File

@ -16,10 +16,14 @@ attributetype ( 1.3.6.1.4.1.27934.1.1.4 NAME 'position'
EQUALITY caseIgnoreIA5Match EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} )
attributetype ( 1.3.6.1.4.1.27934.1.1.5 NAME 'nonMemberTerm'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{5} )
objectclass ( 1.3.6.1.4.1.27934.1.2.1 NAME 'member' objectclass ( 1.3.6.1.4.1.27934.1.2.1 NAME 'member'
SUP top AUXILIARY SUP top AUXILIARY
MUST ( cn $ uid ) MUST ( cn $ uid )
MAY ( studentid $ program $ term $ description $ position ) ) MAY ( studentid $ program $ term $ nonMemberTerm $ description $ position ) )
objectclass ( 1.3.6.1.4.1.27934.1.2.2 NAME 'club' objectclass ( 1.3.6.1.4.1.27934.1.2.2 NAME 'club'
SUP top AUXILIARY SUP top AUXILIARY