]> git.ipfire.org Git - ipfire.org.git/blob - src/web/handlers_base.py
web: Use a proper handler to render 404
[ipfire.org.git] / src / web / handlers_base.py
1 #!/usr/bin/python
2
3 from __future__ import division
4
5 import datetime
6 import dateutil.parser
7 import httplib
8 import ipaddr
9 import logging
10 import time
11 import tornado.locale
12 import tornado.web
13
14 from .. import util
15
16 class BaseHandler(tornado.web.RequestHandler):
17 rss_url = None
18
19 def get_account(self, uid):
20 # Find the name of the author
21 return self.accounts.find(uid)
22
23 @property
24 def hostname(self):
25 # Remove the development prefix
26 return self.request.host.replace(".dev.", ".")
27
28 @property
29 def ssl_params(self):
30 return {
31 "ssl_cipher" : self.request.headers.get("X-Https-Cipher", None),
32 "ssl_protocol" : self.request.headers.get("X-Https-Protocol", None),
33 }
34
35 @property
36 def render_args(self):
37 today = datetime.date.today()
38
39 ret = {
40 "format_size" : util.format_size,
41 "format_time" : util.format_time,
42 "hostname" : self.hostname,
43 "rss_url" : self.rss_url,
44 "year" : today.year,
45 }
46 ret.update(self.ssl_params)
47
48 return ret
49
50 def render(self, *args, **_kwargs):
51 kwargs = self.render_args
52 kwargs.update(_kwargs)
53 tornado.web.RequestHandler.render(self, *args, **kwargs)
54
55 def render_string(self, *args, **_kwargs):
56 kwargs = self.render_args
57 kwargs.update(_kwargs)
58 return tornado.web.RequestHandler.render_string(self, *args, **kwargs)
59
60 def get_remote_ip(self):
61 # Fix for clients behind a proxy that sends "X-Forwarded-For".
62 remote_ips = self.request.remote_ip.split(", ")
63
64 for remote_ip in remote_ips:
65 try:
66 addr = ipaddr.IPAddress(remote_ip)
67 except ValueError:
68 # Skip invalid IP addresses.
69 continue
70
71 # Check if the given IP address is from a
72 # private network.
73 if addr.is_private:
74 continue
75
76 return remote_ip
77
78 # Return the last IP if nothing else worked
79 return remote_ips.pop()
80
81 def get_remote_location(self):
82 if not hasattr(self, "__remote_location"):
83 remote_ip = self.get_remote_ip()
84
85 self.__remote_location = self.geoip.get_location(remote_ip)
86
87 return self.__remote_location
88
89 def get_argument_date(self, arg, *args, **kwargs):
90 value = self.get_argument(arg, *args, **kwargs)
91 if value is None:
92 return
93
94 try:
95 return dateutil.parser.parse(value)
96 except ValueError:
97 raise tornado.web.HTTPError(400)
98
99 # Login stuff
100
101 def get_current_user(self):
102 session_id = self.get_cookie("session_id")
103 if not session_id:
104 return
105
106 # Get account from the session object
107 account = self.backend.accounts.get_by_session(session_id, self.request.host)
108
109 # If the account was not found or the session was not valid
110 # any more, we will remove the cookie.
111 if not account:
112 self.clear_cookie("session_id")
113
114 return account
115
116 def login(self, username, password):
117 # Find account
118 account = self.backend.accounts.find_account(username)
119 if not account:
120 logging.warning(401, "unknown account: %s" % username)
121 return False
122
123 # Check credentials
124 if not account.check_password(password):
125 logging.warning("invalid password for %s" % account)
126 return False
127
128 # User has logged in, create a session
129 session_id, session_expires = self.backend.accounts.create_session(account,
130 self.request.host)
131
132 # Check if a new session was created
133 if not session_id:
134 logging.warning("Could not create session")
135 return False
136
137 # Send session cookie to the client
138 self.set_cookie("session_id", session_id,
139 domain=self.request.host, expires=session_expires)
140
141 return True
142
143 def logout(self):
144 session_id = self.get_cookie("session_id")
145
146 if not session_id:
147 return
148
149 success = self.backend.accounts.destroy_session(session_id, self.request.host)
150 if success:
151 self.clear_cookie("session_id")
152
153 @property
154 def backend(self):
155 return self.application.backend
156
157 @property
158 def db(self):
159 return self.backend.db
160
161 @property
162 def advertisements(self):
163 return self.backend.advertisements
164
165 @property
166 def accounts(self):
167 return self.backend.accounts
168
169 @property
170 def downloads(self):
171 return self.backend.downloads
172
173 @property
174 def fireinfo(self):
175 return self.backend.fireinfo
176
177 @property
178 def iuse(self):
179 return self.backend.iuse
180
181 @property
182 def memcached(self):
183 return self.backend.memcache
184
185 @property
186 def mirrors(self):
187 return self.backend.mirrors
188
189 @property
190 def netboot(self):
191 return self.backend.netboot
192
193 @property
194 def news(self):
195 return self.backend.news
196
197 @property
198 def config(self):
199 return self.backend.settings
200
201 @property
202 def releases(self):
203 return self.backend.releases
204
205 @property
206 def geoip(self):
207 return self.backend.geoip
208
209 @property
210 def talk(self):
211 return self.backend.talk
212
213 @property
214 def tracker(self):
215 return self.backend.tracker
216
217 @property
218 def planet(self):
219 return self.backend.planet
220
221
222 class LoginHandler(BaseHandler):
223 def get(self):
224 self.render("auth/login.html")
225
226 def post(self):
227 username = self.get_argument("username")
228 password = self.get_argument("password")
229
230 if not self.login(username, password):
231 raise tornado.web.HTTPError(401)
232
233 next = self.get_argument("next", "/")
234 return self.redirect(next)
235
236
237 class LogoutHandler(BaseHandler):
238 def get(self):
239 self.logout()
240
241 # Get back to the start page
242 self.redirect("/")
243
244
245 class NotFoundHandler(BaseHandler):
246 def prepare(self):
247 # Raises 404 as soon as it is called
248 raise tornado.web.HTTPError(404)
249
250 def write_error(self, status_code, **kwargs):
251 assert status_code == 404
252
253 self.render("error-404.html")