Merge branch 'master' of ssh://git.fedorahosted.org/git/fedora-infrastructure

Fix Conflicts with the latest fix.
This commit is contained in:
Toshio Kuratomi 2008-02-26 22:24:47 -08:00
commit 9e9ee86ec2
8 changed files with 86 additions and 61 deletions

View file

@ -37,11 +37,13 @@ def canAdminGroup(person, group):
return True return True
else: else:
try: try:
role = PersonRoles.query.filter_by(group_id=g.id, person_id=p.id).one() role = PersonRoles.query.filter_by(group_id=group.id, person_id=person.id).one()
except IndexError: except IndexError:
''' Not in the group ''' ''' Not in the group '''
return False return False
if r.role_status == 'approved' and r.role_type == 'administrator': except InvalidRequestError:
return False
if role.role_status == 'approved' and role.role_type == 'administrator':
return True return True
return False return False
@ -165,16 +167,22 @@ def canApplyGroup(person, group, applicant):
# owner of the group (when they initially make it). # owner of the group (when they initially make it).
prerequisite = group.prerequisite prerequisite = group.prerequisite
# TODO: Make this return more useful info. # TODO: Make this return more useful info.
if prequisite:
if prerequisite:
if prerequisite in person.approved_memberships: if prerequisite in person.approved_memberships:
pass pass
else: else:
print "GOT HERE %s" % prerequisite
turbogears.flash(_('%s membership required before application to this group is allowed' % prerequisite.name))
return False return False
# A user can apply themselves, and FAS admins can apply other people. # A user can apply themselves, and FAS admins can apply other people.
if (username == applicant) or \
if (person == applicant) or \
canAdminGroup(person, group): canAdminGroup(person, group):
return True return True
else: else:
turbogears.flash(_('%s membership required before application to this group is allowed' % prerequisite.name))
return False return False
def canSponsorUser(person, group, target): def canSponsorUser(person, group, target):
@ -197,10 +205,12 @@ def canRemoveUser(person, group, target):
return False return False
# A user can remove themself from a group if user_can_remove is 1 # A user can remove themself from a group if user_can_remove is 1
# Otherwise, a sponsor can remove sponsors/users. # Otherwise, a sponsor can remove sponsors/users.
elif ((person == target) and (group.user_can_remove == 1)) or \ elif ((person == target) and (group.user_can_remove == True)) or \
canSponsorGroup(person, group): canSponsorGroup(person, group):
print "GOT HERE TRUE"
return True return True
else: else:
print "GOT HERE FALSE"
return False return False
def canUpgradeUser(person, group, target): def canUpgradeUser(person, group, target):

View file

