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