]> git.ipfire.org Git - ipfire.org.git/blame - src/web/base.py
wiki: Add a page that helps users editing pages
[ipfire.org.git] / src / web / base.py
CommitLineData
940227cb
MT
1#!/usr/bin/python
2
cc3b928d 3import datetime
66862195 4import dateutil.parser
cfe7d74c 5import functools
11347e46 6import http.client
a69e87a1 7import ipaddress
47ed77ed 8import logging
940227cb
MT
9import time
10import tornado.locale
11import tornado.web
12
f110a9ff 13from ..decorators import *
a95c2f97 14from .. import util
60024cc8 15
cfe7d74c
MT
16def 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
940227cb 34class BaseHandler(tornado.web.RequestHandler):
f6ed3d4d
MT
35 def set_expires(self, seconds):
36 # For HTTP/1.1
b592d7c8 37 self.add_header("Cache-Control", "max-age=%s, must-revalidate" % seconds)
f6ed3d4d
MT
38
39 # For HTTP/1.0
40 expires = datetime.datetime.utcnow() + datetime.timedelta(seconds=seconds)
b592d7c8 41 self.add_header("Expires", expires)
f6ed3d4d 42
37ed7c3c
MT
43 def write_error(self, status_code, **kwargs):
44 # Translate code into message
45 try:
11347e46 46 message = http.client.responses[status_code]
37ed7c3c
MT
47 except KeyError:
48 message = None
49
50 self.render("error.html", status_code=status_code, message=message, **kwargs)
51
d3d02231
MT
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
4ca1a601
MT
58 @property
59 def hostname(self):
60 # Remove the development prefix
61 return self.request.host.replace(".dev.", ".")
62
bff08cb0
MT
63 def get_template_namespace(self):
64 ns = tornado.web.RequestHandler.get_template_namespace(self)
65
911064cf 66 now = datetime.date.today()
cc3b928d 67
bff08cb0 68 ns.update({
6c13ca2d 69 "backend" : self.backend,
5613b94b 70 "debug" : self.application.settings.get("debug", False),
a95c2f97
MT
71 "format_size" : util.format_size,
72 "format_time" : util.format_time,
4ca1a601 73 "hostname" : self.hostname,
911064cf
MT
74 "now" : now,
75 "year" : now.year,
bff08cb0 76 })
940227cb 77
bff08cb0 78 return ns
940227cb 79
9068dba1
MT
80 def get_remote_ip(self):
81 # Fix for clients behind a proxy that sends "X-Forwarded-For".
66862195 82 remote_ips = self.request.remote_ip.split(", ")
494d80e6 83
66862195
MT
84 for remote_ip in remote_ips:
85 try:
a69e87a1 86 addr = ipaddress.ip_address(remote_ip)
66862195
MT
87 except ValueError:
88 # Skip invalid IP addresses.
89 continue
9068dba1 90
66862195
MT
91 # Check if the given IP address is from a
92 # private network.
93 if addr.is_private:
94 continue
9068dba1 95
66862195 96 return remote_ip
9068dba1 97
494d80e6
MT
98 # Return the last IP if nothing else worked
99 return remote_ips.pop()
100
cfe7d74c
MT
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
f110a9ff
MT
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
9068dba1
MT
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
bd2723d4
MT
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
66862195
MT
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
5cc10421
MT
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
66862195
MT
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
a6dc0bad
MT
169 @property
170 def backend(self):
171 return self.application.backend
172
9068dba1
MT
173 @property
174 def db(self):
175 return self.backend.db
176
940227cb
MT
177 @property
178 def accounts(self):
a6dc0bad 179 return self.backend.accounts
940227cb
MT
180
181 @property
9068dba1
MT
182 def downloads(self):
183 return self.backend.downloads
184
66862195
MT
185 @property
186 def fireinfo(self):
187 return self.backend.fireinfo
188
9068dba1
MT
189 @property
190 def iuse(self):
191 return self.backend.iuse
940227cb
MT
192
193 @property
194 def mirrors(self):
9068dba1
MT
195 return self.backend.mirrors
196
197 @property
198 def netboot(self):
199 return self.backend.netboot
940227cb 200
940227cb
MT
201 @property
202 def releases(self):
9068dba1 203 return self.backend.releases
940227cb
MT
204
205 @property
9068dba1
MT
206 def geoip(self):
207 return self.backend.geoip
940227cb
MT
208
209 @property
66862195
MT
210 def talk(self):
211 return self.backend.talk
940227cb 212
66862195 213
3403dc5e
MT
214class NotFoundHandler(BaseHandler):
215 def prepare(self):
216 # Raises 404 as soon as it is called
217 raise tornado.web.HTTPError(404)
218
3403dc5e 219
37ed7c3c
MT
220class ErrorHandler(BaseHandler):
221 """
222 Raises any error we want
223 """
224 def get(self, code):
225 try:
226 code = int(code)
227 except:
228 raise tornado.web.HTTPError(400)
229
230 raise tornado.web.HTTPError(code)
baa693a3
MT
231
232
233class BlockedHandler(BaseHandler):
234 def get(self):
235 # 403 - Forbidden
236 self.set_status(403)
237
238 self.render("static/blocked.html", address=self.get_remote_ip())