@ -58,7 +58,7 @@ class editGroup(validators.Schema):
class usernameGroupnameExists(validators.Schema): class usernameGroupnameExists(validators.Schema):
groupname = validators.All(knownGroup(not_empty=True, max=10), validators.String(max=32, min=3)) groupname = validators.All(knownGroup(not_empty=True, max=10), validators.String(max=32, min=3))
username = validators.All(knownUser(not_empty=True, max=10), validators.String(max=32, min=3)) targetname = validators.All(knownUser(not_empty=True, max=10), validators.String(max=32, min=3))
class groupnameExists(validators.Schema): class groupnameExists(validators.Schema):
groupname = validators.All(knownGroup(not_empty=True, max=10), validators.String(max=32, min=3)) groupname = validators.All(knownGroup(not_empty=True, max=10), validators.String(max=32, min=3))
@ -174,8 +174,8 @@ class Group(controllers.Controller):
return dict() return dict()
else: else:
try: try:
session.flush()
owner.apply(group, person) # Apply... owner.apply(group, person) # Apply...
session.flush()
owner.sponsor(group, person) owner.sponsor(group, person)
owner.upgrade(group, person) owner.upgrade(group, person)
owner.upgrade(group, person) owner.upgrade(group, person)
@ -265,8 +265,8 @@ class Group(controllers.Controller):
group = Groups.by_name(groupname) group = Groups.by_name(groupname)
if not canApplyGroup(person, group, target): if not canApplyGroup(person, group, target):
turbogears.flash(_('%(user)s could not apply to %(group)s.') % \ # turbogears.flash(_('%(user)s could not apply to %(group)s.') % \
{'user': target.username, 'group': group.name }) # {'user': target.username, 'group': group.name })
turbogears.redirect('/group/view/%s' % group.name) turbogears.redirect('/group/view/%s' % group.name)
return dict() return dict()
else: else:
@ -277,16 +277,18 @@ class Group(controllers.Controller):
{'user': target.username, 'group': group.name}) {'user': target.username, 'group': group.name})
else: else:
import turbomail import turbomail
# TODO: CC to right place, put a bit more thought into how to most elegantly do this # TODO: CC to right place, put a bit more thought into how to most elegantly do this
message = turbomail.Message(config.get('accounts_mail'), '%s-sponsors@fedoraproject.org' % group.name, \ message = turbomail.Message(config.get('accounts_mail'), '%s-sponsors@fedoraproject.org' % group.name, \
"Fedora '%(group)s' sponsor needed for %(user)s" % {'user': target.username, 'group': group.name}) "Fedora '%(group)s' sponsor needed for %(user)s" % {'user': target.username, 'group': group.name})
url = config.get('base_url') + turbogears.url('/group/edit/%s' % groupname) url = config.get('base_url_filter.base_url') + turbogears.url('/group/edit/%s' % groupname)
message.plain = dedent(''' message.plain = dedent('''
Fedora user %(user)s, aka %(name)s <%(email)s> has requested Fedora user %(user)s, aka %(name)s <%(email)s> has requested
membership for %(applicant) (%(applicant_name)) in the %(group) group and needs a sponsor. membership for %(applicant)s (%(applicant_name)s) in the %(group)s group and needs a sponsor.
Please go to %(url)s to take action. Please go to %(url)s to take action.
''') % {'user': person.username, 'name': person.human_name, 'applicant': target.username, 'applicant_name': target.human_name, 'email': person.emails['primary'].email, 'url': url} ''' % {'user': person.username, 'name': person.human_name, 'applicant': target.username, 'applicant_name': target.human_name, 'email': person.emails['primary'].email, 'url': url, 'group': group.name} )
turbomail.enqueue(message) turbomail.enqueue(message)
turbogears.flash(_('%(user)s has applied to %(group)s!') % \ turbogears.flash(_('%(user)s has applied to %(group)s!') % \
{'user': target.username, 'group': group.name}) {'user': target.username, 'group': group.name})
@ -338,23 +340,23 @@ class Group(controllers.Controller):
# TODO: Add confirmation? # TODO: Add confirmation?
username = turbogears.identity.current.user_name username = turbogears.identity.current.user_name
person = People.by_username(username) person = People.by_username(username)
target = People.by_username(targetname) requester = People.by_username(targetname)
group = Groups.by_name(groupname) group = Groups.by_name(groupname)
if not canRemoveUser(person, group, target): if not canRemoveUser(person, group, requester):
turbogears.flash(_("You cannot remove '%s'.") % target.username) turbogears.flash(_("You cannot remove '%s'.") % target.username)
turbogears.redirect('/group/view/%s' % group.name) turbogears.redirect('/group/view/%s' % group.name)
return dict() return dict()
else: else:
try: try:
group.remove_person(person, target) person.remove(group, requester)
except: except KeyError:
turbogears.flash(_('%(name)s could not be removed from %(group)s!') % \ turbogears.flash(_('%(name)s could not be removed from %(group)s!') % \
{'name': target.username, 'group': group.name}) {'name': requester.username, 'group': group.name})
turbogears.redirect('/group/view/%s' % group.name) turbogears.redirect('/group/view/%s' % group.name)
else: else:
import turbomail import turbomail
message = turbomail.Message(config.get('accounts_mail'), target.emails['primary'].email, "Your Fedora '%s' membership has been removed" % group.name) message = turbomail.Message(config.get('accounts_mail'), requester.emails['primary'].email, "Your Fedora '%s' membership has been removed" % group.name)
message.plain = dedent(''' message.plain = dedent('''
%(name)s <%(email)s> has removed you from the '%(group)s' %(name)s <%(email)s> has removed you from the '%(group)s'
group of the Fedora Accounts System This change is effective group of the Fedora Accounts System This change is effective
@ -363,7 +365,7 @@ class Group(controllers.Controller):
''') % {'group': group.name, 'name': person.human_name, 'email': person.emails['primary'].email} ''') % {'group': group.name, 'name': person.human_name, 'email': person.emails['primary'].email}
turbomail.enqueue(message) turbomail.enqueue(message)
turbogears.flash(_('%(name)s has been removed from %(group)s!') % \ turbogears.flash(_('%(name)s has been removed from %(group)s!') % \
{'name': target.username, 'group': group.name}) {'name': requester.username, 'group': group.name})
turbogears.redirect('/group/view/%s' % group.name) turbogears.redirect('/group/view/%s' % group.name)
return dict() return dict()

