Added functionality to send out verification email upon successful registration
[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
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
22 from mediagoblin.util import send_email
23
24
25 def register(request):
26 """
27 Your classic registration view!
28 """
29 register_form = auth_forms.RegistrationForm(request.POST)
30
31 if request.method == 'POST' and register_form.validate():
32 # TODO: Make sure the user doesn't exist already
33 users_with_username = \
34 request.db.User.find({'username': request.POST['username']}).count()
35
36 if users_with_username:
37 register_form.username.errors.append(
38 u'Sorry, a user with that name already exists.')
39
40 else:
41 # Create the user
42 entry = request.db.User()
43 entry['username'] = request.POST['username']
44 entry['email'] = request.POST['email']
45 entry['pw_hash'] = auth_lib.bcrypt_gen_password_hash(
46 request.POST['password'])
47 entry.save(validate=True)
48
49 # TODO: Move this setting to a better place
50 EMAIL_SENDER_ADDRESS = 'mediagoblin@fakehost'
51
52 ''' TODO Index - Regarding sending of verification email
53 1. There is no error handling in place
54 2. Due to the distributed nature of GNU MediaGoblin, we should find a way to send some additional information about the specific GNU MediaGoblin instance in the subject line. For example "GNU MediaGoblin @ Wandborg - [...]".
55 3. The verification link generation does not detect and adapt to access via the HTTPS protocol.
56 '''
57
58 # TODO (1)
59 send_email(
60 EMAIL_SENDER_ADDRESS,
61 entry['email'],
62 'GNU MediaGoblin - Verify email', # TODO (2)
63 'http://{host}{uri}?userid={userid}&token={verification_key}'.format( # TODO (3)
64 host = request.host,
65 uri = request.urlgen('mediagoblin.auth.verify_email'),
66 userid = unicode( entry['_id'] ),
67 verification_key = entry['verification_key']
68 ))
69
70 # Redirect to register_success
71 return exc.HTTPFound(
72 location=request.urlgen("mediagoblin.auth.register_success"))
73
74 # render
75 template = request.template_env.get_template(
76 'mediagoblin/auth/register.html')
77 return Response(
78 template.render(
79 {'request': request,
80 'register_form': register_form}))
81
82
83 def register_success(request):
84 template = request.template_env.get_template(
85 'mediagoblin/auth/register_success.html')
86 return Response(
87 template.render(
88 {'request': request}))
89
90
91 def login(request):
92 """
93 MediaGoblin login view.
94
95 If you provide the POST with 'next', it'll redirect to that view.
96 """
97 login_form = auth_forms.LoginForm(request.POST)
98
99 login_failed = False
100
101 if request.method == 'POST' and login_form.validate():
102 user = request.db.User.one(
103 {'username': request.POST['username']})
104
105 if user and user.check_login(request.POST['password']):
106 # set up login in session
107 request.session['user_id'] = unicode(user['_id'])
108 request.session.save()
109
110 if request.POST.get('next'):
111 return exc.HTTPFound(location=request.POST['next'])
112 else:
113 return exc.HTTPFound(
114 location=request.urlgen("index"))
115
116 else:
117 # Prevent detecting who's on this system by testing login
118 # attempt timings
119 auth_lib.fake_login_attempt()
120 login_failed = True
121
122 # render
123 template = request.template_env.get_template(
124 'mediagoblin/auth/login.html')
125 return Response(
126 template.render(
127 {'request': request,
128 'login_form': login_form,
129 'next': request.GET.get('next') or request.POST.get('next'),
130 'login_failed': login_failed}))
131
132
133 def logout(request):
134 # Maybe deleting the user_id parameter would be enough?
135 request.session.delete()
136
137 return exc.HTTPFound(
138 location=request.urlgen("index"))
139
140 def verify_email(request):
141 import bson.objectid
142 user = request.db.User.find_one(
143 {'_id': bson.objectid.ObjectId( unicode( request.GET.get('userid') ) )})
144
145 verification_successful = bool
146
147 if user and user['verification_key'] == unicode( request.GET.get('token') ):
148 user['status'] = u'active'
149 user['email_verified'] = True
150 verification_successful = True
151 user.save()
152 else:
153 verification_successful = False
154
155 template = request.template_env.get_template(
156 'mediagoblin/auth/verify_email.html')
157 return Response(
158 template.render(
159 {'request': request,
160 'user': user,
161 'verification_successful': verification_successful}))