Commit | Line | Data |
---|---|---|
8e1e744d | 1 | # GNU MediaGoblin -- federated, autonomous media hosting |
24181820 CAW |
2 | # Copyright (C) 2011 Free Software Foundation, Inc |
3 | # | |
4 | # This program is free software: you can redistribute it and/or modify | |
5 | # it under the terms of the GNU Affero General Public License as published by | |
6 | # the Free Software Foundation, either version 3 of the License, or | |
7 | # (at your option) any later version. | |
8 | # | |
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU Affero General Public License for more details. | |
13 | # | |
14 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | ||
73a1bc85 | 17 | import bson.objectid |
24181820 CAW |
18 | from webob import Response, exc |
19 | ||
20 | from mediagoblin.auth import lib as auth_lib | |
21 | from mediagoblin.auth import forms as auth_forms | |
5c42a82c | 22 | from mediagoblin.util import send_email |
4c093e85 | 23 | from mediagoblin import globals as mgoblin_globals |
24181820 CAW |
24 | |
25 | ||
26 | def register(request): | |
27 | """ | |
28 | Your classic registration view! | |
29 | """ | |
30 | register_form = auth_forms.RegistrationForm(request.POST) | |
31 | ||
32 | if request.method == 'POST' and register_form.validate(): | |
33 | # TODO: Make sure the user doesn't exist already | |
ce72a1bb | 34 | |
24181820 | 35 | users_with_username = \ |
ce72a1bb JK |
36 | request.db.User.find({ |
37 | 'username': request.POST['username'].lower() | |
38 | }).count() | |
24181820 CAW |
39 | |
40 | if users_with_username: | |
41 | register_form.username.errors.append( | |
42 | u'Sorry, a user with that name already exists.') | |
43 | ||
44 | else: | |
45 | # Create the user | |
46 | entry = request.db.User() | |
ce72a1bb | 47 | entry['username'] = request.POST['username'].lower() |
24181820 CAW |
48 | entry['email'] = request.POST['email'] |
49 | entry['pw_hash'] = auth_lib.bcrypt_gen_password_hash( | |
50 | request.POST['password']) | |
51 | entry.save(validate=True) | |
5c42a82c | 52 | |
4c093e85 JW |
53 | email_template = request.template_env.get_template( |
54 | 'mediagoblin/auth/verification_email.txt') | |
55 | ||
56 | # TODO: There is no error handling in place | |
57 | send_email( | |
58 | mgoblin_globals.email_sender_address, | |
3eae207c | 59 | [entry['email']], |
4c093e85 JW |
60 | # TODO |
61 | # Due to the distributed nature of GNU MediaGoblin, we should | |
62 | # find a way to send some additional information about the | |
63 | # specific GNU MediaGoblin instance in the subject line. For | |
64 | # example "GNU MediaGoblin @ Wandborg - [...]". | |
65 | 'GNU MediaGoblin - Verify email', | |
66 | email_template.render( | |
db5912e3 | 67 | username=entry['username'], |
4c093e85 JW |
68 | verification_url='http://{host}{uri}?userid={userid}&token={verification_key}'.format( |
69 | host=request.host, | |
70 | uri=request.urlgen('mediagoblin.auth.verify_email'), | |
71 | userid=unicode(entry['_id']), | |
72 | verification_key=entry['verification_key']))) | |
5c42a82c | 73 | |
24181820 | 74 | # Redirect to register_success |
73cb7b8e | 75 | return exc.HTTPFound( |
24181820 CAW |
76 | location=request.urlgen("mediagoblin.auth.register_success")) |
77 | ||
78 | # render | |
79 | template = request.template_env.get_template( | |
80 | 'mediagoblin/auth/register.html') | |
81 | return Response( | |
82 | template.render( | |
83 | {'request': request, | |
84 | 'register_form': register_form})) | |
85 | ||
86 | ||
87 | def register_success(request): | |
88 | template = request.template_env.get_template( | |
89 | 'mediagoblin/auth/register_success.html') | |
90 | return Response( | |
91 | template.render( | |
92 | {'request': request})) | |
93 | ||
94 | ||
692fd1c9 | 95 | def login(request): |
a3776717 | 96 | """ |
8e1e744d | 97 | MediaGoblin login view. |
a3776717 CAW |
98 | |
99 | If you provide the POST with 'next', it'll redirect to that view. | |
100 | """ | |
692fd1c9 CAW |
101 | login_form = auth_forms.LoginForm(request.POST) |
102 | ||
a3776717 CAW |
103 | login_failed = False |
104 | ||
692fd1c9 | 105 | if request.method == 'POST' and login_form.validate(): |
b058cf15 | 106 | user = request.db.User.one( |
ce72a1bb | 107 | {'username': request.POST['username'].lower()}) |
692fd1c9 | 108 | |
d1938963 | 109 | if user and user.check_login(request.POST['password']): |
692fd1c9 CAW |
110 | # set up login in session |
111 | request.session['user_id'] = unicode(user['_id']) | |
a3776717 | 112 | request.session.save() |
692fd1c9 | 113 | |
574d1511 | 114 | if request.POST.get('next'): |
a3776717 CAW |
115 | return exc.HTTPFound(location=request.POST['next']) |
116 | else: | |
117 | return exc.HTTPFound( | |
118 | location=request.urlgen("index")) | |
692fd1c9 CAW |
119 | |
120 | else: | |
121 | # Prevent detecting who's on this system by testing login | |
122 | # attempt timings | |
123 | auth_lib.fake_login_attempt() | |
a3776717 | 124 | login_failed = True |
692fd1c9 CAW |
125 | |
126 | # render | |
127 | template = request.template_env.get_template( | |
128 | 'mediagoblin/auth/login.html') | |
129 | return Response( | |
130 | template.render( | |
131 | {'request': request, | |
a3776717 CAW |
132 | 'login_form': login_form, |
133 | 'next': request.GET.get('next') or request.POST.get('next'), | |
134 | 'login_failed': login_failed})) | |
692fd1c9 CAW |
135 | |
136 | ||
137 | def logout(request): | |
b97232fa CAW |
138 | # Maybe deleting the user_id parameter would be enough? |
139 | request.session.delete() | |
140 | ||
141 | return exc.HTTPFound( | |
142 | location=request.urlgen("index")) | |
db1a438f | 143 | |
5866d1a8 | 144 | |
db1a438f | 145 | def verify_email(request): |
4c093e85 JW |
146 | """ |
147 | Email verification view | |
148 | ||
149 | validates GET parameters against database and unlocks the user account, if | |
150 | you are lucky :) | |
151 | """ | |
db1a438f | 152 | user = request.db.User.find_one( |
4c093e85 | 153 | {'_id': bson.objectid.ObjectId(unicode(request.GET.get('userid')))}) |
db1a438f JW |
154 | |
155 | verification_successful = bool | |
156 | ||
4c093e85 | 157 | if user and user['verification_key'] == unicode(request.GET.get('token')): |
db1a438f JW |
158 | user['status'] = u'active' |
159 | user['email_verified'] = True | |
160 | verification_successful = True | |
161 | user.save() | |
162 | else: | |
163 | verification_successful = False | |
164 | ||
165 | template = request.template_env.get_template( | |
166 | 'mediagoblin/auth/verify_email.html') | |
167 | return Response( | |
168 | template.render( | |
169 | {'request': request, | |
170 | 'user': user, | |
171 | 'verification_successful': verification_successful})) | |
28afb47c AM |
172 | |
173 | def verify_email_notice(request): | |
174 | """ | |
175 | Verify warning view. | |
176 | ||
177 | When the user tries to do some action that requires their account | |
178 | to be verified beforehand, this view is called upon! | |
179 | """ | |
180 | ||
181 | template = request.template_env.get_template( | |
182 | 'mediagoblin/auth/verification_needed.html') | |
183 | return Response( | |
184 | template.render( | |
185 | {'request': request})) | |
186 | ||
5866d1a8 | 187 | |
b93a6a22 AM |
188 | def resend_activation(request): |
189 | """ | |
190 | The reactivation view | |
191 | ||
192 | Resend the activation email. | |
193 | """ | |
194 | ||
195 | request.user.generate_new_verification_key() | |
196 | ||
197 | # Copied shamelessly from the register view above. | |
198 | ||
199 | email_template = request.template_env.get_template( | |
200 | 'mediagoblin/auth/verification_email.txt') | |
201 | ||
202 | # TODO: There is no error handling in place | |
203 | send_email( | |
204 | mgoblin_globals.email_sender_address, | |
205 | [request.user['email']], | |
206 | # TODO | |
207 | # Due to the distributed nature of GNU MediaGoblin, we should | |
208 | # find a way to send some additional information about the | |
209 | # specific GNU MediaGoblin instance in the subject line. For | |
210 | # example "GNU MediaGoblin @ Wandborg - [...]". | |
211 | 'GNU MediaGoblin - Verify email', | |
212 | email_template.render( | |
213 | username=request.user['username'], | |
214 | verification_url='http://{host}{uri}?userid={userid}&token={verification_key}'.format( | |
215 | host=request.host, | |
216 | uri=request.urlgen('mediagoblin.auth.verify_email'), | |
217 | userid=unicode(request.user['_id']), | |
218 | verification_key=request.user['verification_key']))) | |
219 | ||
5866d1a8 CAW |
220 | return exc.HTTPFound( |
221 | location=request.urlgen('mediagoblin.auth.resend_verification_success')) | |
b93a6a22 | 222 | |
b93a6a22 | 223 | |
5866d1a8 | 224 | def resend_activation_success(request): |
b93a6a22 | 225 | template = request.template_env.get_template( |
5866d1a8 CAW |
226 | 'mediagoblin/auth/resent_verification_email.html') |
227 | return Response( | |
228 | template.render( | |
229 | {'request': request})) |