View file

@ -37,6 +37,8 @@ from sqlalchemy.orm.collections import column_mapped_collection
from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy import select, and_ from sqlalchemy import select, and_
from turbogears.database import session
from turbogears import identity from turbogears import identity
from fas.json import SABase from fas.json import SABase
@ -112,7 +114,7 @@ class People(SABase):
by_username = classmethod(by_username) by_username = classmethod(by_username)
# If we're going to do logging here, we'll have to pass the person that did the applying. # If we're going to do logging here, we'll have to pass the person that did the applying.
def apply(cls, group, requestor): def apply(cls, group, requester):
''' '''
Apply a person to a group Apply a person to a group
''' '''
@ -122,9 +124,9 @@ class People(SABase):
role.member = cls role.member = cls
role.group = group role.group = group
def approve(cls, group, requestor): def approve(cls, group, requester):
''' '''
Approve a person in a group - requestor for logging purposes Approve a person in a group - requester for logging purposes
''' '''
if group in cls.approved_memberships: if group in cls.approved_memberships:
raise '%s is already approved in %s' % (cls.username, group.name) raise '%s is already approved in %s' % (cls.username, group.name)
@ -132,9 +134,9 @@ class People(SABase):
role = PersonRoles.query.filter_by(person_id=cls.id, group_id=group.id).first() role = PersonRoles.query.filter_by(person_id=cls.id, group_id=group.id).first()
role.role_status = 'approved' role.role_status = 'approved'
def upgrade(cls, group, requestor): def upgrade(cls, group, requester):
''' '''
Upgrade a user in a group - requestor for logging purposes Upgrade a user in a group - requester for logging purposes
''' '''
if not group in cls.memberships: if not group in cls.memberships:
raise '%s not a member of %s' % (group.name, cls.memberships) raise '%s not a member of %s' % (group.name, cls.memberships)
@ -147,9 +149,9 @@ class People(SABase):
elif role.role_type == 'user': elif role.role_type == 'user':
role.role_type = 'sponsor' role.role_type = 'sponsor'
def downgrade(cls, group, requestor): def downgrade(cls, group, requester):
''' '''
Downgrade a user in a group - requestor for logging purposes Downgrade a user in a group - requester for logging purposes
''' '''
if not group in cls.memberships: if not group in cls.memberships:
raise '%s not a member of %s' % (group.name, cls.memberships) raise '%s not a member of %s' % (group.name, cls.memberships)
@ -162,20 +164,20 @@ class People(SABase):
elif role.role_type == 'administrator': elif role.role_type == 'administrator':
role.role_type = 'sponsor' role.role_type = 'sponsor'
def sponsor(cls, group, requestor): def sponsor(cls, group, requester):
# If we want to do logging, this might be the place. # If we want to do logging, this might be the place.
# TODO: Find out how to log timestamp # TODO: Find out how to log timestamp
if not group in cls.memberships: if not group in cls.memberships:
raise '%s not a member of %s' % (group.name, cls.memberships) raise '%s not a member of %s' % (group.name, cls.memberships)
role = PersonRoles.query.filter_by(person_id=cls.id, group_id=group.id).first() role = PersonRoles.query.filter_by(person_id=cls.id, group_id=group.id).first()
role.role_status = 'approved' role.role_status = 'approved'
role.sponsor_id = requestor.id role.sponsor_id = requester.id
def remove(cls, group, requestor): def remove(cls, group, requester):
role = PersonRoles.query.filter_by(person_id=cls.id, group_id=group.id).first() role = PersonRoles.query.filter_by(person_id=cls.id, group_id=group.id).first()
try: try:
session.delete(role) session.delete(role)
except: except TypeError:
pass pass
# Handle somehow. # Handle somehow.

