|
a/opensourceprojects/controllers.py |
|
b/opensourceprojects/controllers.py |
1 |
|
1 |
|
2 |
class RootController:
|
2 |
import allura.tasks.mail_tasks
|
|
|
3 |
from allura.controllers.root import RootController as AlluraRootController
|
|
|
4 |
from allura.controllers.auth import AuthController
|
|
|
5 |
from allura.lib.decorators import require_post
|
|
|
6 |
from allura.lib.widgets import forms
|
|
|
7 |
from allura import model as M
|
|
|
8 |
from allura.lib import plugin
|
|
|
9 |
|
|
|
10 |
from tg import expose, session, flash, redirect, validate, config
|
|
|
11 |
from tg.decorators import with_trailing_slash, without_trailing_slash
|
|
|
12 |
from pylons import c, g, request, response
|
|
|
13 |
|
|
|
14 |
import ew as ew_core
|
|
|
15 |
import ew.jinja2_ew as ew
|
|
|
16 |
from allura.lib import validators as V
|
|
|
17 |
from formencode import validators as fev
|
|
|
18 |
import formencode
|
|
|
19 |
from allura.lib import helpers as h
|
|
|
20 |
import string, random, os
|
|
|
21 |
from hashlib import sha256
|
|
|
22 |
import logging
|
|
|
23 |
|
|
|
24 |
log = logging.getLogger(__name__)
|
|
|
25 |
|
|
|
26 |
class OSPRegistrationForm(forms.ForgeForm):
|
|
|
27 |
template = 'jinja:opensourceprojects:templates/widgets/forge_form.html'
|
|
|
28 |
class fields(ew_core.NameList):
|
|
|
29 |
display_name = ew.TextField(
|
|
|
30 |
label='Display Name',
|
|
|
31 |
validator=fev.UnicodeString(not_empty=True),
|
|
|
32 |
attrs={'placeholder':'Display Name', 'class':'displayname'},
|
|
|
33 |
show_label=False
|
|
|
34 |
)
|
|
|
35 |
username = ew.TextField(
|
|
|
36 |
label='Desired Username',
|
|
|
37 |
validator=fev.Regex(h.re_path_portion, not_empty=True),
|
|
|
38 |
attrs={'placeholder':'Username', 'class':'username'},
|
|
|
39 |
show_label=False
|
|
|
40 |
)
|
|
|
41 |
username.validator._messages['invalid'] = (
|
|
|
42 |
'Usernames can include letters, numbers, and dashes, but must start with a letter' )
|
|
|
43 |
email = ew.TextField(
|
|
|
44 |
label = 'Email Address',
|
|
|
45 |
validator=fev.Email(not_empty=True),
|
|
|
46 |
attrs={'placeholder':'Email Address', 'class':'email'},
|
|
|
47 |
show_label=False
|
|
|
48 |
)
|
|
|
49 |
|
|
|
50 |
@ew_core.core.validator
|
|
|
51 |
def to_python(self, value, state):
|
|
|
52 |
d = super(OSPRegistrationForm, self).to_python(value, state)
|
|
|
53 |
value['username'] = username = value['username'].lower()
|
|
|
54 |
if M.User.by_username(username):
|
|
|
55 |
raise formencode.Invalid('That username is already taken. Please choose another.',
|
|
|
56 |
value, state)
|
|
|
57 |
|
|
|
58 |
if M.EmailAddress.query.get(_id=value['email'].lower(), confirmed=True):
|
|
|
59 |
raise formencode.Invalid('That email address is already taken. Please choose another.',
|
|
|
60 |
value, state)
|
|
|
61 |
|
|
|
62 |
return d
|
|
|
63 |
|
|
|
64 |
form = OSPRegistrationForm(action='/auth2/save_new', submit_text='Sign Up')
|
|
|
65 |
|
|
|
66 |
class OSPAuthController(AuthController):
|
|
|
67 |
"""
|
|
|
68 |
This Auth controller modifies account registration
|
|
|
69 |
"""
|
|
|
70 |
|
|
|
71 |
@expose('jinja:opensourceprojects:templates/create_account.html')
|
|
|
72 |
def create_account(self, **kw):
|
|
|
73 |
c.form = form
|
|
|
74 |
return dict()
|
|
|
75 |
|
|
|
76 |
@expose()
|
|
|
77 |
@require_post()
|
|
|
78 |
@validate(form, error_handler=create_account)
|
|
|
79 |
def save_new(self, display_name=None, username=None, email=None, **kw):
|
|
|
80 |
pw = OSPAuthController.random_pass(20)
|
|
|
81 |
user = M.User.register(
|
|
|
82 |
dict(username=username,
|
|
|
83 |
display_name=display_name,
|
|
|
84 |
password=pw,
|
|
|
85 |
disabled=True))
|
|
|
86 |
|
|
|
87 |
user.email_addresses.append(email)
|
|
|
88 |
em = M.EmailAddress.upsert(str(email))
|
|
|
89 |
em.claimed_by_user_id=user._id
|
|
|
90 |
self.send_account_link(em, pw)
|
|
|
91 |
flash('User "%s" registered, check you email for confirmation' % user.get_pref('display_name'))
|
|
|
92 |
redirect('/')
|
|
|
93 |
|
|
|
94 |
@staticmethod
|
|
|
95 |
def send_account_link(email, passwd):
|
|
|
96 |
email.nonce = sha256(os.urandom(10)).hexdigest()
|
|
|
97 |
log.info('Sending verification link to %s', email._id)
|
|
|
98 |
text = '''
|
|
|
99 |
You are receiving this email, to confirm the creationg of the account
|
|
|
100 |
%s at opensourceprojects.eu.
|
|
|
101 |
|
|
|
102 |
To verify the account please visit the following URL:
|
|
|
103 |
|
3 |
pass
|
104 |
%s
|
|
|
105 |
|
|
|
106 |
Your password for this account is
|
|
|
107 |
|
|
|
108 |
%s
|
|
|
109 |
|
|
|
110 |
If you did not request this account, please ignore this email.
|
|
|
111 |
|
|
|
112 |
''' % (email.claimed_by_user().username, g.url('/auth2/verify_acct', a=email.nonce), passwd)
|
|
|
113 |
|
|
|
114 |
allura.tasks.mail_tasks.sendmail.post(
|
|
|
115 |
destinations=[email._id],
|
|
|
116 |
fromaddr=email._id,
|
|
|
117 |
reply_to='',
|
|
|
118 |
subject='OpensourceProjects.eu: Account creation',
|
|
|
119 |
message_id=h.gen_message_id(),
|
|
|
120 |
text=text)
|
|
|
121 |
|
|
|
122 |
@expose('jinja:opensourceprojects:templates/verify_acct.html')
|
|
|
123 |
def verify_acct(self, a):
|
|
|
124 |
"""
|
|
|
125 |
Verify an account using an email token
|
|
|
126 |
"""
|
|
|
127 |
addr = M.EmailAddress.query.get(nonce=a)
|
|
|
128 |
if not addr:
|
|
|
129 |
flash('Unknown verification link', 'error')
|
|
|
130 |
redirect('/')
|
|
|
131 |
|
|
|
132 |
addr.confirmed = True
|
|
|
133 |
user = addr.claimed_by_user()
|
|
|
134 |
user.disabled = False
|
|
|
135 |
return dict(username=user.username)
|
|
|
136 |
|
|
|
137 |
@staticmethod
|
|
|
138 |
def random_pass(size=8, chars=string.ascii_letters + string.digits):
|
|
|
139 |
"""
|
|
|
140 |
Generate a random password
|
|
|
141 |
"""
|
|
|
142 |
return ''.join(random.choice(chars) for i in range(size))
|
|
|
143 |
|
|
|
144 |
|
|
|
145 |
class RootController(AlluraRootController):
|
|
|
146 |
|
|
|
147 |
"""
|
|
|
148 |
The root controller for OpenSourceProjects.eu
|
|
|
149 |
|
|
|
150 |
Add the following to the .ini config file to enable
|
|
|
151 |
this root.
|
|
|
152 |
|
|
|
153 |
[app:main]
|
|
|
154 |
override_root = opensourceprojects
|
|
|
155 |
|
|
|
156 |
This controller adds:
|
|
|
157 |
* An about page
|
|
|
158 |
* A new auth controller
|
|
|
159 |
* A new front page
|
|
|
160 |
"""
|
|
|
161 |
|
|
|
162 |
# auth = OSPAuthController()
|
|
|
163 |
auth2 = OSPAuthController()
|
|
|
164 |
|
|
|
165 |
@expose('jinja:opensourceprojects:templates/about.html')
|
|
|
166 |
def about(self):
|
|
|
167 |
return dict()
|
|
|
168 |
|
|
|
169 |
@expose('jinja:opensourceprojects:templates/frontpage.html')
|
|
|
170 |
@with_trailing_slash
|
|
|
171 |
def index(self, **kw):
|
|
|
172 |
return dict(form=OSPRegistrationForm(submit_text='Sign Up now!', action='/auth2/save_new'))
|
|
|
173 |
|
|
|
174 |
|
|
|
175 |
|