]> git.ipfire.org Git - ipfire.org.git/blob - src/web/base.py
wiki: Fix rendering image detail pages
[ipfire.org.git] / src / web / base.py
1 #!/usr/bin/python
2
3 import datetime
4 import dateutil.parser
5 import functools
6 import http.client
7 import ipaddress
8 import logging
9 import time
10 import tornado.locale
11 import tornado.web
12
13 from ..decorators import *
14 from .. import util
15
16 def blacklisted(method):
17 @tornado.gen.coroutine
18 @functools.wraps(method)
19 def wrapper(self, *args, **kwargs):
20 # Check if remote is blacklisted
21 is_blacklisted = yield self.remote.is_blacklisted()
22
23 # If so, redirect to the blocked page
24 if is_blacklisted:
25 logging.warning("%s is blacklisted" % self.remote)
26
27 return self.redirect("https://www.ipfire.org/blocked")
28
29 return method(self, *args, **kwargs)
30
31 return wrapper
32
33
34 class BaseHandler(tornado.web.RequestHandler):
35 def set_expires(self, seconds):
36 # For HTTP/1.1
37 self.add_header("Cache-Control", "max-age=%s, must-revalidate" % seconds)
38
39 # For HTTP/1.0
40 expires = datetime.datetime.utcnow() + datetime.timedelta(seconds=seconds)
41 self.add_header("Expires", expires)
42
43 def write_error(self, status_code, **kwargs):
44 # Translate code into message
45 try:
46 message = http.client.responses[status_code]
47 except KeyError:
48 message = None
49
50 self.render("error.html", status_code=status_code, message=message, **kwargs)
51
52 def xsrf_form_html(self, *args, **kwargs):
53 # Set Vary: Cookie header
54 self.add_header("Vary", "Cookie")
55
56 return super().xsrf_form_html(*args, **kwargs)
57
58 @property
59 def hostname(self):
60 # Remove the development prefix
61 return self.request.host.replace(".dev.", ".")
62
63 def get_template_namespace(self):
64 ns = tornado.web.RequestHandler.get_template_namespace(self)
65
66 now = datetime.date.today()
67
68 ns.update({
69 "backend" : self.backend,
70 "debug" : self.application.settings.get("debug", False),
71 "format_size" : util.format_size,
72 "format_time" : util.format_time,
73 "hostname" : self.hostname,
74 "now" : now,
75 "year" : now.year,
76 })
77
78 return ns
79
80 def get_remote_ip(self):
81 # Fix for clients behind a proxy that sends "X-Forwarded-For".
82 remote_ips = self.request.remote_ip.split(", ")
83
84 for remote_ip in remote_ips:
85 try:
86 addr = ipaddress.ip_address(remote_ip)
87 except ValueError:
88 # Skip invalid IP addresses.
89 continue
90
91 # Check if the given IP address is from a
92 # private network.
93 if addr.is_private:
94 continue
95
96 return remote_ip
97
98 # Return the last IP if nothing else worked
99 return remote_ips.pop()
100
101 @lazy_property
102 def remote(self):
103 address = self.get_remote_ip()
104
105 if address:
106 return self.backend.geoip.lookup(address)
107
108 @lazy_property
109 def current_country_code(self):
110 remote_ip = self.get_remote_ip()
111
112 if remote_ip:
113 return self.backend.geoip.get_country(remote_ip)
114
115 def get_remote_location(self):
116 if not hasattr(self, "__remote_location"):
117 remote_ip = self.get_remote_ip()
118
119 self.__remote_location = self.geoip.get_location(remote_ip)
120
121 return self.__remote_location
122
123 def get_argument_int(self, *args, **kwargs):
124 arg = self.get_argument(*args, **kwargs)
125
126 if arg is None or arg == "":
127 return
128
129 try:
130 return int(arg)
131 except ValueError:
132 raise tornado.web.HTTPError(400)
133
134 def get_argument_date(self, arg, *args, **kwargs):
135 value = self.get_argument(arg, *args, **kwargs)
136 if value is None:
137 return
138
139 try:
140 return dateutil.parser.parse(value)
141 except ValueError:
142 raise tornado.web.HTTPError(400)
143
144 def get_file(self, name):
145 try:
146 file = self.request.files[name][0]
147
148 return file["filename"], file["body"], file["content_type"]
149 except KeyError:
150 return None
151
152 # Login stuff
153
154 def get_current_user(self):
155 session_id = self.get_cookie("session_id")
156 if not session_id:
157 return
158
159 # Get account from the session object
160 account = self.backend.accounts.get_by_session(session_id, self.request.host)
161
162 # If the account was not found or the session was not valid
163 # any more, we will remove the cookie.
164 if not account:
165 self.clear_cookie("session_id")
166
167 return account
168
169 @property
170 def backend(self):
171 return self.application.backend
172
173 @property
174 def db(self):
175 return self.backend.db
176
177 @property
178 def accounts(self):
179 return self.backend.accounts
180
181 @property
182 def downloads(self):
183 return self.backend.downloads
184
185 @property
186 def fireinfo(self):
187 return self.backend.fireinfo
188
189 @property
190 def iuse(self):
191 return self.backend.iuse
192
193 @property
194 def memcached(self):
195 return self.backend.memcache
196
197 @property
198 def mirrors(self):
199 return self.backend.mirrors
200
201 @property
202 def netboot(self):
203 return self.backend.netboot
204
205 @property
206 def releases(self):
207 return self.backend.releases
208
209 @property
210 def geoip(self):
211 return self.backend.geoip
212
213 @property
214 def talk(self):
215 return self.backend.talk
216
217
218 class NotFoundHandler(BaseHandler):
219 def prepare(self):
220 # Raises 404 as soon as it is called
221 raise tornado.web.HTTPError(404)
222
223
224 class ErrorHandler(BaseHandler):
225 """
226 Raises any error we want
227 """
228 def get(self, code):
229 try:
230 code = int(code)
231 except:
232 raise tornado.web.HTTPError(400)
233
234 raise tornado.web.HTTPError(code)
235
236
237 class BlockedHandler(BaseHandler):
238 def get(self):
239 # 403 - Forbidden
240 self.set_status(403)
241
242 self.render("static/blocked.html", address=self.get_remote_ip())