View file

@ -39,11 +39,11 @@
<td><a href="${tg.url('/group/view/%s' % group.name)}">${group.name}</a></td> <td><a href="${tg.url('/group/view/%s' % group.name)}">${group.name}</a></td>
<td>${ group.display_name }</td> <td>${ group.display_name }</td>
<td> <td>
<a py:if="group in person.roles" href="${tg.url('/group/view/%s' % group)}"> <a py:if="group in person.memberships" href="${tg.url('/group/view/%s' % group.name)}">
<!--<span class="approved" py:if="myGroups[group].fedoraRoleStatus.lower() == 'approved'">${_('Approved')}</span> <span class="approved" py:if="group in person.approved_memberships">${_('Approved')}</span>
<span class="unapproved" py:if="myGroups[group].fedoraRoleStatus.lower() == 'unapproved'">${_('Unapproved')}</span>--> <span class="unapproved" py:if="group in person.unapproved_memberships">${_('Unapproved')}</span>
</a> </a>
<a py:if="group not in person.roles" href="${tg.url('/group/apply/%s/%s' % (group, person))}"><span>${_('Apply')}</span></a> <a py:if="group not in person.memberships" href="${tg.url('/group/apply/%s/%s' % (group.name, person.username))}"><span>${_('Apply')}</span></a>
</td> </td>
</div> </div>
</tr> </tr>

View file

