]>
Commit | Line | Data |
---|---|---|
08df6527 MT |
1 | #!/usr/bin/python |
2 | ||
3 | import logging | |
4 | import tornado.web | |
5 | ||
124a8404 | 6 | from . import base |
08df6527 | 7 | |
170b63ba MT |
8 | class CacheMixin(object): |
9 | def prepare(self): | |
10 | # Mark this as private when someone is logged in | |
11 | if self.current_user: | |
12 | self.add_header("Cache-Control", "private") | |
13 | ||
14 | self.add_header("Vary", "Cookie") | |
15 | ||
16 | ||
17 | class AuthenticationMixin(CacheMixin): | |
d8a15b2e | 18 | def authenticate(self, username, password): |
08df6527 MT |
19 | # Find account |
20 | account = self.backend.accounts.find_account(username) | |
21 | if not account: | |
22 | raise tornado.web.HTTPError(401, "Unknown user: %s" % username) | |
23 | ||
24 | # Check credentials | |
25 | if not account.check_password(password): | |
26 | raise tornado.web.HTTPError(401, "Invalid password for %s" % account) | |
27 | ||
d8a15b2e MT |
28 | return self.login(account) |
29 | ||
30 | def login(self, account): | |
08df6527 | 31 | # User has logged in, create a session |
906e1e6a MT |
32 | session_id, session_expires = self.backend.accounts.create_session( |
33 | account, self.request.host) | |
08df6527 MT |
34 | |
35 | # Check if a new session was created | |
36 | if not session_id: | |
37 | raise tornado.web.HTTPError(500, "Could not create session") | |
38 | ||
39 | # Send session cookie to the client | |
40 | self.set_cookie("session_id", session_id, | |
41 | domain=self.request.host, expires=session_expires) | |
42 | ||
43 | def logout(self): | |
44 | session_id = self.get_cookie("session_id") | |
45 | if not session_id: | |
46 | return | |
47 | ||
906e1e6a | 48 | success = self.backend.accounts.destroy_session(session_id, self.request.host) |
08df6527 MT |
49 | if success: |
50 | self.clear_cookie("session_id") | |
51 | ||
52 | ||
08df6527 | 53 | class LoginHandler(AuthenticationMixin, base.BaseHandler): |
cfe7d74c | 54 | @base.blacklisted |
08df6527 MT |
55 | def get(self): |
56 | next = self.get_argument("next", None) | |
57 | ||
58 | self.render("auth/login.html", next=next) | |
59 | ||
cfe7d74c | 60 | @base.blacklisted |
372ef119 | 61 | @base.ratelimit(minutes=60, requests=5) |
08df6527 MT |
62 | def post(self): |
63 | username = self.get_argument("username") | |
64 | password = self.get_argument("password") | |
65 | ||
66 | with self.db.transaction(): | |
d8a15b2e | 67 | self.authenticate(username, password) |
08df6527 MT |
68 | |
69 | # Determine the page we should redirect to | |
70 | next = self.get_argument("next", None) | |
71 | ||
72 | return self.redirect(next or "/") | |
73 | ||
74 | ||
75 | class LogoutHandler(AuthenticationMixin, base.BaseHandler): | |
76 | def get(self): | |
77 | with self.db.transaction(): | |
78 | self.logout() | |
79 | ||
80 | # Get back to the start page | |
81 | self.redirect("/") | |
9b8ff27d MT |
82 | |
83 | ||
f32dd17f MT |
84 | class RegisterHandler(base.BaseHandler): |
85 | @base.blacklisted | |
86 | def get(self): | |
d521c9df MT |
87 | # Redirect logged in users away |
88 | if self.current_user: | |
89 | self.redirect("/") | |
90 | ||
f32dd17f MT |
91 | self.render("auth/register.html") |
92 | ||
23f84bbc | 93 | @tornado.gen.coroutine |
372ef119 | 94 | @base.ratelimit(minutes=24*60, requests=5) |
f32dd17f MT |
95 | def post(self): |
96 | uid = self.get_argument("uid") | |
97 | email = self.get_argument("email") | |
98 | ||
99 | first_name = self.get_argument("first_name") | |
100 | last_name = self.get_argument("last_name") | |
101 | ||
23f84bbc MT |
102 | # Check if this is a spam account |
103 | is_spam = yield self.backend.accounts.check_spam(uid, email, | |
104 | address=self.get_remote_ip()) | |
105 | ||
106 | if is_spam: | |
107 | self.render("auth/register-spam.html") | |
108 | return | |
109 | ||
f32dd17f | 110 | # Register account |
f2ba8a1f MT |
111 | try: |
112 | with self.db.transaction(): | |
113 | self.backend.accounts.register(uid, email, | |
114 | first_name=first_name, last_name=last_name) | |
115 | except ValueError as e: | |
09c67399 | 116 | raise tornado.web.HTTPError(400, "%s" % e) from e |
f32dd17f MT |
117 | |
118 | self.render("auth/register-success.html") | |
119 | ||
120 | ||
d8a15b2e MT |
121 | class ActivateHandler(AuthenticationMixin, base.BaseHandler): |
122 | def get(self, uid, activation_code): | |
b4d72c76 | 123 | self.render("auth/activate.html") |
d8a15b2e MT |
124 | |
125 | def post(self, uid, activation_code): | |
b4d72c76 MT |
126 | password1 = self.get_argument("password1") |
127 | password2 = self.get_argument("password2") | |
d8a15b2e | 128 | |
b4d72c76 MT |
129 | if not password1 == password2: |
130 | raise tornado.web.HTTPError(400, "Passwords do not match") | |
d8a15b2e | 131 | |
b4d72c76 MT |
132 | with self.db.transaction(): |
133 | account = self.backend.accounts.activate(uid, activation_code) | |
134 | if not account: | |
135 | raise tornado.web.HTTPError(400, "Account not found: %s" % uid) | |
d8a15b2e | 136 | |
b4d72c76 MT |
137 | # Set the new password |
138 | account.passwd(password1) | |
d8a15b2e | 139 | |
b4d72c76 MT |
140 | # Create session |
141 | self.login(account) | |
d8a15b2e | 142 | |
b00cc400 MT |
143 | # Redirect to success page |
144 | self.render("auth/activated.html", account=account) |