Implement required groups, fix LDAP problems with empty strings.

This commit is contained in:
Ricky Zhou (周家杰) 2007-09-14 19:07:31 -07:00
parent ae5cd66631
commit 44020c6d25
8 changed files with 85 additions and 32 deletions

View file

@ -89,7 +89,7 @@ def canViewGroup(userName, groupName, g=None):
if re.compile(privilegedViewGroups).match(groupName):
if not g:
g = Groups.byUserName(userName)
if canAdminGroup(userName, groupName):
if canAdminGroup(userName, groupName, g):
return True
else:
return False
@ -97,9 +97,18 @@ def canViewGroup(userName, groupName, g=None):
return True
def canApplyGroup(userName, groupName, applyUserName, g=None):
# This is where we could make groups depend on other ones.
if not g:
g = Groups.byUserName(userName)
# User must satisfy all dependencies to join.
# This is bypassed for people already in the group and for the
# owner of the group (when they initially make it).
group = Groups.groups(groupName)[groupName]
requirements = group.fedoraGroupRequires.split()
for req in requirements:
try:
g[req].cn
except KeyError:
return False
# A user can apply themselves, and FAS admins can apply other people.
if (userName == applyUserName) or \
isAdmin(userName, g):

View file

@ -60,13 +60,15 @@ class Server(object):
''' Modify an attribute, requires write access '''
if new in (old, 'None'):
return None
if old == None:
old = 'None'
o = { attribute : old }
n = { attribute : new }
ldif = ldap.modlist.modifyModlist(o, n)
#o = { attribute : old }
#n = { attribute : new }
ldif = []
ldif.append((ldap.MOD_DELETE,attribute,None))
ldif.append((ldap.MOD_ADD,attribute,new))
#ldif = ldap.modlist.modifyModlist(o, n, ignore_oldexistent=1)
# commit
self.ldapConn.modify_s(base, ldif)
@ -103,13 +105,14 @@ class Group(object):
__server = Server()
__base = 'ou=FedoraGroups,dc=fedoraproject,dc=org'
def __init__(self, cn, fedoraGroupDesc, fedoraGroupOwner, fedoraGroupType, fedoraGroupNeedsSponsor, fedoraGroupUserCanRemove, fedoraGroupJoinMsg):
def __init__(self, cn, fedoraGroupDesc, fedoraGroupOwner, fedoraGroupType, fedoraGroupNeedsSponsor, fedoraGroupUserCanRemove, fedoraGroupRequires, fedoraGroupJoinMsg):
self.cn = cn
self.fedoraGroupDesc = fedoraGroupDesc
self.fedoraGroupOwner = fedoraGroupOwner
self.fedoraGroupType = fedoraGroupType
self.fedoraGroupNeedsSponsor = fedoraGroupNeedsSponsor
self.fedoraGroupUserCanRemove = fedoraGroupUserCanRemove
self.fedoraGroupRequires = fedoraGroupRequires
self.fedoraGroupJoinMsg = fedoraGroupJoinMsg
def __json__(self):
@ -119,11 +122,12 @@ class Group(object):
'fedoraGroupType': self.fedoraGroupType,
'fedoraGroupNeedsSponsor': self.fedoraGroupNeedsSponsor,
'fedoraGroupUserCanRemove': self.fedoraGroupUserCanRemove,
'fedoraGroupRequires': self.fedoraGroupRequires,
'fedoraGroupJoinMsg': self.fedoraGroupJoinMsg
}
@classmethod
def newGroup(self, cn, fedoraGroupDesc, fedoraGroupOwner, fedoraGroupNeedsSponsor, fedoraGroupUserCanRemove, fedoraGroupJoinMsg):
def newGroup(self, cn, fedoraGroupDesc, fedoraGroupOwner, fedoraGroupNeedsSponsor, fedoraGroupUserCanRemove, fedoraGroupRequires, fedoraGroupJoinMsg):
''' Create a new group '''
attributes = { 'cn' : cn,
'objectClass' : ('fedoraGroup'),
@ -132,6 +136,7 @@ class Group(object):
'fedoraGroupType' : '1',
'fedoraGroupNeedsSponsor' : fedoraGroupNeedsSponsor,
'fedoraGroupUserCanRemove' : fedoraGroupUserCanRemove,
'fedoraGroupRequires' : fedoraGroupRequires,
'fedoraGroupJoinMsg' : fedoraGroupJoinMsg,
}
@ -225,6 +230,7 @@ class Groups(object):
fedoraGroupType = group[0][1]['fedoraGroupType'][0],
fedoraGroupNeedsSponsor = group[0][1]['fedoraGroupNeedsSponsor'][0],
fedoraGroupUserCanRemove = group[0][1]['fedoraGroupUserCanRemove'][0],
fedoraGroupRequires = group[0][1]['fedoraGroupRequires'][0],
fedoraGroupJoinMsg = group[0][1]['fedoraGroupJoinMsg'][0])
else:
return None
@ -426,9 +432,13 @@ class Person(object):
if not ldapServer:
s = Server()
ldapServer = s.ldapConn
who = 'cn=%s,ou=People,dc=fedoraproject,dc=org' % who
try:
ldapServer.simple_bind_s(who, password)
except NO_SUCH_OBJECT:
raise AuthError
except INVALID_CREDENTIALS:
raise AuthError
def upgrade(self, group):
''' Upgrade user in group '''