@ -11,8 +11,8 @@
<h2>${group.display_name} (${group.name})</h2> <h2>${group.display_name} (${group.name})</h2>
<h3> <h3>
${_('My Status:')} ${_('My Status:')}
<span py:if="auth.isApproved(person, group)" class="approved">${_('Approved')}</span> <span py:if="group in person.memberships and group in person.approved_memberships" class="approved">${_('Approved')}</span>
<span py:if="not auth.isApproved(person, group)" class="unapproved">${_('Unapproved')}</span> <span py:if="group in person.memberships and not group in person.approved_memberships" class="unapproved">${_('Unapproved')}</span>
<span py:if="not group in person.memberships">${_('Not a Member')}</span> <span py:if="not group in person.memberships">${_('Not a Member')}</span>
</h3> </h3>
<form py:if="not group in person.memberships" action="${tg.url('/group/apply/%s/%s' % (group.name, person.username))}"> <form py:if="not group in person.memberships" action="${tg.url('/group/apply/%s/%s' % (group.name, person.username))}">
@ -22,7 +22,7 @@
</div> </div>
</form> </form>
<a py:if="group in person.memberships" href="${tg.url('/group/remove/%s/%s' % (group.name, person.username))}">${_('Remove me')}</a> <a py:if="group in person.memberships" href="${tg.url('/group/remove/%s/%s' % (group.name, person.username))}">${_('Remove me')}</a>
<h3>Group Details <a href="${tg.url('/group/edit/%s' % group.name)}">${_('(edit)')}</a></h3> <h3>Group Details <a py:if="auth.canAdminGroup(person, group)" href="${tg.url('/group/edit/%s' % group.name)}">${_('(edit)')}</a></h3>
<div class="userbox"> <div class="userbox">
<dl> <dl>
<dt>${_('Name:')}</dt><dd>${group.name}&nbsp;</dd> <dt>${_('Name:')}</dt><dd>${group.name}&nbsp;</dd>
@ -38,6 +38,9 @@
<span py:if="group.user_can_remove == 0" py:strip="">${_('No')}</span> <span py:if="group.user_can_remove == 0" py:strip="">${_('No')}</span>
&nbsp;</dd> &nbsp;</dd>
<dt>${_('Join Message:')}</dt><dd>${group.joinmsg}&nbsp;</dd> <dt>${_('Join Message:')}</dt><dd>${group.joinmsg}&nbsp;</dd>
<dt>${_('Prerequisite:')}</dt>
<dd py:if="group.prerequisite">${group.prerequisite.name}&nbsp;</dd>
<dd py:if="not group.prerequisite">&nbsp;</dd>
<dt>${_('Created:')}</dt><dd>${group.creation}&nbsp;</dd> <dt>${_('Created:')}</dt><dd>${group.creation}&nbsp;</dd>
</dl> </dl>
</div> </div>
@ -67,20 +70,20 @@
from datetime import datetime from datetime import datetime
from pytz import timezone from pytz import timezone
?> ?>
<td><!--${datetime.fromtimestamp(float(role.member.creation), timezone(role.member.timezone)).strftime('%F %R %Z')}--></td> <td>${role.member.creation}<!--${datetime.fromtimestamp(float(role.member.creation), timezone(role.member.timezone)).strftime('%F %R %Z')}--></td>
<td py:if="role.approval == 'none'">${role.member.creation}</td> <td py:if="role.approval == 'none'">${role.member.creation}</td>
<td py:if="role.approval != 'none'"><!--${datetime.fromtimestamp(float(role.member.creation), timezone(role.member.timezone)).strftime('%F %R %Z')}--></td> <td py:if="role.approval != 'none'">${role.member.timezone}<!--${datetime.fromtimestamp(float(role.member.creation), timezone(role.member.timezone)).strftime('%F %R %Z')}--></td>
<td>${role.role_status}</td> <td>${role.role_status}</td>
<td>${role.role_type}</td> <td>${role.role_type}</td>
<!--<td>${groups[user].fedoraRoleDomain}</td>--> <!--<td>${groups[user].fedoraRoleDomain}</td>-->
<!-- This section includes all action items --> <!-- This section includes all action items -->
<td py:if="auth.canSponsorGroup(role.member, group)"> <td py:if="auth.canSponsorGroup(role.member, group)">
<ul> <ul>
<!--
<li py:if="groups[user].fedoraRoleStatus.lower() != 'approved'"> <li py:if="group in role.member.memberships">
<a py:if="group.fedoraGroupNeedsSponsor.upper() == 'TRUE'" <a py:if="group in role.member.unapproved_memberships"
href="${tg.url('/group/sponsor/%s/%s' % (groups[user].cn, user))}">${_('Sponsor')}</a> href="${tg.url('/group/sponsor/%s/%s' % (group.name, role.member.username))}">${_('Sponsor')}</a>
<a py:if="not group.fedoraGroupNeedsSponsor.upper() == 'TRUE'" <!--<a py:if="not group.fedoraGroupNeedsSponsor.upper() == 'TRUE'"
href="${tg.url('/group/sponsor/%s/%s' % (groups[user].cn, user))}">${_('Approve')}</a> href="${tg.url('/group/sponsor/%s/%s' % (groups[user].cn, user))}">${_('Approve')}</a>
</li> </li>
<li py:if="auth.canRemoveUser(tg.identity.user.user_name, group.cn, userName)"> <li py:if="auth.canRemoveUser(tg.identity.user.user_name, group.cn, userName)">
@ -90,9 +93,9 @@
<a href="${tg.url('/group/upgrade/%s/%s' % (groups[user].cn, user))}">${_('Upgrade')}</a> <a href="${tg.url('/group/upgrade/%s/%s' % (groups[user].cn, user))}">${_('Upgrade')}</a>
</li> </li>
<li py:if="auth.canDowngradeUser(tg.identity.user.user_name, group.cn, userName)"> <li py:if="auth.canDowngradeUser(tg.identity.user.user_name, group.cn, userName)">
<a href="${tg.url('/group/downgrade/%s/%s' % (groups[user].cn, user))}">${_('Downgrade')}</a> <a href="${tg.url('/group/downgrade/%s/%s' % (groups[user].cn, user))}">${_('Downgrade')}</a>-->
</li> </li>
-->
</ul> </ul>
</td> </td>
</tr> </tr>

View file

