|
a |
|
b/qiita_pet/handlers/auth_handlers.py |
|
|
1 |
# ----------------------------------------------------------------------------- |
|
|
2 |
# Copyright (c) 2014--, The Qiita Development Team. |
|
|
3 |
# |
|
|
4 |
# Distributed under the terms of the BSD 3-clause License. |
|
|
5 |
# |
|
|
6 |
# The full license is in the file LICENSE, distributed with this software. |
|
|
7 |
# ----------------------------------------------------------------------------- |
|
|
8 |
|
|
|
9 |
from tornado.escape import url_escape, json_encode |
|
|
10 |
|
|
|
11 |
from qiita_pet.handlers.base_handlers import BaseHandler |
|
|
12 |
from qiita_core.qiita_settings import qiita_config, r_client |
|
|
13 |
from qiita_core.util import execute_as_transaction |
|
|
14 |
from qiita_core.exceptions import (IncorrectPasswordError, IncorrectEmailError, |
|
|
15 |
UnverifiedEmailError) |
|
|
16 |
from qiita_db.util import send_email |
|
|
17 |
from qiita_db.user import User |
|
|
18 |
from qiita_db.exceptions import (QiitaDBUnknownIDError, QiitaDBDuplicateError, |
|
|
19 |
QiitaDBError) |
|
|
20 |
# login code modified from https://gist.github.com/guillaumevincent/4771570 |
|
|
21 |
|
|
|
22 |
|
|
|
23 |
class AuthCreateHandler(BaseHandler): |
|
|
24 |
"""User Creation""" |
|
|
25 |
def get(self): |
|
|
26 |
try: |
|
|
27 |
error_message = self.get_argument("error") |
|
|
28 |
# Tornado can raise an Exception directly, not a defined type |
|
|
29 |
except Exception: |
|
|
30 |
error_message = "" |
|
|
31 |
self.render("create_user.html", error=error_message) |
|
|
32 |
|
|
|
33 |
@execute_as_transaction |
|
|
34 |
def post(self): |
|
|
35 |
username = self.get_argument("email", "").strip().lower() |
|
|
36 |
password = self.get_argument("newpass", "") |
|
|
37 |
info = {} |
|
|
38 |
for info_column in ("name", "affiliation", "address", "phone"): |
|
|
39 |
hold = self.get_argument(info_column, None) |
|
|
40 |
if hold: |
|
|
41 |
info[info_column] = hold |
|
|
42 |
|
|
|
43 |
created = False |
|
|
44 |
try: |
|
|
45 |
created = User.create(username, password, info) |
|
|
46 |
except QiitaDBDuplicateError: |
|
|
47 |
msg = "Email already registered as a user" |
|
|
48 |
|
|
|
49 |
if created: |
|
|
50 |
info = created.info |
|
|
51 |
try: |
|
|
52 |
# qiita_config.base_url doesn't have a / at the end, but the |
|
|
53 |
# qiita_config.portal_dir has it at the beginning but not at |
|
|
54 |
# the end. This constructs the correct URL |
|
|
55 |
url = qiita_config.base_url + qiita_config.portal_dir |
|
|
56 |
send_email(username, "QIITA: Verify Email Address", "Please " |
|
|
57 |
"click the following link to verify email address: " |
|
|
58 |
"%s/auth/verify/%s?email=%s\n\nBy clicking you are " |
|
|
59 |
"accepting our term and conditions: " |
|
|
60 |
"%s/iframe/?iframe=qiita-terms" |
|
|
61 |
% (url, info['user_verify_code'], |
|
|
62 |
url_escape(username), url)) |
|
|
63 |
except Exception: |
|
|
64 |
msg = ("Unable to send verification email. Please contact the " |
|
|
65 |
"qiita developers at <a href='mailto:%s'>%s</a>") % ( |
|
|
66 |
qiita_config.help_email, qiita_config.help_email) |
|
|
67 |
self.redirect(u"%s/?level=danger&message=%s" |
|
|
68 |
% (qiita_config.portal_dir, url_escape(msg))) |
|
|
69 |
return |
|
|
70 |
|
|
|
71 |
msg = ("<h3>User Successfully Created</h3><p>Your Qiita account " |
|
|
72 |
"has been successfully created. An email has been sent to " |
|
|
73 |
"the email address you provided. This email contains " |
|
|
74 |
"instructions on how to activate your account.</p>" |
|
|
75 |
"<p>If you don't receive your activation email within a " |
|
|
76 |
"couple of minutes, check your spam folder. If you still " |
|
|
77 |
"don't see it, send us an email at <a " |
|
|
78 |
"href=\"mailto:%s\">%s" |
|
|
79 |
"</a>.</p>") % (qiita_config.help_email, |
|
|
80 |
qiita_config.help_email) |
|
|
81 |
self.redirect(u"%s/?level=success&message=%s" % |
|
|
82 |
(qiita_config.portal_dir, url_escape(msg))) |
|
|
83 |
else: |
|
|
84 |
error_msg = u"?error=" + url_escape(msg) |
|
|
85 |
self.redirect(u"%s/auth/create/%s" |
|
|
86 |
% (qiita_config.portal_dir, error_msg)) |
|
|
87 |
|
|
|
88 |
|
|
|
89 |
class AuthVerifyHandler(BaseHandler): |
|
|
90 |
def get(self, code): |
|
|
91 |
email = self.get_argument("email").strip().lower() |
|
|
92 |
|
|
|
93 |
code_is_valid = False |
|
|
94 |
msg = "This code is not valid." |
|
|
95 |
|
|
|
96 |
# an exception is raised if the 'code type' is not available, otherwise |
|
|
97 |
# the method determines the validity of the code |
|
|
98 |
try: |
|
|
99 |
code_is_valid = User.verify_code(email, code, "create") |
|
|
100 |
except QiitaDBError: |
|
|
101 |
msg = "This user has already created an account." |
|
|
102 |
|
|
|
103 |
if code_is_valid: |
|
|
104 |
msg = "Successfully verified user. You are now free to log in." |
|
|
105 |
color = "black" |
|
|
106 |
r_client.zadd('qiita-usernames', {email: 0}) |
|
|
107 |
else: |
|
|
108 |
color = "red" |
|
|
109 |
|
|
|
110 |
self.render("user_verified.html", msg=msg, color=color, |
|
|
111 |
email=self.get_argument("email").strip()) |
|
|
112 |
|
|
|
113 |
|
|
|
114 |
class AuthLoginHandler(BaseHandler): |
|
|
115 |
"""user login, no page necessary""" |
|
|
116 |
def get(self): |
|
|
117 |
self.redirect("%s/" % qiita_config.portal_dir) |
|
|
118 |
|
|
|
119 |
@execute_as_transaction |
|
|
120 |
def post(self): |
|
|
121 |
username = self.get_argument("username", "").strip().lower() |
|
|
122 |
passwd = self.get_argument("password", "") |
|
|
123 |
nextpage = self.get_argument("next", None) |
|
|
124 |
if nextpage is None: |
|
|
125 |
if "auth/" not in self.request.headers['Referer']: |
|
|
126 |
nextpage = self.request.headers['Referer'] |
|
|
127 |
else: |
|
|
128 |
nextpage = "%s/" % qiita_config.portal_dir |
|
|
129 |
|
|
|
130 |
msg = "" |
|
|
131 |
# check the user level |
|
|
132 |
try: |
|
|
133 |
if User(username).level == "unverified": |
|
|
134 |
# email not verified so dont log in |
|
|
135 |
msg = ("Email not verified. Please check your email and click " |
|
|
136 |
"the verify link. You may need to check your spam " |
|
|
137 |
"folder to find the email.<br/>If a verification email" |
|
|
138 |
" has not arrived in 15 minutes, please email <a href='" |
|
|
139 |
"mailto:%s'>%s</a>") % (qiita_config.help_email, |
|
|
140 |
qiita_config.help_email) |
|
|
141 |
except QiitaDBUnknownIDError: |
|
|
142 |
msg = "Unknown user" |
|
|
143 |
except RuntimeError: |
|
|
144 |
# means DB not available, so set maintenance mode and failover |
|
|
145 |
r_client.set("maintenance", "Database connection unavailable, " |
|
|
146 |
"please try again later.") |
|
|
147 |
self.redirect("%s/" % qiita_config.portal_dir) |
|
|
148 |
return |
|
|
149 |
|
|
|
150 |
# Check the login information |
|
|
151 |
login = None |
|
|
152 |
try: |
|
|
153 |
login = User.login(username, passwd) |
|
|
154 |
except IncorrectEmailError: |
|
|
155 |
msg = "Unknown user" |
|
|
156 |
except IncorrectPasswordError: |
|
|
157 |
msg = "Incorrect password" |
|
|
158 |
except UnverifiedEmailError: |
|
|
159 |
msg = "You have not verified your email address" |
|
|
160 |
|
|
|
161 |
if login: |
|
|
162 |
# everything good so log in |
|
|
163 |
self.set_current_user(username) |
|
|
164 |
self.redirect(nextpage) |
|
|
165 |
else: |
|
|
166 |
self.render("index.html", message=msg, level='danger') |
|
|
167 |
|
|
|
168 |
def set_current_user(self, user): |
|
|
169 |
if user: |
|
|
170 |
self.set_secure_cookie("user", json_encode(user)) |
|
|
171 |
else: |
|
|
172 |
self.clear_cookie("user") |
|
|
173 |
|
|
|
174 |
|
|
|
175 |
class AuthLogoutHandler(BaseHandler): |
|
|
176 |
"""Logout handler, no page necessary""" |
|
|
177 |
def get(self): |
|
|
178 |
self.clear_cookie("user") |
|
|
179 |
self.redirect("%s/" % qiita_config.portal_dir) |