View file

@ -24,6 +24,16 @@ class knownGroup(validators.FancyValidator):
if not g:
raise validators.Invalid(_("The group '%s' does not exist.") % value, value, state)
class groupsExist(validators.FancyValidator):
'''Make sure that required groups already exist'''
def _to_python(self, value, state):
return value.strip()
def validate_python(self, value, state):
for group in value.split():
g = Groups.groups(group)
if not g:
raise validators.Invalid(_("The required group '%s' does not exist.") % value, value, state)
class unknownGroup(validators.FancyValidator):
'''Make sure that a group doesn't already exist'''
def _to_python(self, value, state):
@ -37,11 +47,13 @@ class createGroup(validators.Schema):
groupName = validators.All(unknownGroup(not_empty=True, max=10), validators.String(max=32, min=3))
fedoraGroupDesc = validators.NotEmpty
fedoraGroupOwner = validators.All(knownUser(not_empty=True, max=10), validators.String(max=32, min=3))
fedoraGroupRequires = groupsExist
class editGroup(validators.Schema):
groupName = validators.All(knownGroup(not_empty=True, max=10), validators.String(max=32, min=3))
fedoraGroupDesc = validators.NotEmpty
fedoraGroupOwner = validators.All(knownUser(not_empty=True, max=10), validators.String(max=32, min=3))
fedoraGroupRequires = groupsExist
class userNameGroupNameExists(validators.Schema):
groupName = validators.All(knownGroup(not_empty=True, max=10), validators.String(max=32, min=3))
@ -77,10 +89,10 @@ class Group(controllers.Controller):
turbogears.redirect('/')
return dict(tg_errors=tg_errors)
@identity.require(turbogears.identity.not_anonymous())
@validate(validators=groupNameExists())
@error_handler(error)
@expose(template="fas.templates.group.view")
@identity.require(turbogears.identity.not_anonymous())
def view(self, groupName):
'''View group'''
userName = turbogears.identity.current.user_name
@ -108,8 +120,8 @@ class Group(controllers.Controller):
value = {'groupName': groupName}
return dict(userName=userName, groups=groups, group=group, me=me, value=value)
@expose(template="fas.templates.group.new")
@identity.require(turbogears.identity.not_anonymous())
@expose(template="fas.templates.group.new")
def new(self):
'''Display create group form'''
userName = turbogears.identity.current.user_name
@ -118,11 +130,11 @@ class Group(controllers.Controller):
turbogears.redirect('/')
return dict()
@identity.require(turbogears.identity.not_anonymous())
@validate(validators=createGroup())
@error_handler(error)
@expose(template="fas.templates.group.new")
@identity.require(turbogears.identity.not_anonymous())
def create(self, groupName, fedoraGroupDesc, fedoraGroupOwner, fedoraGroupNeedsSponsor="FALSE", fedoraGroupUserCanRemove="FALSE", fedoraGroupJoinMsg=""):
def create(self, groupName, fedoraGroupDesc, fedoraGroupOwner, fedoraGroupNeedsSponsor="FALSE", fedoraGroupUserCanRemove="FALSE", fedoraGroupRequires="", fedoraGroupJoinMsg=""):
'''Create a group'''
userName = turbogears.identity.current.user_name
if not canCreateGroup(userName):
@ -134,6 +146,7 @@ class Group(controllers.Controller):
fedoraGroupOwner.encode('utf8'),
fedoraGroupNeedsSponsor.encode('utf8'),
fedoraGroupUserCanRemove.encode('utf8'),
fedoraGroupRequires.encode('utf8'),
fedoraGroupJoinMsg.encode('utf8'),)
except:
@ -153,8 +166,10 @@ class Group(controllers.Controller):
turbogears.redirect('/group/view/%s' % groupName)
return dict()
@expose(template="fas.templates.group.edit")
@identity.require(turbogears.identity.not_anonymous())
@validate(validators=groupNameExists())
@error_handler(error)
@expose(template="fas.templates.group.edit")
def edit(self, groupName):
'''Display edit group form'''
userName = turbogears.identity.current.user_name
@ -168,17 +183,19 @@ class Group(controllers.Controller):
'fedoraGroupType': group.fedoraGroupType,
'fedoraGroupNeedsSponsor': (group.fedoraGroupNeedsSponsor.upper() == 'TRUE'),
'fedoraGroupUserCanRemove': (group.fedoraGroupUserCanRemove.upper() == 'TRUE'),
#'fedoraGroupRequires': group.fedoraGroupRequires,
'fedoraGroupRequires': group.fedoraGroupRequires,
'fedoraGroupJoinMsg': group.fedoraGroupJoinMsg, }
return dict(value=value)
@identity.require(turbogears.identity.not_anonymous())
@validate(validators=editGroup())
@error_handler(error)
@expose()
@identity.require(turbogears.identity.not_anonymous())
def save(self, groupName, fedoraGroupDesc, fedoraGroupOwner, fedoraGroupType=1, fedoraGroupNeedsSponsor="FALSE", fedoraGroupUserCanRemove="FALSE", fedoraGroupJoinMsg=""):
def save(self, groupName, fedoraGroupDesc, fedoraGroupOwner, fedoraGroupType=1, fedoraGroupNeedsSponsor="FALSE", fedoraGroupUserCanRemove="FALSE", fedoraGroupRequires="", fedoraGroupJoinMsg=""):
'''Edit a group'''
userName = turbogears.identity.current.user_name
if fedoraGroupRequires == None:
fedoraGroupRequires = ""
if not canEditGroup(userName, groupName):
turbogears.flash(_("You cannot edit '%s'.") % groupName)
turbogears.redirect('/group/view/%s' % groupName)
@ -191,6 +208,7 @@ class Group(controllers.Controller):
server.modify(base, 'fedoraGroupType', str(fedoraGroupType).encode('utf8'))
server.modify(base, 'fedoraGroupNeedsSponsor', fedoraGroupNeedsSponsor.encode('utf8'))
server.modify(base, 'fedoraGroupUserCanRemove', fedoraGroupUserCanRemove.encode('utf8'))
server.modify(base, 'fedoraGroupRequires', fedoraGroupRequires.encode('utf8'))
server.modify(base, 'fedoraGroupJoinMsg', fedoraGroupJoinMsg.encode('utf8'))
try:
1
@ -201,8 +219,8 @@ class Group(controllers.Controller):
turbogears.redirect('/group/view/%s' % groupName)
return dict()
@expose(template="fas.templates.group.list", allow_json=True)
@identity.require(turbogears.identity.not_anonymous())
@expose(template="fas.templates.group.list", allow_json=True)
def list(self, search='*'):
groups = Groups.groups(search)
userName = turbogears.identity.current.user_name
@ -216,17 +234,17 @@ class Group(controllers.Controller):
return ({'groups': groups})
return dict(groups=groups, search=search, myGroups=myGroups)
@identity.require(turbogears.identity.not_anonymous())
@validate(validators=userNameGroupNameExists())
@error_handler(error)
@expose(template='fas.templates.group.view')
@identity.require(turbogears.identity.not_anonymous())
def apply(self, groupName, userName=None):
'''Apply to a group'''
applicant = turbogears.identity.current.user_name
if not userName:
userName = applicant
if not canApplyGroup(applicant, groupName, userName):
turbogears.flash(_('You cannot apply %(user)s for %(group)s!') % \
turbogears.flash(_('%(user)s could not apply to %(group)s!') % \
{'user': userName, 'group': groupName})
turbogears.redirect('/group/view/%s' % groupName)
return dict()
@ -242,10 +260,10 @@ class Group(controllers.Controller):
turbogears.redirect('/group/view/%s' % groupName)
return dict()
@identity.require(turbogears.identity.not_anonymous())
@validate(validators=userNameGroupNameExists())
@error_handler(error)
@expose(template='fas.templates.group.view')
@identity.require(turbogears.identity.not_anonymous())
def sponsor(self, groupName, userName):
'''Sponsor user'''
sponsor = turbogears.identity.current.user_name
@ -265,10 +283,10 @@ class Group(controllers.Controller):
turbogears.redirect('/group/view/%s' % groupName)
return dict()
@identity.require(turbogears.identity.not_anonymous())
@validate(validators=userNameGroupNameExists())
@error_handler(error)
@expose(template='fas.templates.group.view')
@identity.require(turbogears.identity.not_anonymous())
def remove(self, groupName, userName):
'''Remove user from group'''
# TODO: Add confirmation?
@ -290,10 +308,10 @@ class Group(controllers.Controller):
turbogears.redirect('/group/view/%s' % groupName)
return dict()
@identity.require(turbogears.identity.not_anonymous())
@validate(validators=userNameGroupNameExists())
@error_handler(error)
@expose(template='fas.templates.group.view')
@identity.require(turbogears.identity.not_anonymous())
def upgrade(self, groupName, userName):
'''Upgrade user in group'''
sponsor = turbogears.identity.current.user_name
@ -316,10 +334,10 @@ class Group(controllers.Controller):
turbogears.redirect('/group/view/%s' % groupName)
return dict()
@identity.require(turbogears.identity.not_anonymous())
@validate(validators=userNameGroupNameExists())
@error_handler(error)
@expose(template='fas.templates.group.view')
@identity.require(turbogears.identity.not_anonymous())
def downgrade(self, groupName, userName):
'''Upgrade user in group'''
sponsor = turbogears.identity.current.user_name
@ -342,10 +360,10 @@ class Group(controllers.Controller):
turbogears.redirect('/group/view/%s' % groupName)
return dict()
@identity.require(turbogears.identity.not_anonymous())
@validate(validators=groupNameExists())
@error_handler(error)
@expose(template="genshi-text:fas.templates.group.dump", format="text", content_type='text/plain; charset=utf-8')
@identity.require(turbogears.identity.not_anonymous())
def dump(self, groupName):
userName = turbogears.identity.current.user_name
if not canViewGroup(userName, groupName):

View file

@ -27,6 +27,10 @@
<input py:if="value['fedoraGroupUserCanRemove']" type="checkbox" id="fedoraGroupUserCanRemove" name="fedoraGroupUserCanRemove" value="TRUE" checked="checked" />
<input py:if="not value['fedoraGroupUserCanRemove']" type="checkbox" id="fedoraGroupUserCanRemove" name="fedoraGroupUserCanRemove" value="TRUE" />
</div>
<div class="field">
<label for="fedoraGroupRequires">Must Belong To:</label>
<input type="text" id="fedoraGroupRequires" name="fedoraGroupRequires" value="${value['fedoraGroupRequires']}" />
</div>
<div class="field">
<label for="fedoraGroupJoinMsg">Group Join Message:</label>
<input type="text" id="fedoraGroupJoinMsg" name="fedoraGroupJoinMsg" value="${value['fedoraGroupJoinMsg']}" />

View file

@ -29,6 +29,10 @@
<label for="fedoraGroupUserCanRemove">Self Removal:</label>
<input type="checkbox" id="fedoraGroupUserCanRemove" name="fedoraGroupUserCanRemove" value="TRUE" checked="checked" />
</div>
<div class="field">
<label for="fedoraGroupRequires">Must Belong To:</label>
<input type="text" id="fedoraGroupRequires" name="fedoraGroupRequires" value="cla_done" />
</div>
<div class="field">
<label for="fedoraGroupJoinMsg">Join Message:</label>
<input type="text" id="fedoraGroupJoinMsg" name="fedoraGroupJoinMsg" />

View file

@ -84,6 +84,10 @@ class changePass(validators.Schema):
passwordCheck = validators.String()
chained_validators = [validators.FieldsMatch('password', 'passwordCheck')]
class userNameExists(validators.Schema):
userName = validators.All(knownUser(not_empty=True, max=10), validators.String(max=32, min=3))
class userNameExists(validators.Schema):
userName = validators.All(knownUser(not_empty=True, max=10), validators.String(max=32, min=3))
@ -137,8 +141,10 @@ class User(controllers.Controller):
claDone=None
return dict(user=user, groups=groups, groupsPending=groupsPending, groupdata=groupdata, claDone=claDone, personal=personal, admin=admin)
@expose(template="fas.templates.user.edit")
@identity.require(turbogears.identity.not_anonymous())
@validate(validators=userNameExists())
@error_handler(error)
@expose(template="fas.templates.user.edit")
def edit(self, userName=None):
'''Edit a user
'''
@ -159,6 +165,7 @@ class User(controllers.Controller):
'description': user.description, }
return dict(value=value)
@identity.require(turbogears.identity.not_anonymous())
@validate(validators=editUser())
@error_handler(error)
@expose(template='fas.templates.user.edit')
@ -192,8 +199,8 @@ class User(controllers.Controller):
'description': description, }
return dict(value=value)
@identity.require(turbogears.identity.in_group("accounts")) #TODO: Use auth.py
@expose(template="fas.templates.user.list")
@identity.require(turbogears.identity.in_group("accounts"))
def list(self, search="a*"):
'''List users
'''
@ -248,15 +255,15 @@ class User(controllers.Controller):
turbogears.redirect('/user/new')
return dict()
@expose(template="fas.templates.user.changepass")
@identity.require(turbogears.identity.not_anonymous())
@expose(template="fas.templates.user.changepass")
def changepass(self):
return dict()
@identity.require(turbogears.identity.not_anonymous())
@validate(validators=changePass())
@error_handler(error)
@expose(template="fas.templates.user.changepass")
@identity.require(turbogears.identity.not_anonymous())
def setpass(self, currentPassword, password, passwordCheck):
userName = turbogears.identity.current.user_name
try:

