Making the users_with_username function call in the register view slightly cleaner
[mediagoblin.git] / mediagoblin / auth / views.py
1 # GNU MediaGoblin -- federated, autonomous media hosting
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
17 import uuid
18
19 from webob import exc
20
21 from mediagoblin import messages
22 from mediagoblin import mg_globals
23 from mediagoblin.util import render_to_response, redirect
24 from mediagoblin.util import pass_to_ugettext as _
25 from mediagoblin.db.util import ObjectId
26 from mediagoblin.auth import lib as auth_lib
27 from mediagoblin.auth import forms as auth_forms
28 from mediagoblin.auth.lib import send_verification_email
29
30
31 def register(request):
32 """
33 Your classic registration view!
34 """
35 # Redirects to indexpage if registrations are disabled
36 if not mg_globals.app_config["allow_registration"]:
37 messages.add_message(
38 request,
39 messages.WARNING,
40 _('Sorry, registration is disabled on this instance.'))
41 return redirect(request, "index")
42
43 register_form = auth_forms.RegistrationForm(request.POST)
44
45 if request.method == 'POST' and register_form.validate():
46 # TODO: Make sure the user doesn't exist already
47
48 users_with_username = request.db.User.find(
49 {'username': request.POST['username'].lower()}).count()
50
51 if users_with_username:
52 register_form.username.errors.append(
53 _(u'Sorry, a user with that name already exists.'))
54
55 else:
56 # Create the user
57 user = request.db.User()
58 user['username'] = request.POST['username'].lower()
59 user['email'] = request.POST['email']
60 user['pw_hash'] = auth_lib.bcrypt_gen_password_hash(
61 request.POST['password'])
62 user.save(validate=True)
63
64 # log the user in
65 request.session['user_id'] = unicode(user['_id'])
66 request.session.save()
67
68 # send verification email
69 send_verification_email(user, request)
70
71 # redirect the user to their homepage... there will be a
72 # message waiting for them to verify their email
73 return redirect(
74 request, 'mediagoblin.user_pages.user_home',
75 user=user['username'])
76
77 return render_to_response(
78 request,
79 'mediagoblin/auth/register.html',
80 {'register_form': register_form})
81
82
83 def login(request):
84 """
85 MediaGoblin login view.
86
87 If you provide the POST with 'next', it'll redirect to that view.
88 """
89 login_form = auth_forms.LoginForm(request.POST)
90
91 login_failed = False
92
93 if request.method == 'POST' and login_form.validate():
94 user = request.db.User.one(
95 {'username': request.POST['username'].lower()})
96
97 if user and user.check_login(request.POST['password']):
98 # set up login in session
99 request.session['user_id'] = unicode(user['_id'])
100 request.session.save()
101
102 if request.POST.get('next'):
103 return exc.HTTPFound(location=request.POST['next'])
104 else:
105 return redirect(request, "index")
106
107 else:
108 # Prevent detecting who's on this system by testing login
109 # attempt timings
110 auth_lib.fake_login_attempt()
111 login_failed = True
112
113 return render_to_response(
114 request,
115 'mediagoblin/auth/login.html',
116 {'login_form': login_form,
117 'next': request.GET.get('next') or request.POST.get('next'),
118 'login_failed': login_failed,
119 'allow_registration': mg_globals.app_config["allow_registration"]})
120
121
122 def logout(request):
123 # Maybe deleting the user_id parameter would be enough?
124 request.session.delete()
125
126 return redirect(request, "index")
127
128
129 def verify_email(request):
130 """
131 Email verification view
132
133 validates GET parameters against database and unlocks the user account, if
134 you are lucky :)
135 """
136 # If we don't have userid and token parameters, we can't do anything; 404
137 if not request.GET.has_key('userid') or not request.GET.has_key('token'):
138 return exc.HTTPNotFound()
139
140 user = request.db.User.find_one(
141 {'_id': ObjectId(unicode(request.GET['userid']))})
142
143 if user and user['verification_key'] == unicode(request.GET['token']):
144 user['status'] = u'active'
145 user['email_verified'] = True
146 user.save()
147 messages.add_message(
148 request,
149 messages.SUCCESS,
150 _("Your email address has been verified. "
151 "You may now login, edit your profile, and submit images!"))
152 else:
153 messages.add_message(
154 request,
155 messages.ERROR,
156 _('The verification key or user id is incorrect'))
157
158 return redirect(
159 request, 'mediagoblin.user_pages.user_home',
160 user=request.user['username'])
161
162
163 def resend_activation(request):
164 """
165 The reactivation view
166
167 Resend the activation email.
168 """
169 request.user['verification_key'] = unicode(uuid.uuid4())
170 request.user.save()
171
172 send_verification_email(request.user, request)
173
174 messages.add_message(
175 request,
176 messages.INFO,
177 _('Resent your verification email.'))
178 return redirect(
179 request, 'mediagoblin.user_pages.user_home',
180 user=request.user['username'])