]> git.ipfire.org Git - ipfire.org.git/blob - src/web/base.py
xsrf_form_html: Set Vary: Cookie header
[ipfire.org.git] / src / web / base.py
1 #!/usr/bin/python
2
3 import datetime
4 import dateutil.parser
5 import http.client
6 import ipaddress
7 import logging
8 import time
9 import tornado.locale
10 import tornado.web
11
12 from ..decorators import *
13 from .. import util
14
15 class BaseHandler(tornado.web.RequestHandler):
16 def set_expires(self, seconds):
17 # For HTTP/1.1
18 self.add_header("Cache-Control", "max-age=%s, must-revalidate" % seconds)
19
20 # For HTTP/1.0
21 expires = datetime.datetime.utcnow() + datetime.timedelta(seconds=seconds)
22 self.add_header("Expires", expires)
23
24 def write_error(self, status_code, **kwargs):
25 # Translate code into message
26 try:
27 message = http.client.responses[status_code]
28 except KeyError:
29 message = None
30
31 self.render("error.html", status_code=status_code, message=message, **kwargs)
32
33 def xsrf_form_html(self, *args, **kwargs):
34 # Set Vary: Cookie header
35 self.add_header("Vary", "Cookie")
36
37 return super().xsrf_form_html(*args, **kwargs)
38
39 @property
40 def hostname(self):
41 # Remove the development prefix
42 return self.request.host.replace(".dev.", ".")
43
44 def get_template_namespace(self):
45 ns = tornado.web.RequestHandler.get_template_namespace(self)
46
47 now = datetime.date.today()
48
49 ns.update({
50 "debug" : self.application.settings.get("debug", False),
51 "format_size" : util.format_size,
52 "format_time" : util.format_time,
53 "hostname" : self.hostname,
54 "now" : now,
55 "year" : now.year,
56 })
57
58 return ns
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 = ipaddress.ip_address(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 @lazy_property
82 def current_country_code(self):
83 remote_ip = self.get_remote_ip()
84
85 if remote_ip:
86 return self.backend.geoip.get_country(remote_ip)
87
88 def get_remote_location(self):
89 if not hasattr(self, "__remote_location"):
90 remote_ip = self.get_remote_ip()
91
92 self.__remote_location = self.geoip.get_location(remote_ip)
93
94 return self.__remote_location
95
96 def get_argument_int(self, *args, **kwargs):
97 arg = self.get_argument(*args, **kwargs)
98
99 if arg is None or arg == "":
100 return
101
102 try:
103 return int(arg)
104 except ValueError:
105 raise tornado.web.HTTPError(400)
106
107 def get_argument_date(self, arg, *args, **kwargs):
108 value = self.get_argument(arg, *args, **kwargs)
109 if value is None:
110 return
111
112 try:
113 return dateutil.parser.parse(value)
114 except ValueError:
115 raise tornado.web.HTTPError(400)
116
117 def get_file(self, name):
118 try:
119 file = self.request.files[name][0]
120
121 return file["filename"], file["body"], file["content_type"]
122 except KeyError:
123 return None
124
125 # Login stuff
126
127 def get_current_user(self):
128 session_id = self.get_cookie("session_id")
129 if not session_id:
130 return
131
132 # Get account from the session object
133 account = self.backend.accounts.get_by_session(session_id, self.request.host)
134
135 # If the account was not found or the session was not valid
136 # any more, we will remove the cookie.
137 if not account:
138 self.clear_cookie("session_id")
139
140 return account
141
142 @property
143 def backend(self):
144 return self.application.backend
145
146 @property
147 def db(self):
148 return self.backend.db
149
150 @property
151 def accounts(self):
152 return self.backend.accounts
153
154 @property
155 def downloads(self):
156 return self.backend.downloads
157
158 @property
159 def fireinfo(self):
160 return self.backend.fireinfo
161
162 @property
163 def iuse(self):
164 return self.backend.iuse
165
166 @property
167 def mirrors(self):
168 return self.backend.mirrors
169
170 @property
171 def netboot(self):
172 return self.backend.netboot
173
174 @property
175 def releases(self):
176 return self.backend.releases
177
178 @property
179 def geoip(self):
180 return self.backend.geoip
181
182 @property
183 def talk(self):
184 return self.backend.talk
185
186
187 class NotFoundHandler(BaseHandler):
188 def prepare(self):
189 # Raises 404 as soon as it is called
190 raise tornado.web.HTTPError(404)
191
192
193 class ErrorHandler(BaseHandler):
194 """
195 Raises any error we want
196 """
197 def get(self, code):
198 try:
199 code = int(code)
200 except:
201 raise tornado.web.HTTPError(400)
202
203 raise tornado.web.HTTPError(code)
204
205
206 class BlockedHandler(BaseHandler):
207 def get(self):
208 # 403 - Forbidden
209 self.set_status(403)
210
211 self.render("static/blocked.html", address=self.get_remote_ip())