]>
Commit | Line | Data |
---|---|---|
940227cb MT |
1 | #!/usr/bin/python |
2 | ||
60024cc8 MT |
3 | from __future__ import division |
4 | ||
cc3b928d | 5 | import datetime |
66862195 MT |
6 | import dateutil.parser |
7 | import httplib | |
8 | import ipaddr | |
47ed77ed | 9 | import logging |
940227cb MT |
10 | import time |
11 | import tornado.locale | |
12 | import tornado.web | |
13 | ||
a95c2f97 | 14 | from .. import util |
60024cc8 | 15 | |
940227cb | 16 | class BaseHandler(tornado.web.RequestHandler): |
de683d7c MT |
17 | rss_url = None |
18 | ||
940227cb MT |
19 | def get_account(self, uid): |
20 | # Find the name of the author | |
21 | return self.accounts.find(uid) | |
22 | ||
4ca1a601 MT |
23 | @property |
24 | def hostname(self): | |
25 | # Remove the development prefix | |
26 | return self.request.host.replace(".dev.", ".") | |
27 | ||
47d47c2e MT |
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 | ||
940227cb MT |
35 | @property |
36 | def render_args(self): | |
cc3b928d MT |
37 | today = datetime.date.today() |
38 | ||
47d47c2e | 39 | ret = { |
a95c2f97 MT |
40 | "format_size" : util.format_size, |
41 | "format_time" : util.format_time, | |
4ca1a601 | 42 | "hostname" : self.hostname, |
de683d7c | 43 | "rss_url" : self.rss_url, |
cc3b928d | 44 | "year" : today.year, |
940227cb | 45 | } |
47d47c2e MT |
46 | ret.update(self.ssl_params) |
47 | ||
48 | return ret | |
940227cb | 49 | |
bcc3ed4d MT |
50 | def render(self, *args, **_kwargs): |
51 | kwargs = self.render_args | |
52 | kwargs.update(_kwargs) | |
940227cb MT |
53 | tornado.web.RequestHandler.render(self, *args, **kwargs) |
54 | ||
bcc3ed4d MT |
55 | def render_string(self, *args, **_kwargs): |
56 | kwargs = self.render_args | |
57 | kwargs.update(_kwargs) | |
940227cb MT |
58 | return tornado.web.RequestHandler.render_string(self, *args, **kwargs) |
59 | ||
9068dba1 MT |
60 | def get_remote_ip(self): |
61 | # Fix for clients behind a proxy that sends "X-Forwarded-For". | |
66862195 | 62 | remote_ips = self.request.remote_ip.split(", ") |
494d80e6 | 63 | |
66862195 MT |
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 | |
9068dba1 | 70 | |
66862195 MT |
71 | # Check if the given IP address is from a |
72 | # private network. | |
73 | if addr.is_private: | |
74 | continue | |
9068dba1 | 75 | |
66862195 | 76 | return remote_ip |
9068dba1 | 77 | |
494d80e6 MT |
78 | # Return the last IP if nothing else worked |
79 | return remote_ips.pop() | |
80 | ||
9068dba1 MT |
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 | ||
66862195 MT |
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 | ||
a6dc0bad MT |
153 | @property |
154 | def backend(self): | |
155 | return self.application.backend | |
156 | ||
9068dba1 MT |
157 | @property |
158 | def db(self): | |
159 | return self.backend.db | |
160 | ||
a0048e66 MT |
161 | @property |
162 | def advertisements(self): | |
9068dba1 | 163 | return self.backend.advertisements |
a0048e66 | 164 | |
940227cb MT |
165 | @property |
166 | def accounts(self): | |
a6dc0bad | 167 | return self.backend.accounts |
940227cb MT |
168 | |
169 | @property | |
9068dba1 MT |
170 | def downloads(self): |
171 | return self.backend.downloads | |
172 | ||
66862195 MT |
173 | @property |
174 | def fireinfo(self): | |
175 | return self.backend.fireinfo | |
176 | ||
9068dba1 MT |
177 | @property |
178 | def iuse(self): | |
179 | return self.backend.iuse | |
940227cb | 180 | |
b3250465 MT |
181 | @property |
182 | def memcached(self): | |
9068dba1 | 183 | return self.backend.memcache |
b3250465 | 184 | |
940227cb MT |
185 | @property |
186 | def mirrors(self): | |
9068dba1 MT |
187 | return self.backend.mirrors |
188 | ||
189 | @property | |
190 | def netboot(self): | |
191 | return self.backend.netboot | |
940227cb MT |
192 | |
193 | @property | |
194 | def news(self): | |
9068dba1 | 195 | return self.backend.news |
940227cb MT |
196 | |
197 | @property | |
198 | def config(self): | |
9068dba1 | 199 | return self.backend.settings |
940227cb MT |
200 | |
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 MT |
212 | |
213 | @property | |
214 | def tracker(self): | |
9068dba1 | 215 | return self.backend.tracker |
bcc3ed4d | 216 | |
66862195 MT |
217 | |
218 | class LoginHandler(BaseHandler): | |
219 | def get(self): | |
220 | self.render("auth/login.html") | |
221 | ||
222 | def post(self): | |
223 | username = self.get_argument("username") | |
224 | password = self.get_argument("password") | |
225 | ||
226 | if not self.login(username, password): | |
227 | raise tornado.web.HTTPError(401) | |
228 | ||
229 | next = self.get_argument("next", "/") | |
230 | return self.redirect(next) | |
231 | ||
232 | ||
233 | class LogoutHandler(BaseHandler): | |
234 | def get(self): | |
235 | self.logout() | |
236 | ||
237 | # Get back to the start page | |
238 | self.redirect("/") | |
3403dc5e MT |
239 | |
240 | ||
241 | class NotFoundHandler(BaseHandler): | |
242 | def prepare(self): | |
243 | # Raises 404 as soon as it is called | |
244 | raise tornado.web.HTTPError(404) | |
245 | ||
246 | def write_error(self, status_code, **kwargs): | |
247 | assert status_code == 404 | |
248 | ||
249 | self.render("error-404.html") |