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

Fix conflicts in fas2.sql.
Conflicts:

	fas/fas2.sql
This commit is contained in:
Toshio Kuratomi 2008-03-11 17:05:54 -07:00
commit 4a7f7f6ef7
24 changed files with 373 additions and 2089 deletions

View file

@ -436,7 +436,7 @@ class MakeShellAccounts(BaseClient):
def create_ssh_keys(self):
''' Create ssh keys '''
home_base = config.get('users', 'home').strip('"')
home_base = prefix + config.get('users', 'home').strip('"')
for person in self.people:
username = person['username']
if self.valid_user(username):

View file

@ -62,6 +62,7 @@ for person in c.fetchall():
p.internal_comments = internal_comments
p.ircnick = ircnick
p.status = 'active'
p.email = email
try:
session.flush()
except IntegrityError, e:
@ -69,25 +70,6 @@ for person in c.fetchall():
session.close()
continue
person_email = PersonEmails()
try:
person_email.email = email
except AttributeError:
print "\tERROR - Could not create email for %s (%s)" % (username, email)
session.close()
continue
person_email.person = p
person_email.description = 'Fedora Email'
person_email.verified = True # The first email is verified for free, since this is where their password is sent.
session.flush()
email_purpose = EmailPurposes()
email_purpose.person = p
email_purpose.person_email = person_email
email_purpose.purpose = 'primary'
session.flush()
c.execute('select id, name, owner_id, group_type, needs_sponsor, user_can_remove, prerequisite_id, joinmsg from project_group;')
bool_dict = {0 : False, 1 : True}
print "Creating Groups..."

View file

@ -135,7 +135,7 @@ class CLA(controllers.Controller):
emails = [];
for uid in key.uids:
emails.extend([uid.email])
if person.emails['primary'] in emails:
if person.email in emails:
verified = True
else:
turbogears.flash(_('Your key did not match your email.'))
@ -181,7 +181,7 @@ class CLA(controllers.Controller):
message.plain = '''
Fedora user %(username)s has signed a completed ICLA using their published GPG key, ID %(gpg_keyid)s,
that is associated with e-mail address %(email)s. The full signed ICLA is attached.
''' % {'username': person.username, 'gpg_keyid': person.gpg_keyid, 'email': person.emails['primary']}
''' % {'username': person.username, 'gpg_keyid': person.gpg_keyid, 'email': person.email}
signature.file.seek(0) # For another read()
message.attach(signature.file, signature.filename)
turbomail.enqueue(message)

View file

@ -308,7 +308,7 @@ Fedora user %(user)s, aka %(name)s <%(email)s> has requested
membership for %(applicant)s (%(applicant_name)s) in the %(group)s group and needs a sponsor.
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'], 'url': url, 'group': group.name}
''') % {'user': person.username, 'name': person.human_name, 'applicant': target.username, 'applicant_name': target.human_name, 'email': person.email, 'url': url, 'group': group.name}
turbomail.enqueue(message)
turbogears.flash(_('%(user)s has applied to %(group)s!') % \
{'user': target.username, 'group': group.name})
@ -339,14 +339,14 @@ Please go to %(url)s to take action.
turbogears.redirect('/group/view/%s' % group.name)
else:
import turbomail
message = turbomail.Message(config.get('accounts_email'), target.emails['primary'], "Your Fedora '%s' membership has been sponsored" % group.name)
message = turbomail.Message(config.get('accounts_email'), target.email, "Your Fedora '%s' membership has been sponsored" % group.name)
message.plain = _('''
%(name)s <%(email)s> has sponsored you for membership in the %(group)s
group of the Fedora account system. If applicable, this change should
propagate into the e-mail aliases and CVS repository within an hour.
%(joinmsg)s
''') % {'group': group.name, 'name': person.human_name, 'email': person.emails['primary'], 'joinmsg': group.joinmsg}
''') % {'group': group.name, 'name': person.human_name, 'email': person.email, 'joinmsg': group.joinmsg}
turbomail.enqueue(message)
turbogears.flash(_("'%s' has been sponsored!") % target.human_name)
turbogears.redirect('/group/view/%s' % group.name)
@ -376,13 +376,13 @@ propagate into the e-mail aliases and CVS repository within an hour.
{'user': target.username, 'group': group.name, 'error': e})
turbogears.redirect('/group/view/%s' % group.name)
else:
message = turbomail.Message(config.get('accounts_email'), target.emails['primary'], "Your Fedora '%s' membership has been removed" % group.name)
message = turbomail.Message(config.get('accounts_email'), target.email, "Your Fedora '%s' membership has been removed" % group.name)
message.plain = _('''
%(name)s <%(email)s> has removed you from the '%(group)s'
group of the Fedora Accounts System This change is effective
immediately for new operations, and should propagate into the e-mail
aliases within an hour.
''') % {'group': group.name, 'name': person.human_name, 'email': person.emails['primary']}
''') % {'group': group.name, 'name': person.human_name, 'email': person.email}
turbomail.enqueue(message)
turbogears.flash(_('%(name)s has been removed from %(group)s') % \
{'name': target.username, 'group': group.name})
@ -413,7 +413,7 @@ aliases within an hour.
turbogears.redirect('/group/view/%s' % group.name)
else:
import turbomail
message = turbomail.Message(config.get('accounts_email'), target.emails['primary'], "Your Fedora '%s' membership has been upgraded" % group.name)
message = turbomail.Message(config.get('accounts_email'), target.email, "Your Fedora '%s' membership has been upgraded" % group.name)
# Should we make person.upgrade return this?
role = PersonRoles.query.filter_by(group=group, member=target).one()
status = role.role_type
@ -422,7 +422,7 @@ aliases within an hour.
'%(group)s' group of the Fedora Accounts System This change is
effective immediately for new operations, and should propagate
into the e-mail aliases within an hour.
''') % {'group': group.name, 'name': person.human_name, 'email': person.emails['primary'], 'status': status}
''') % {'group': group.name, 'name': person.human_name, 'email': person.email, 'status': status}
turbomail.enqueue(message)
turbogears.flash(_('%s has been upgraded!') % target.username)
turbogears.redirect('/group/view/%s' % group.name)
@ -452,7 +452,7 @@ into the e-mail aliases within an hour.
turbogears.redirect('/group/view/%s' % group.name)
else:
import turbomail
message = turbomail.Message(config.get('accounts_email'), target.emails['primary'], "Your Fedora '%s' membership has been downgraded" % group.name)
message = turbomail.Message(config.get('accounts_email'), target.email, "Your Fedora '%s' membership has been downgraded" % group.name)
role = PersonRoles.query.filter_by(group=group, member=target).one()
status = role.role_type
message.plain = _('''
@ -460,7 +460,7 @@ into the e-mail aliases within an hour.
'%(group)s' group of the Fedora Accounts System This change is
effective immediately for new operations, and should propagate
into the e-mail aliases within an hour.
''') % {'group': group.name, 'name': person.human_name, 'email': person.emails['primary'], 'status': status}
''') % {'group': group.name, 'name': person.human_name, 'email': person.email, 'status': status}
turbomail.enqueue(message)
turbogears.flash(_('%s has been downgraded!') % target.username)
turbogears.redirect('/group/view/%s' % group.name)
@ -504,7 +504,7 @@ into the e-mail aliases within an hour.
group = Groups.by_name(groupname)
if isApproved(person, group):
message = turbomail.Message(person.emails['primary'], target, _('Come join The Fedora Project!'))
message = turbomail.Message(person.email, target, _('Come join The Fedora Project!'))
message.plain = _('''
%(name)s <%(email)s> has invited you to join the Fedora
Project! We are a community of users and developers who produce a
@ -520,7 +520,7 @@ place for you whether you're an artist, a web site builder, a writer, or
a people person. You'll grow and learn as you work on a team with other
very smart and talented people.
Fedora and FOSS are changing the world -- come be a part of it!''') % {'name': person.human_name, 'email': person.emails['primary']}
Fedora and FOSS are changing the world -- come be a part of it!''') % {'name': person.human_name, 'email': person.email}
turbomail.enqueue(message)
turbogears.flash(_('Message sent to: %s') % target)
turbogears.redirect('/group/view/%s' % group.name)

