]>
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 | |
940227cb MT |
9 | import time |
10 | import tornado.locale | |
11 | import tornado.web | |
12 | ||
66862195 | 13 | import backend.util |
60024cc8 | 14 | |
940227cb | 15 | class BaseHandler(tornado.web.RequestHandler): |
de683d7c MT |
16 | rss_url = None |
17 | ||
940227cb MT |
18 | def get_account(self, uid): |
19 | # Find the name of the author | |
20 | return self.accounts.find(uid) | |
21 | ||
60024cc8 | 22 | def get_user_locale(self): |
45c763aa MT |
23 | # The planet is always in english. |
24 | if self.request.host == "planet.ipfire.org": | |
dbf95cf2 | 25 | return tornado.locale.get("en_US") |
45c763aa | 26 | |
dbf95cf2 MT |
27 | # Otherwise take the browser locale. |
28 | return self.get_browser_locale() | |
940227cb MT |
29 | |
30 | @property | |
31 | def render_args(self): | |
cc3b928d MT |
32 | today = datetime.date.today() |
33 | ||
66862195 MT |
34 | # Get the requested host and remove the development prefix |
35 | hostname = self.request.host.replace(".dev.", ".") | |
36 | ||
940227cb | 37 | return { |
66862195 MT |
38 | "format_size" : backend.util.format_size, |
39 | "format_time" : backend.util.format_time, | |
40 | "hostname" : hostname, | |
940227cb | 41 | "lang" : self.locale.code[:2], |
de683d7c | 42 | "rss_url" : self.rss_url, |
cc3b928d | 43 | "year" : today.year, |
940227cb MT |
44 | } |
45 | ||
bcc3ed4d MT |
46 | def render(self, *args, **_kwargs): |
47 | kwargs = self.render_args | |
48 | kwargs.update(_kwargs) | |
940227cb MT |
49 | tornado.web.RequestHandler.render(self, *args, **kwargs) |
50 | ||
bcc3ed4d MT |
51 | def render_string(self, *args, **_kwargs): |
52 | kwargs = self.render_args | |
53 | kwargs.update(_kwargs) | |
940227cb MT |
54 | return tornado.web.RequestHandler.render_string(self, *args, **kwargs) |
55 | ||
02f2d7fe | 56 | def write_error(self, status_code, **kwargs): |
940227cb MT |
57 | if status_code in (404, 500): |
58 | render_args = ({ | |
59 | "code" : status_code, | |
60 | "exception" : kwargs.get("exception", None), | |
61 | "message" : httplib.responses[status_code], | |
62 | }) | |
02f2d7fe | 63 | self.render("error-%s.html" % status_code, **render_args) |
940227cb | 64 | else: |
02f2d7fe | 65 | return tornado.web.RequestHandler.write_error(self, status_code, **kwargs) |
940227cb | 66 | |
3d540c40 MT |
67 | def static_url(self, path, static=True): |
68 | ret = tornado.web.RequestHandler.static_url(self, path) | |
69 | ||
1de8dd23 MT |
70 | if self.settings.get("debug", False): |
71 | return ret | |
72 | ||
73 | elif self.request.host == "admin.ipfire.org": | |
74 | return ret | |
75 | ||
76 | elif static: | |
77 | return "http://static.ipfire.org%s" % ret | |
3d540c40 MT |
78 | |
79 | return ret | |
80 | ||
9068dba1 MT |
81 | def get_remote_ip(self): |
82 | # Fix for clients behind a proxy that sends "X-Forwarded-For". | |
66862195 MT |
83 | remote_ips = self.request.remote_ip.split(", ") |
84 | for remote_ip in remote_ips: | |
85 | try: | |
86 | addr = ipaddr.IPAddress(remote_ip) | |
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 MT |
97 | |
98 | def get_remote_location(self): | |
99 | if not hasattr(self, "__remote_location"): | |
100 | remote_ip = self.get_remote_ip() | |
101 | ||
102 | self.__remote_location = self.geoip.get_location(remote_ip) | |
103 | ||
104 | return self.__remote_location | |
105 | ||
66862195 MT |
106 | def get_argument_date(self, arg, *args, **kwargs): |
107 | value = self.get_argument(arg, *args, **kwargs) | |
108 | if value is None: | |
109 | return | |
110 | ||
111 | try: | |
112 | return dateutil.parser.parse(value) | |
113 | except ValueError: | |
114 | raise tornado.web.HTTPError(400) | |
115 | ||
116 | # Login stuff | |
117 | ||
118 | def get_current_user(self): | |
119 | session_id = self.get_cookie("session_id") | |
120 | if not session_id: | |
121 | return | |
122 | ||
123 | # Get account from the session object | |
124 | account = self.backend.accounts.get_by_session(session_id, self.request.host) | |
125 | ||
126 | # If the account was not found or the session was not valid | |
127 | # any more, we will remove the cookie. | |
128 | if not account: | |
129 | self.clear_cookie("session_id") | |
130 | ||
131 | return account | |
132 | ||
133 | def login(self, username, password): | |
134 | # Find account | |
135 | account = self.backend.accounts.find_account(username) | |
136 | if not account: | |
137 | logging.warning(401, "unknown account: %s" % username) | |
138 | return False | |
139 | ||
140 | # Check credentials | |
141 | if not account.check_password(password): | |
142 | logging.warning("invalid password for %s" % account) | |
143 | return False | |
144 | ||
145 | # User has logged in, create a session | |
146 | session_id, session_expires = self.backend.accounts.create_session(account, | |
147 | self.request.host) | |
148 | ||
149 | # Check if a new session was created | |
150 | if not session_id: | |
151 | logging.warning("Could not create session") | |
152 | return False | |
153 | ||
154 | # Send session cookie to the client | |
155 | self.set_cookie("session_id", session_id, | |
156 | domain=self.request.host, expires=session_expires) | |
157 | ||
158 | return True | |
159 | ||
160 | def logout(self): | |
161 | session_id = self.get_cookie("session_id") | |
162 | ||
163 | if not session_id: | |
164 | return | |
165 | ||
166 | success = self.backend.accounts.destroy_session(session_id, self.request.host) | |
167 | if success: | |
168 | self.clear_cookie("session_id") | |
169 | ||
a6dc0bad MT |
170 | @property |
171 | def backend(self): | |
172 | return self.application.backend | |
173 | ||
9068dba1 MT |
174 | @property |
175 | def db(self): | |
176 | return self.backend.db | |
177 | ||
a0048e66 MT |
178 | @property |
179 | def advertisements(self): | |
9068dba1 | 180 | return self.backend.advertisements |
a0048e66 | 181 | |
940227cb MT |
182 | @property |
183 | def accounts(self): | |
a6dc0bad | 184 | return self.backend.accounts |
940227cb MT |
185 | |
186 | @property | |
9068dba1 MT |
187 | def downloads(self): |
188 | return self.backend.downloads | |
189 | ||
66862195 MT |
190 | @property |
191 | def fireinfo(self): | |
192 | return self.backend.fireinfo | |
193 | ||
9068dba1 MT |
194 | @property |
195 | def iuse(self): | |
196 | return self.backend.iuse | |
940227cb | 197 | |
b3250465 MT |
198 | @property |
199 | def memcached(self): | |
9068dba1 | 200 | return self.backend.memcache |
b3250465 | 201 | |
940227cb MT |
202 | @property |
203 | def mirrors(self): | |
9068dba1 MT |
204 | return self.backend.mirrors |
205 | ||
206 | @property | |
207 | def netboot(self): | |
208 | return self.backend.netboot | |
940227cb MT |
209 | |
210 | @property | |
211 | def news(self): | |
9068dba1 | 212 | return self.backend.news |
940227cb MT |
213 | |
214 | @property | |
215 | def config(self): | |
9068dba1 | 216 | return self.backend.settings |
940227cb MT |
217 | |
218 | @property | |
219 | def releases(self): | |
9068dba1 | 220 | return self.backend.releases |
940227cb MT |
221 | |
222 | @property | |
9068dba1 MT |
223 | def geoip(self): |
224 | return self.backend.geoip | |
940227cb MT |
225 | |
226 | @property | |
66862195 MT |
227 | def talk(self): |
228 | return self.backend.talk | |
940227cb MT |
229 | |
230 | @property | |
231 | def tracker(self): | |
9068dba1 | 232 | return self.backend.tracker |
bcc3ed4d MT |
233 | |
234 | @property | |
235 | def planet(self): | |
a6dc0bad | 236 | return self.backend.planet |
7771acea MT |
237 | |
238 | @property | |
239 | def wishlist(self): | |
9068dba1 | 240 | return self.backend.wishlist |
66862195 MT |
241 | |
242 | ||
243 | class LoginHandler(BaseHandler): | |
244 | def get(self): | |
245 | self.render("auth/login.html") | |
246 | ||
247 | def post(self): | |
248 | username = self.get_argument("username") | |
249 | password = self.get_argument("password") | |
250 | ||
251 | if not self.login(username, password): | |
252 | raise tornado.web.HTTPError(401) | |
253 | ||
254 | next = self.get_argument("next", "/") | |
255 | return self.redirect(next) | |
256 | ||
257 | ||
258 | class LogoutHandler(BaseHandler): | |
259 | def get(self): | |
260 | self.logout() | |
261 | ||
262 | # Get back to the start page | |
263 | self.redirect("/") |