View file

@ -14,4 +14,4 @@ attributeTypes: ( 2.5.444.13 NAME 'fedoraGroupUserCanRemove' DESC 'boolean indic
attributeTypes: ( 2.5.444.14 NAME 'fedoraGroupJoinMsg' DESC 'message received upon joining the group' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1000} )
attributeTypes: ( 2.5.444.21 NAME 'fedoraGroupDesc' DESC 'group description' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{100} )
attributeTypes: ( 2.5.444.20 NAME 'fedoraGroupRequires' DESC 'Requisites of this Group' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{50} )
objectClasses: ( 2.5.555.3 NAME 'fedoraGroup' DESC 'A object describing a group entry' STRUCTURAL MUST ( cn $ fedoraGroupDesc $ fedoraGroupOwner ) MAY ( fedoraGroupJoinMsg $ fedoraGroupUsercanRemove $ fedoraGroupType $ fedoraGroupNeedsSponsor $ fedoraGroupUserCanRemove $ fedoraGroupRequires ) )
objectClasses: ( 2.5.555.3 NAME 'fedoraGroup' DESC 'A object describing a group entry' STRUCTURAL MUST ( cn $ fedoraGroupDesc $ fedoraGroupOwner ) MAY ( fedoraGroupJoinMsg $ fedoraGroupUsercanRemove $ fedoraGroupType $ fedoraGroupNeedsSponsor $ fedoraGroupRequires ) )

View file

@ -342,6 +342,7 @@ def main():
userLdif.append(["fedoraGroupUserCanRemove",[str(group[4])]]) #need to convert to bool
userLdif.append(["fedoraGroupDesc",[str('Please fill out a Group Description')]]) #need to convert to bool
#userLdif.append(["groupPrerequisite",[str(group[5])]])
userLdif.append(["fedoraGroupRequires",[str(group[5])]]) # <- Hope this is added properly - Ricky
#userLdif.append(["groupPrerequisite",prereq]) not currently in the schema
userLdif.append(["fedoraGroupJoinMsg",[str(group[6]) or "None" ]])
ldifWriter.unparse("cn=" + str(group[7]) +",ou=FedoraGroups,dc=fedoraproject,dc=org" , userLdif )