View file

@ -4,10 +4,11 @@ from turbogears.database import session
from fas.auth import *
# TODO: gettext like crazy.
class Help(controllers.Controller):
help = { 'none' : ['Error', '<p>We could not find that help item</p>'],
'user_ircnick' : ['IRC Nick (Optional)', '<p>IRC Nick is used to identify yourself on irc.freenode.net. Please register your nick on irc.freenode.net first, then fill this in so people can find you online when they need to</p>'],
'user_primary_email' : ['Primary Email (Required)', '<p>This email address should be your prefered email contact and will be used to send various official emails to. This is also where your @fedoraproject.org email will get forwarded</p>'],
'user_email' : ['Email (Required)', '<p>This email address should be your prefered email contact and will be used to send various official emails to. This is also where your @fedoraproject.org email will get forwarded</p>'],
'user_human_name' : ['Full Name (Required)', '<p>Your Human Name or "real life" name</p>'],
'user_gpg_keyid' : ['GPG Key', '<p>Only required for users signing the <a href="http://fedoraproject.org/wiki/Legal/Licenses/CLA">CLA</a>. It is generally used to prove that a message or email came from you or to encrypt information so that only the recipients can read it. See the <a href="http://fedoraproject.org/wiki/Infrastructure/AccountSystem/CLAHowTo">CLAHowTo</a> for more information</p>'],
'user_telephone' : ['Telephone', '<p>Only required for users signing the <a href="http://fedoraproject.org/wiki/Legal/Licenses/CLA">CLA</a>. Sometimes during a time of emergency someone from the Fedora Project may need to contact you. For more information see our <a href="http://fedoraproject.org/wiki/Legal/PrivacyPolicy">Privacy Policy</a></p>'],

View file

@ -56,14 +56,10 @@ get_engine()
#
PeopleTable = Table('people', metadata, autoload=True)
PersonEmailsTable = Table('person_emails', metadata, autoload=True)
EmailPurposesTable = Table('email_purposes', metadata, autoload=True)
PersonRolesTable = Table('person_roles', metadata, autoload=True)
ConfigsTable = Table('configs', metadata, autoload=True)
GroupsTable = Table('groups', metadata, autoload=True)
GroupEmailsTable = Table('group_emails', metadata, autoload=True)
GroupEmailPurposesTable = Table('group_email_purposes', metadata, autoload=True)
GroupRolesTable = Table('group_roles', metadata, autoload=True)
BugzillaQueueTable = Table('bugzilla_queue', metadata, autoload=True)
LogTable = Table('log', metadata, autoload=True)
@ -116,7 +112,7 @@ class People(SABase):
A class method that can be used to search users
based on their email addresses since it is unique.
'''
return cls.query.join(['email_purposes', 'person_email']).filter_by(email=email).one()
return cls.query.filter_by(email=email).one()
@classmethod
def by_username(cls, username):
@ -250,8 +246,12 @@ class People(SABase):
if not identity.in_group('admin'):
# Only admins can see internal_comments
del props['internal_comments']
del props['emailtoken']
if identity.current.anonymous:
# Anonymous users can't see any of these
del props['email']
del props['emailtoken']
del props['unverified_email']
del props['ssh_key']
del props['gpg_keyid']
del props['affiliation']
@ -262,8 +262,10 @@ class People(SABase):
del props['postal_address']
del props['telephone']
del props['facsimile']
# TODO: Are we still doing the fas-system thing? I think I saw a systems users somewhere...
elif not identity.current.user.username == self.username and 'fas-system' not in identity.current.groups:
# Only an admin or the user themselves can see these fields
del props['unverified_email']
del props['password']
del props['passwordtoken']
del props['postal_address']
@ -277,19 +279,6 @@ class People(SABase):
approved_memberships = association_proxy('approved_roles', 'group')
unapproved_memberships = association_proxy('unapproved_roles', 'group')
emails = association_proxy('email_purposes', 'email')
class PersonEmails(SABase):
'''Map a person to an email address.'''
def __repr__(cls):
return "PersonEmails(%s,%s,%s,%s)" % (cls.person.username, cls.email, cls.description, cls.verified)
class EmailPurposes(SABase):
'''Map a person to an email (with a purpose).'''
def __repr__(cls):
return "EmailPurposes(%s,%s,%s)" % (cls.person.username, cls.email, cls.purpose)
email = association_proxy('person_email', 'email')
class PersonRoles(SABase):
'''Record people that are members of groups.'''
def __repr__(cls):
@ -317,7 +306,7 @@ class Groups(SABase):
A class method that can be used to search groups
based on their email addresses since it is unique.
'''
return cls.query.join(['email_purposes', 'group_email']).filter_by(email=email).one()
return cls.query.filter_by(email=email).one()
@classmethod
@ -338,21 +327,6 @@ class Groups(SABase):
# Groups that this group belongs to
memberships = association_proxy('group_roles', 'group')
emails = association_proxy('email_purposes', 'email')
class GroupEmails(SABase):
'''Map a group to an email address.'''
def __repr__(cls):
return "GroupEmails(%s,%s,%s,%s)" % (cls.group.name, cls.email, cls.description, cls.verified)
class GroupEmailPurposes(SABase):
'''Map a group to an email (with a purpose).'''
def __repr__(cls):
return "GroupEmailPurposes(%s,%s,%s)" % (cls.group.name, cls.email, cls.purpose)
email = association_proxy('group_email', 'email')
class GroupRoles(SABase):
'''Record groups that are members of other groups.'''
pass
@ -420,12 +394,6 @@ mapper(UnApprovedRoles, UnApprovedRolesSelect, properties = {
})
mapper(People, PeopleTable, properties = {
'email_purposes': relation(EmailPurposes, backref = 'person',
collection_class = column_mapped_collection(
EmailPurposesTable.c.purpose)),
'person_emails': relation(PersonEmails, backref = 'person',
collection_class = column_mapped_collection(
PersonEmailsTable.c.email)),
# This name is kind of confusing. It's to allow person.group_roles['groupname'] in order to make auth.py (hopefully) slightly faster.
'group_roles': relation(PersonRoles,
collection_class = attribute_mapped_collection('groupname'),
@ -435,11 +403,6 @@ mapper(People, PeopleTable, properties = {
'unapproved_roles': relation(UnApprovedRoles, backref='member',
primaryjoin = PeopleTable.c.id==UnApprovedRoles.c.person_id)
})
mapper(PersonEmails, PersonEmailsTable)
mapper(EmailPurposes, EmailPurposesTable, properties = {
'person_email': relation(PersonEmails, uselist = False,
primaryjoin = PersonEmailsTable.c.id==EmailPurposesTable.c.email_id)
})
mapper(PersonRoles, PersonRolesTable, properties = {
'member': relation(People, backref = 'roles', lazy = False,
primaryjoin=PersonRolesTable.c.person_id==PeopleTable.c.id),
@ -454,20 +417,9 @@ mapper(Configs, ConfigsTable, properties = {
mapper(Groups, GroupsTable, properties = {
'owner': relation(People, uselist=False,
primaryjoin = GroupsTable.c.owner_id==PeopleTable.c.id),
'email_purposes': relation(GroupEmailPurposes, backref = 'group',
collection_class = column_mapped_collection(
GroupEmailPurposesTable.c.purpose)),
'group_emails': relation(GroupEmails, backref = 'group',
collection_class = column_mapped_collection(
GroupEmailsTable.c.email)),
'prerequisite': relation(Groups, uselist=False,
primaryjoin = GroupsTable.c.prerequisite_id==GroupsTable.c.id)
})
mapper(GroupEmails, GroupEmailsTable)
mapper(GroupEmailPurposes, GroupEmailPurposesTable, properties = {
'group_email': relation(GroupEmails, uselist = False,
primaryjoin = GroupEmailsTable.c.id==GroupEmailPurposesTable.c.email_id)
})
# GroupRoles are complex because the group is a member of a group and thus
# is referencing the same table.
mapper(GroupRoles, GroupRolesTable, properties = {

View file

@ -2,7 +2,7 @@
Release information about the Fedora Accounts System
'''
VERSION = '0.1'
VERSION = '0.5'
NAME = 'fas'
DESCRIPTION = 'The Fedora Account System'
LONG_DESCRIPTION = '''

View file

@ -20,7 +20,7 @@
</p>
<p>
Full name: ${person.human_name}<br />
E-Mail: ${person.emails['primary']}<br />
E-Mail: ${person.email}<br />
Address: ${person.postal_address}<br />
Telephone: ${person.telephone}
<!-- Facsimile: ${person.facsimile} -->

View file

@ -27,7 +27,7 @@
fedora-legal@redhat.com. Please read this document carefully before
signing and keep a copy for your records.
Full name: ${'%28s' % person.human_name} E-Mail: ${'%17s' % person.emails['primary']}
Full name: ${'%28s' % person.human_name} E-Mail: ${'%17s' % person.email}
Address:
${person.postal_address}
@ -150,5 +150,5 @@ ${person.postal_address}
If you agree to these terms and conditions, type "I agree" here:
Enter your full name here:
E-mail: ${person.emails['primary']}
E-mail: ${person.email}
Date: ${date}

View file

@ -19,7 +19,7 @@
<div>
${_('If you agree to these terms and conditions, type "%s" here:') % 'I agree'} <input type="text" id="agree" name="agree" /><br />
${_('Full Name:')} ${person.human_name}<br />
${_('E-mail:')} ${person.emails['primary']}<br />
${_('E-mail:')} ${person.email}<br />
${_('Date:')} ${date}<br />
<input type="submit" value="${_('Submit CLA')}" />
</div>

View file

@ -1,3 +1,3 @@
#for role in sorted(group.approved_roles)
${role.member.username},${role.member.emails['primary']},${role.member.human_name},${role.role_type},0
${role.member.username},${role.member.email},${role.member.human_name},${role.role_type},0
#end

View file

@ -12,12 +12,12 @@
<div>
<!--TODO: Make the email translatable -->
${_('To email:')} <input type="text" value="" name="target" /><br />
${_('From:')} ${person.emails['primary']}<br />
${_('From:')} ${person.email}<br />
${_('Subject:')} Invitation to join the Fedora Team!<br />
${_('Message:')}
<div class="message">
<p>
${person.human_name} &lt;<a href="mailto: ${person.emails['primary']}">${person.emails['primary']}</a>&gt; has invited you to join the Fedora
${person.human_name} &lt;<a href="mailto: ${person.email}">${person.email}</a>&gt; has invited you to join the Fedora
Project! We are a community of users and developers who produce a
complete operating system from entirely free and open source software
(FOSS). ${person.human_name} thinks that you have knowledge and skills

View file

@ -17,8 +17,8 @@
<!--Need to figure out what the interface should be for emails. -->
<div class="field">
<label for="mail">${_('Email')}:</label>
<input type="text" id="email" name="email" value="${target.emails['primary']}" />
<script type="text/javascript">var hb2 = new HelpBalloon({dataURL: '${tg.url('/help/get_help/user_primary_email')}'});</script>
<input type="text" id="email" name="email" value="${target.email}" />
<script type="text/javascript">var hb2 = new HelpBalloon({dataURL: '${tg.url('/help/get_help/user_email')}'});</script>
</div>
<!-- <div class="field">
<label for="fedoraPersonBugzillaMail">${_('Bugzilla Email')}:</label>

View file

@ -1,30 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/"
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="../../master.html" />
<head>
<title>${_('Add Email')}</title>
</head>
<body>
<h2>${_('Add Email')}</h2>
<form action="${tg.url('/user/email/create/%s' % target.username)}" method="post">
<div class="field">
<label for="email">${_('Email:')}</label>
<input type="text" id="email" name="email" />
<!-- TODO: More generic documentation for adding an email -->
<script type="text/javascript">var hb1 = new HelpBalloon({dataURL: '${tg.url('/help/get_help/user_primary_email')}'});</script>
</div>
<div class="field">
<label for="description">${_('Description:')}</label>
<input type="text" id="description" name="description" />
<!-- TODO: Correct documentation for this -->
<script type="text/javascript">var hb1 = new HelpBalloon({dataURL: '${tg.url('/help/get_help/user_primary_email')}'});</script>
</div>
<div class="field">
<input type="submit" value="${_('Save!')}" />
<a href="${tg.url('/user/email/manage')}">${_('Cancel')}</a>
</div>
</form>
</body>
</html>

View file

@ -1,28 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/"
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="../../master.html" />
<head>
<title>${_('Edit Email')}</title>
</head>
<body>
<h2>${_('Edit Email')}</h2>
<form action="${tg.url('/user/email/save/%s' % target.username)}" method="post">
<div class="field">
<label for="email">${_('Email:')}</label> <span>${email}</span>
<input type="hidden" id="email" name="email" value="${email}" />
</div>
<div class="field">
<label for="description">${_('Description:')}</label>
<input type="text" id="description" name="description" value="${target.person_emails[email].description}" />
<!-- TODO: Correct documentation for this -->
<script type="text/javascript">var hb1 = new HelpBalloon({dataURL: '${tg.url('/help/get_help/user_primary_email')}'});</script>
</div>
<div class="field">
<input type="submit" value="${_('Save!')}" />
<a href="${tg.url('/user/email/manage')}">${_('Cancel')}</a>
</div>
</form>
</body>
</html>

View file

@ -1,56 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/"
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="../../master.html" />
<head>
<title>${_('Manage Emails')}</title>
</head>
<body>
<h2>${_('Managing Emails for %s') % target.username}</h2>
<h3>Available Emails</h3>
<table>
<thead>
<tr>
<th>${_('Email')}</th>
<th>${_('Description')}</th>
<th>${_('Verified')}</th>
</tr>
</thead>
<tbody>
<tr py:for="email in target.person_emails.values()">
<td><a href="mailto:${email.email}">${email.email}</a></td>
<td>${email.description}</td>
<td py:if="email.verified"><span class="approved">${_('Verified')}</span></td>
<td py:if="not email.verified"><span class="unapproved">${_('Unverified')}</span> (<a href="${tg.url('/email/verify')}">${_('Resend Verification')}</a>)</td>
<td py:if="len(target.person_emails) > 1"><a href="${tg.url('/user/email/remove/%s/%s') % (target.username, email.email)}">${_('Remove')}</a></td>
</tr>
</tbody>
</table>
<h3>Set Emails</h3>
<form action="${tg.url('/user/email/map/%s' % target.username)}">
<table>
<thead>
<tr>
<th>${_('Email')}</th>
<th>${_('Description')}</th>
<th>${_('Purpose')}</th>
</tr>
</thead>
<tbody>
<tr py:for="purpose in target.email_purposes.values()">
<td>
<select id="email" name="email">
<py:for each="person_email in target.person_emails.values()">
<option py:if="person_email.verified" value="person_email.email" py:attrs="{'selected': purpose.email == person_email.email and 'selected' or None}">${person_email.email} (${person_email.description})</option>
</py:for>
</select>
</td>
<td>${purpose.person_email.description}</td>
<td>${purpose.purpose}</td>
</tr>
</tbody>
</table>
</form>
</body>
</html>

View file

@ -11,7 +11,7 @@
<form action="${tg.url('/user/sendpass')}" method="post">
<ul>
<div class="field"><label for="username">${_('Username:')}</label> <input type="text" id="username" name="username" /></div>
<div class="field"><label for="email">${_('Primary Email:')}</label> <input type="text" id="email" name="email" /></div>
<div class="field"><label for="email">${_('Email:')}</label> <input type="text" id="email" name="email" /></div>
<div class="field"><input type="checkbox" id="encrypted" name="encrypted" /> <label style="width: auto; float: none; margin-left: 1ex;" for="encrypted">${_('Encrypt/Sign password reset email')}</label></div>
<div class="field"><input type="submit" value="${_('Reset Password')}" /></div>
</ul>

View file

@ -19,7 +19,7 @@
<dl>
<dt>${_('Account Name:')}</dt><dd>${person.username}</dd>
<dt>${_('Real Name:')}</dt><dd>${person.human_name}</dd>
<dt>${_('Email:')}</dt><dd>${person.emails['primary']}</dd>
<dt>${_('Email:')}</dt><dd>${person.email}</dd>
<!--<dt>${_('Bugzilla Email:')}</dt><dd>${person.username}</dd>-->
<dt>${_('IRC Nick:')}</dt><dd>${person.ircnick}&nbsp;</dd>
<dt>${_('PGP Key:')}</dt><dd>${person.gpg_keyid}&nbsp;</dd>

View file

@ -17,13 +17,10 @@ import subprocess
from OpenSSL import crypto
from fas.model import People
from fas.model import PersonEmails
from fas.model import EmailPurposes
from fas.model import Log
from fas import openssl_fas
from fas.auth import *
#from fas.user_email import Email, NonFedoraEmail
from random import Random
import sha
@ -159,8 +156,6 @@ def generate_salt(length=8):
class User(controllers.Controller):
#email = Email()
def __init__(self):
'''Create a User Controller.
'''
@ -254,16 +249,11 @@ class User(controllers.Controller):
return dict()
try:
target.human_name = human_name
# FIXME: WARNING! This is deceptive. Remember that it
# changes the email object itself, not the email attached
# to the purpose.
if not target.emails['primary'] == email:
if target.email != email:
''' Log this '''
oldEmail = target.emails['primary']
oldEmail = target.email
Log(author_id=person.id, description='Email changed from %s to %s' % (oldEmail, email))
target.emails['primary'] = email
# target.emails['bugzilla'] = bugzilla
target.email = email
target.ircnick = ircnick
target.gpg_keyid = gpg_keyid
target.telephone = telephone
@ -311,7 +301,7 @@ class User(controllers.Controller):
people = People.query.filter(People.username.like(re_search)).order_by('username')
emails = {}
for person in people:
emails[person.username] = person.emails['primary']
emails[person.username] = person.email
return dict(emails=emails)
@expose(template='fas.templates.user.new')
@ -334,26 +324,12 @@ class User(controllers.Controller):
person.username = username
person.human_name = human_name
person.telephone = telephone
person.email = email
person.password = '*'
person.status = 'active'
session.flush()
# TODO: Handle properly if email has already been used. This might be painful, since the person already exists, at this point.
person_email = PersonEmails()
person_email.email = email
person_email.person = person
person_email.description = 'Fedora Email'
person_email.verified = True # The first email is verified for free, since this is where their password is sent.
session.flush()
email_purpose = EmailPurposes()
email_purpose.person = person
email_purpose.person_email = person_email
email_purpose.purpose = 'primary'
session.flush()
newpass = generate_password()
message = turbomail.Message(config.get('accounts_email'), person.emails['primary'], _('Welcome to the Fedora Project!'))
message = turbomail.Message(config.get('accounts_email'), person.email, _('Welcome to the Fedora Project!'))
message.plain = _('''
You have created a new Fedora account!
Your new password is: %s
@ -436,6 +412,7 @@ forward to working with you!
turbogears.redirect('/user/view/%s' % turbogears.identity.current.user_name)
return dict()
#TODO: Validate
@expose(template="fas.templates.user.resetpass")
def sendpass(self, username, email, encrypted=False):
import turbomail
@ -449,8 +426,7 @@ forward to working with you!
except InvalidRequestError:
turbogears.flash(_('Username email combo does not exist!'))
turbogears.redirect('/user/resetpass')
if username and email:
if not email == person.emails['primary']:
if email != person.email:
turbogears.flash(_("username + email combo unknown."))
return dict()
newpass = generate_password()
@ -470,12 +446,8 @@ Please go to https://admin.fedoraproject.org/fas/ to change it.
ret = subprocess.call([config.get('gpgexec'), '--keyserver', config.get('gpg_keyserver'), '--recv-keys', keyid])
if ret != 0:
turbogears.flash(_("Your key could not be retrieved from subkeys.pgp.net"))
turbogears.redirect('/cla/view/sign')
turbogears.redirect('/user/resetpass')
return dict()
#try:
# subprocess.check_call([config.get('gpgexec'), '--keyserver', config.get('gpg_keyserver'), '--recv-keys', keyid])
#except subprocess.CalledProcessError:
# turbogears.flash(_("Your key could not be retrieved from subkeys.pgp.net"))
else:
try:
plaintext = StringIO.StringIO(mail)
@ -502,10 +474,10 @@ Please go to https://admin.fedoraproject.org/fas/ to change it.
try:
person.password = newpass['hash']
turbogears.flash(_('Your new password has been emailed to you.'))
turbogears.redirect('/login')
return dict()
except:
turbogears.flash(_('Your password could not be reset.'))
else:
turbogears.redirect('/login')
return dict()
@identity.require(turbogears.identity.not_anonymous())
@ -533,7 +505,7 @@ Please go to https://admin.fedoraproject.org/fas/ to change it.
O=config.get('openssl_o'),
OU=config.get('openssl_ou'),
CN=person.username,
emailAddress=person.emails['primary'],
emailAddress=person.email,
)
cert = openssl_fas.createCertificate(req, (cacert, cakey), person.certificate_serial, (0, expire), digest='md5')

View file

@ -1,294 +0,0 @@
import turbogears
from turbogears import controllers, expose, paginate, identity, redirect, widgets, validate, validators, error_handler, config
from turbogears.database import session
import cherrypy
import turbomail
import random
from fas.model import People
from fas.model import PersonEmails
from fas.model import EmailPurposes
from fas.model import Log
from fas.auth import *
class NonFedoraEmail(validators.FancyValidator):
'''Make sure that an email address is not @fedoraproject.org'''
def _to_python(self, value, state):
return value.strip()
def validate_python(self, value, state):
if value.endswith('@fedoraproject.org'):
raise validators.Invalid(_("To prevent email loops, your email address cannot be @fedoraproject.org."), value, state)
class EmailSave(validators.Schema):
email = validators.All(
validators.Email(not_empty=True, strip=True),
NonFedoraEmail(not_empty=True, strip=True),
)
description = validators.String(not_empty=True, max=512)
def generate_validtoken(length=32):
''' Generate Validation Token '''
chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
token = ''
for i in xrange(length):
token += random.choice(chars)
return token
# Note: I'm making some of these controllers really, really hideous
# (in the interest of allowing admins to modify pretty much everything)
# Is this really necessary (as in, can tg-admin shell be "good enough?"
# (I'm pretty much referring to passing the username around every
# instead of just using the current logged on person.)
# I hope all of this doesn't end up being too convoluted for most users...
class Email(controllers.Controller):
def __init__(self):
'''Create an Email Controller.
'''
@identity.require(turbogears.identity.not_anonymous())
def index(self):
'''Redirect to manage
'''
turbogears.redirect('/user/email/manage')
@expose(template="fas.templates.error")
def error(self, tg_errors=None):
'''Show a friendly error message'''
if not tg_errors:
turbogears.redirect('/')
return dict(tg_errors=tg_errors)
@identity.require(turbogears.identity.not_anonymous())
#@validate(validators=UserView())
@error_handler(error)
@expose(template="fas.templates.user.email.manage", allow_json=True)
def manage(self, targetname=None):
'''
Manage a person's emails
'''
# TODO: Some sort of auth checking - other people should
# probably be limited to looking at a person's email through
# /user/view, although admins should probably be able to set
# emails (with/without verification?)
username = turbogears.identity.current.user_name
person = People.by_username(username)
if targetname:
target = People.by_username(targetname)
else:
target = person
return dict(target=target)
@identity.require(turbogears.identity.not_anonymous())
# TODO: Validate!
#@validate(validators=UserView())
@error_handler(error)
@expose(template="fas.templates.user.email.edit")
# TODO: Should the purpose-setting part be moved in into user/save?
def edit(self, targetname, email):
'''
Display the form to edit an email
'''
username = turbogears.identity.current.user_name
person = People.by_username(username)
if targetname:
target = People.by_username(targetname)
else:
target = person
if not canEditUser(person, target):
turbogears.flash(_('You cannot edit %s') % target.username )
turbogears.redirect('/user/email/manage')
return dict()
return dict(email=email, target=target)
@identity.require(turbogears.identity.not_anonymous())
# TODO: Validate!
#@validate(validators=UserView())
@error_handler(error)
@expose()
# TODO: Should the purpose-setting part be moved in into user/save?
def save(self, targetname, email, description):
'''
Save an email entry
'''
username = turbogears.identity.current.user_name
person = People.by_username(username)
if targetname:
target = People.by_username(targetname)
else:
target = person
if not canEditUser(person, target):
turbogears.flash(_('You cannot edit %s') % target.username )
turbogears.redirect('/user/email/manage')
return dict()
try:
person.person_emails[email].description = description
except KeyError:
turbogears.flash(_('No such email is associated with your user.'))
turbogears.redirect('/user/email/manage')
return dict()
else:
turbogears.flash(_('Your email has been saved.'))
turbogears.redirect('/user/email/manage')
return dict()
@identity.require(turbogears.identity.not_anonymous())
# TODO: Validate!
#@validate(validators=UserView())
@error_handler(error)
@expose(template="fas.templates.user.email.add")
def add(self, targetname=None):
'''
Display the form to add an email
'''
username = turbogears.identity.current.user_name
person = People.by_username(username)
if targetname:
target = People.by_username(targetname)
else:
target = person
if not canEditUser(person, target):
turbogears.flash(_('You cannot edit %s') % target.username )
turbogears.redirect('/user/email/manage')
return dict()
return dict(target=target)
@identity.require(turbogears.identity.not_anonymous())
# TODO: Validate!
#@validate(validators=UserView())
@error_handler(error)
@expose(allow_json=True)
def remove(self, targetname, email):
'''
Remove an email
'''
username = turbogears.identity.current.user_name
person = People.by_username(username)
if targetname:
target = People.by_username(targetname)
else:
target = person
if not canEditUser(person, target):
turbogears.flash(_('You cannot edit %s') % target.username )
turbogears.redirect('/user/email/manage')
return dict()
try:
session.delete(target.person_emails[email])
session.flush()
except IntegrityError:
turbogears.flash(_('You cannot delete an email that is in use.'))
turbogears.redirect('/user/email/manage')
return dict()
else:
turbogears.flash(_('The email \'%s\' has been removed.') % email )
turbogears.redirect('/user/email/manage')
return dict()
@identity.require(turbogears.identity.not_anonymous())
@validate(validators=EmailSave())
@error_handler(error)
@expose(template="fas.templates.user.email.add", allow_json=True)
def create(self, targetname, email, description):
'''
Create an email entry.
'''
username = turbogears.identity.current.user_name
person = People.by_username(username)
if targetname:
target = People.by_username(targetname)
else:
target = person
if not canEditUser(person, target):
turbogears.flash(_('You cannot edit %s') % target.username )
turbogears.redirect('/user/email/manage')
return dict()
validtoken = generate_validtoken()
try:
person_email = PersonEmails()
person_email.email = email
person_email.person = target
person_email.description = description
person_email.validtoken = validtoken
session.flush()
# Hmm, should this be checked in the validator or here?
except IntegrityError:
turbogears.flash(_('The email \'%s\' is already in used.') % email)
return dict(target=target)
else:
# TODO: Make this email more friendly. Maybe escape the @ in email too?
validurl = config.get('base_url_filter.base_url') + turbogears.url('/user/email/verify/%s/%s/%s') % (target.username, email, validtoken)
message = turbomail.Message(config.get('accounts_email'), email, _('Confirm this email address'))
message.plain = _('''
Go to this URL to verify that you own this email address: %s
''') % validurl
turbomail.enqueue(message)
turbogears.flash(_('Your email has been added. Before you can use this email, you must verify it. The email you added should receive a message with instructions shortly.'))
turbogears.redirect('/user/email/manage')
return dict()
return dict(target=target)
@identity.require(turbogears.identity.not_anonymous())
# TODO: Validation!
#@validate(validators=UserView())
@error_handler(error)
@expose(allow_json=True)
def verify(self, targetname, email, validtoken):
'''
Verify an email
'''
username = turbogears.identity.current.user_name
person = People.by_username(username)
if targetname:
target = People.by_username(targetname)
else:
target = person
if not canEditUser(person, target):
turbogears.flash(_('You cannot edit %s') % target.username )
turbogears.redirect('/user/email/manage')
return dict()
if target.person_emails[email].verified:
turbogears.flash(_('The email provided has already been verified.'))
turbogears.redirect('/user/email/manage')
return dict()
try:
if target.person_emails[email].validtoken == validtoken:
target.person_emails[email].validtoken = ''
target.person_emails[email].verified = True
turbogears.flash(_('Your email has been successfully verified.'))
turbogears.redirect('/user/email/manage')
return dict()
else:
turbogears.flash(_('The verification string did not match.'))
turbogears.redirect('/user/email/manage')
return dict()
except KeyError:
turbogears.flash(_('No such email is associated with your user.'))
turbogears.redirect('/user/email/manage')
return dict()

View file

@ -257,7 +257,7 @@ create or replace function bugzilla_sync() returns trigger as $bz_sync$
return None
# Retrieve the bugzilla email address
### FIXME: Once we implement it, we'll want to add a check for an email
### FIXME: Once we implement it, we will want to add a check for an email
# address in configs::application='bugzilla',person_id=person_id,
# attribute='login'
plan = plpy.prepare("select email from people where id = $1", ('int4',))
@ -575,10 +575,10 @@ create trigger role_bugzilla_sync before update or insert or delete
-- for each row execute procedure bugzilla_sync_email();
-- For Fas to connect to the database
GRANT ALL ON TABLE people, groups, person_roles, person_emails, email_purposes, group_roles, group_emails, group_email_purposes, bugzilla_queue, configs, person_seq, visit, visit_identity, log, log_id_seq, TO GROUP fedora;
GRANT ALL ON TABLE people, groups, person_roles, group_roles, bugzilla_queue, configs, person_seq, visit, visit_identity, log, log_id_seq, person_emails_id_seq, group_emails_id_seq TO GROUP fedora;
-- Create default admin user - Default Password "admin"
INSERT INTO people (id, username, human_name, password) VALUES (100001, 'admin', 'Admin User', '$1$djFfnacd$b6NFqFlac743Lb4sKWXj4/');
INSERT INTO people (id, username, human_name, password, email) VALUES (100001, 'admin', 'Admin User', '$1$djFfnacd$b6NFqFlac743Lb4sKWXj4/', 'root@localhost');
-- Create default groups and populate
INSERT INTO groups (id, name, display_name, owner_id, group_type) VALUES (100002, 'cla_sign', 'Signed CLA Group', (SELECT id from people where username='admin'), 'tracking');
@ -589,7 +589,3 @@ INSERT INTO groups (name, display_name, owner_id, group_type) VALUES ('fas-syste
INSERT INTO person_roles (person_id, group_id, role_type, role_status, internal_comments, sponsor_id) VALUES ((SELECT id from people where username='admin'), (select id from groups where name='accounts'), 'administrator', 'approved', 'created at install time', (SELECT id from people where username='admin'));
-- Give admin user his email address
INSERT INTO person_emails (email, person_id, verified) VALUES ('root@localhost', (SELECT id from people where username='admin'), true);
INSERT INTO email_purposes (email_id, person_id, purpose) VALUES ((SELECT id from person_emails where email='root@localhost'), (SELECT id from people where username='admin'), 'primary');

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff