import allura.tasks.mail_tasks
from allura.controllers.root import RootController as AlluraRootController
from allura.controllers.auth import AuthController
from allura.lib.decorators import require_post
from allura.lib.widgets import forms
from allura import model as M
from allura.lib import plugin
from tg import expose, session, flash, redirect, validate, config
from tg.decorators import with_trailing_slash, without_trailing_slash
from pylons import c, g, request, response
import ew as ew_core
import ew.jinja2_ew as ew
from allura.lib import validators as V
from formencode import validators as fev
import formencode
from allura.lib import helpers as h
import string, random, os
from hashlib import sha256
import logging
log = logging.getLogger(__name__)
class OSPRegistrationForm(forms.ForgeForm):
template = 'jinja:opensourceprojects:templates/widgets/forge_form.html'
class fields(ew_core.NameList):
display_name = ew.TextField(
label='Display Name',
validator=fev.UnicodeString(not_empty=True),
attrs={'placeholder':'Display Name', 'class':'displayname'},
show_label=False
)
username = ew.TextField(
label='Desired Username',
validator=fev.Regex(h.re_path_portion, not_empty=True),
attrs={'placeholder':'Username', 'class':'username'},
show_label=False
)
username.validator._messages['invalid'] = (
'Usernames can include letters, numbers, and dashes, but must start with a letter' )
email = ew.TextField(
label = 'Email Address',
validator=fev.Email(not_empty=True),
attrs={'placeholder':'Email Address', 'class':'email'},
show_label=False
)
@ew_core.core.validator
def to_python(self, value, state):
d = super(OSPRegistrationForm, self).to_python(value, state)
value['username'] = username = value['username'].lower()
if M.User.by_username(username):
raise formencode.Invalid('That username is already taken. Please choose another.',
value, state)
if M.EmailAddress.query.get(_id=value['email'].lower(), confirmed=True):
raise formencode.Invalid('That email address is already taken. Please choose another.',
value, state)
return d
form = OSPRegistrationForm(action='/auth/save_new', submit_text='Sign Up')
class OSPAuthController(AuthController):
"""
This Auth controller modifies account registration
"""
@expose('jinja:opensourceprojects:templates/create_account.html')
def create_account(self, **kw):
c.form = form
return dict()
@expose()
@require_post()
@validate(form, error_handler=create_account)
def save_new(self, display_name=None, username=None, email=None, **kw):
pw = OSPAuthController.random_pass(20)
user = M.User.register(
dict(username=username,
display_name=display_name,
password=pw,
disabled=True))
user.email_addresses.append(email)
em = M.EmailAddress.upsert(str(email))
em.claimed_by_user_id=user._id
self.send_account_link(em, pw)
flash('User "%s" registered, check you email for confirmation' % user.get_pref('display_name'))
redirect('/')
@staticmethod
def send_account_link(email, passwd):
email.nonce = sha256(os.urandom(10)).hexdigest()
log.info('Sending verification link to %s', email._id)
text = '''
You are receiving this email, to confirm the creationg of the account
%s at opensourceprojects.eu.
To verify the account please visit the following URL:
%s
Your password for this account is
%s
If you did not request this account, please ignore this email.
''' % (email.claimed_by_user().username, g.url('/auth/verify_acct', a=email.nonce), passwd)
allura.tasks.mail_tasks.sendmail.post(
destinations=[email._id],
fromaddr=email._id,
reply_to='',
subject='OpensourceProjects.eu: Account creation',
message_id=h.gen_message_id(),
text=text)
@expose()
def verify_acct(self, a):
"""
Verify an account using an email token
"""
addr = M.EmailAddress.query.get(nonce=a)
if not addr:
flash('Unknown verification link', 'error')
redirect('/')
addr.confirmed = True
addr.nonce = ''
user = addr.claimed_by_user()
user.disabled = False
flash('User "%s" confirmed, you can now login into your account' % user.username)
redirect('/')
@staticmethod
def random_pass(size=8, chars=string.ascii_letters + string.digits):
"""
Generate a random password
"""
return ''.join(random.choice(chars) for i in range(size))
class RootController(AlluraRootController):
"""
The root controller for OpenSourceProjects.eu
Add the following to the .ini config file to enable
this root.
[app:main]
override_root = opensourceprojects
This controller adds:
* An about page
* A new auth controller
* A new front page
"""
auth = OSPAuthController()
@expose('jinja:opensourceprojects:templates/about.html')
def about(self):
return dict()
@expose('jinja:opensourceprojects:templates/frontpage.html')
@with_trailing_slash
def index(self, **kw):
return dict(form=OSPRegistrationForm(submit_text='Sign Up now!', action='/auth/save_new'))