@ -50,11 +50,11 @@
<div id="sidebar"> <div id="sidebar">
<ul> <ul>
<li class="first"><a href="${tg.url('/group/list')}">${_('Group List')}</a></li> <li class="first"><a href="${tg.url('/group/list')}">${_('Group List')}</a></li>
<!--<div py:if="'accounts' in tg.identity.groups" py:strip=''> --> <div py:if="not tg.identity.anonymous and 'accounts' in tg.identity.groups" py:strip=''>
<!-- TODO: Make these use auth.py --> <!-- TODO: Make these use auth.py -->
<!-- <li><a href="${tg.url('/user/list')}">${_('User List')}</a></li> <li><a href="${tg.url('/user/list')}">${_('User List')}</a></li>
<li><a href="${tg.url('/group/new')}">${_('New Group')}</a></li> <li><a href="${tg.url('/group/new')}">${_('New Group')}</a></li>
</div>--> </div>
<li><a href="${tg.url('/group/list/A*')}">${_('Apply For a new Group')}</a></li> <li><a href="${tg.url('/group/list/A*')}">${_('Apply For a new Group')}</a></li>
<li><a href="http://fedoraproject.org/wiki/FWN/LatestIssue">${_('News')}</a></li> <li><a href="http://fedoraproject.org/wiki/FWN/LatestIssue">${_('News')}</a></li>
</ul> </ul>

View file

@ -28,11 +28,11 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr py:for="user in sorted(users)"> <tr py:for="person in people">
<td><a href="${tg.url('/user/view/%s' % user)}">${user}</a></td> <td><a href="${tg.url('/user/view/%s' % person.username)}">${person.username}</a></td>
<td> <td>
<span py:if="claDone[user]" class="approved">${_('CLA Done')}</span> <span py:if="cla_done_group in person.memberships" class="approved">${_('CLA Done')}</span>
<span py:if="not claDone[user]" class="unapproved">${_('CLA Not Done')}</span> <span py:if="not cla_done_group in person.memberships" class="unapproved">${_('CLA Not Done')}</span>
</td> </td>
</tr> </tr>
</tbody> </tbody>

View file

@ -1,6 +1,7 @@
import turbogears import turbogears
from turbogears import controllers, expose, paginate, identity, redirect, widgets, validate, validators, error_handler from turbogears import controllers, expose, paginate, identity, redirect, widgets, validate, validators, error_handler
from turbogears.database import session from turbogears.database import session
import cherrypy
import ldap import ldap
@ -135,6 +136,11 @@ class User(controllers.Controller):
''' '''
turbogears.redirect('/user/view/%s' % turbogears.identity.current.user_name) turbogears.redirect('/user/view/%s' % turbogears.identity.current.user_name)
def jsonRequest(self):
return 'tg_format' in cherrypy.request.params and \
cherrypy.request.params['tg_format'] == 'json'
@expose(template="fas.templates.error") @expose(template="fas.templates.error")
def error(self, tg_errors=None): def error(self, tg_errors=None):
'''Show a friendly error message''' '''Show a friendly error message'''
@ -222,17 +228,19 @@ class User(controllers.Controller):
return dict(target=target) return dict(target=target)
@identity.require(turbogears.identity.in_group("accounts")) #TODO: Use auth.py @identity.require(turbogears.identity.in_group("accounts")) #TODO: Use auth.py
@expose(template="fas.templates.user.list") @expose(template="fas.templates.user.list", allow_json=True)
def list(self, search="a*"): def list(self, search="a*"):
'''List users '''List users
''' '''
people = People.query.filter(People.username.like('%%%s%%' % username)) re_search = re.sub(r'\*', r'%', search).lower()
try: people = People.query.filter(People.username.like(re_search)).order_by('username')
people[0] if people.count() < 0:
except: turbogears.flash(_("No Users found matching '%s'") % search)
turbogears.flash(_("No users found matching '%s'") % search) if self.jsonRequest():
people = [] return ({'users': users})
return dict(users=users, search=search) cla_done_group = Groups.by_name('cla_done')
return dict(people=people, search=search, cla_done_group=cla_done_group)
@expose(template='fas.templates.user.new') @expose(template='fas.templates.user.new')
def new(self): def new(self):