]> git.ipfire.org Git - ipfire.org.git/blame - src/web/__init__.py
analytics: Record some page views
[ipfire.org.git] / src / web / __init__.py
CommitLineData
81675874 1#/usr/bin/python
2
feb02477 3import logging
81675874 4import os.path
c01ad253 5import phonenumbers
e96e445b 6import phonenumbers.geocoder
81675874 7import tornado.locale
a49b5422 8import tornado.options
81675874 9import tornado.web
10
a95c2f97 11import ipfire
574a88c7 12import ipfire.countries
440aba92 13from .. import util
feb02477 14
11347e46 15from .handlers import *
81675874 16
08df6527 17from . import auth
12e5de7e 18from . import blog
f301d952 19from . import boot
1958a22b 20from . import docs
c7bcb9ca 21from . import donate
aec63a26 22from . import downloads
96c9bb79 23from . import fireinfo
699a0911 24from . import iuse
97e15cf6 25from . import lists
f5b01fc2 26from . import location
a41085fb 27from . import nopaste
df6180a5 28from . import ui_modules
b01a1ee3 29from . import users
4235ba55 30from . import voip
12e5de7e 31
81675874 32class Application(tornado.web.Application):
3e7c6ccd
MT
33 def __init__(self, config, **kwargs):
34 # Initialize backend
a95c2f97 35 self.backend = ipfire.Backend(config)
a6dc0bad 36
9ed02e3b
MT
37 settings = {
38 # Do not compress responses
39 "gzip" : False,
40
41 # Enable XSRF cookies
42 "xsrf_cookies" : True,
43
44 # Login
45 "login_url" : "/login",
46
47 # Setup directory structure
48 "static_path" : self.backend.config.get("global", "static_dir"),
49 "template_path" : self.backend.config.get("global", "templates_dir"),
50
eabe6b8d 51 # UI Methods
9ed02e3b 52 "ui_methods" : {
574a88c7 53 "format_country_name" : self.format_country_name,
6eddfb50 54 "format_language_name" : self.format_language_name,
e96e445b
MT
55 "format_month_name" : self.format_month_name,
56 "format_phone_number" : self.format_phone_number,
57 "format_phone_number_to_e164" : self.format_phone_number_to_e164,
58 "format_phone_number_location" : self.format_phone_number_location,
cc3b928d 59 },
eabe6b8d
MT
60
61 # UI Modules
9ed02e3b 62 "ui_modules" : {
5806d6fc
MT
63 # Auth
64 "Password" : auth.PasswordModule,
65
f5b01fc2 66 # Blog
7e64f6a3
MT
67 "BlogHistoryNavigation": blog.HistoryNavigationModule,
68 "BlogList" : blog.ListModule,
f91dfcc7 69
93feb275
MT
70 # Boot
71 "BootMenuConfig" : boot.MenuConfigModule,
72 "BootMenuHeader" : boot.MenuHeaderModule,
73 "BootMenuSeparator" : boot.MenuSeparatorModule,
74
cf59466c 75 # Docs
739fff76 76 "DocsDiff" : docs.DiffModule,
cf59466c 77 "DocsHeader" : docs.HeaderModule,
d25f886f 78 "DocsList" : docs.ListModule,
cf59466c 79
e1814f16
MT
80 # Nopaste
81 "Code" : nopaste.CodeModule,
82
23f0179e 83 # Fireinfo
96c9bb79 84 "FireinfoDeviceTable" : fireinfo.DeviceTableModule,
eabe6b8d
MT
85 "FireinfoDeviceAndGroupsTable"
86 : fireinfo.DeviceAndGroupsTableModule,
87
beb13102
MT
88 # Users
89 "UsersList" : users.ListModule,
90
4235ba55 91 # VoIP
214a68a0 92 "VoIPConferences" : voip.ConferencesModule,
00465786
MT
93 "VoIPOutboundRegistrations" :
94 voip.OutboundRegistrationsModule,
8e93325b 95 "VoIPQueues" : voip.QueuesModule,
4235ba55
MT
96 "VoIPRegistrations" : voip.RegistrationsModule,
97
eabe6b8d 98 # Misc
6c6de80a 99 "IPFireLogo" : ui_modules.IPFireLogoModule,
1c4522dc 100 "Markdown" : ui_modules.MarkdownModule,
eabe6b8d
MT
101 "Map" : ui_modules.MapModule,
102 "ProgressBar" : ui_modules.ProgressBarModule,
81675874 103 },
3403dc5e
MT
104
105 # Call this when a page wasn't found
b22bc8e8 106 "default_handler_class" : base.NotFoundHandler,
9ed02e3b 107 }
9068dba1 108 settings.update(kwargs)
5cf160e0 109
ae0228e1
MT
110 tornado.web.Application.__init__(self, **settings)
111
66862195 112 authentication_handlers = [
08df6527
MT
113 (r"/login", auth.LoginHandler),
114 (r"/logout", auth.LogoutHandler),
66862195
MT
115 ]
116
c85f80e2 117 self.add_handlers(r"(www\.)?([a-z]+\.dev\.)?ipfire\.org", [
940227cb
MT
118 # Entry site that lead the user to index
119 (r"/", IndexHandler),
940227cb 120
8505c8cd 121 # Authentication
268a972b 122 (r"/join", auth.JoinHandler),
8505c8cd
MT
123 (r"/login", auth.LoginHandler),
124 (r"/logout", auth.LogoutHandler),
42c7cc66 125 (r"/activate/([a-z_][a-z0-9_-]{0,31})/(\w+)", auth.ActivateHandler),
8505c8cd 126
34472923
MT
127 # Blog
128 (r"/blog", blog.IndexHandler),
34472923
MT
129 (r"/blog/drafts", blog.DraftsHandler),
130 (r"/blog/feed.xml", blog.FeedHandler),
4d657f4f 131 (r"/blog/write", blog.WriteHandler),
feb245e0 132 (r"/blog/years/([0-9]{4})", blog.YearHandler),
34472923
MT
133 (r"/blog/([0-9a-z\-\._]+)", blog.PostHandler),
134 (r"/blog/([0-9a-z\-\._]+)/delete", blog.DeleteHandler),
135 (r"/blog/([0-9a-z\-\._]+)/edit", blog.EditHandler),
136 (r"/blog/([0-9a-z\-\._]+)/publish", blog.PublishHandler),
56801afb 137 (r"/blog/([0-9a-z\-\._]+)/debug/email", blog.DebugEmailHandler),
34472923 138
1958a22b 139 # Docs
5f0d294e 140 (r"/docs/recent\-changes", docs.RecentChangesHandler),
0ce8cc32 141 (r"/docs/search", docs.SearchHandler),
350f391e 142 (r"/docs/tree", docs.TreeHandler),
16619e57 143 (r"/docs/watchlist", docs.WatchlistHandler),
bb998aca 144 (r"/docs/_restore", docs.RestoreHandler),
26ade731 145 (r"/docs/_upload", docs.UploadHandler),
3cfea281
MT
146 (r"/docs(/[A-Za-z0-9\-_\/]+)?/_edit", docs.EditHandler),
147 (r"/docs(/[A-Za-z0-9\-_\/]+)?/_render", docs.RenderHandler),
148 (r"/docs(/[A-Za-z0-9\-_\/]+)?/_(watch|unwatch)", docs.WatchHandler),
107881bb 149 (r"/docs(/[A-Za-z0-9\-_\/]+)?/_files", docs.FilesHandler),
3cfea281
MT
150 (r"/docs(/[A-Za-z0-9\-_\/]+(?:.*)\.(?:\w+))/_delete", docs.DeleteFileHandler),
151 (r"/docs(/[A-Za-z0-9\-_\/]+(?:.*)\.(?:\w+))$", docs.FileHandler),
107881bb 152 (r"/docs(/[A-Za-z0-9\-_\/]+)?", docs.PageHandler),
1958a22b 153
aec63a26
MT
154 # Downloads
155 (r"/downloads", downloads.IndexHandler),
930647fc 156 (r"/downloads/cloud", StaticHandler, { "template" : "downloads/cloud.html" }),
aec63a26
MT
157 (r"/downloads/mirrors", downloads.MirrorsHandler),
158 (r"/downloads/thank-you", downloads.ThankYouHandler),
159 (r"/downloads/([0-9a-z\-\.]+)", downloads.ReleaseHandler),
160
e64ce07e 161 # Donate
c7bcb9ca
MT
162 (r"/donate", donate.DonateHandler),
163 (r"/donate/thank-you", donate.ThankYouHandler),
164 (r"/donate/error", donate.ErrorHandler),
8d48f4ef 165
97e15cf6
MT
166 # Lists
167 (r"/lists", lists.IndexHandler),
168
8066a1e7
MT
169 # Password Reset
170 (r"/password\-reset", auth.PasswordResetInitiationHandler),
171 (r"/password\-reset/([a-z_][a-z0-9_-]{0,31})/(\w+)", auth.PasswordResetHandler),
69a212f3 172 (r"/.well-known/change-password", auth.WellKnownChangePasswordHandler),
8066a1e7 173
d9f7b6e5
MT
174 # Projects
175 (r"/projects/location", location.IndexHandler),
930647fc
MT
176 (r"/projects/location/download", StaticHandler, { "template" : "location/download.html" }),
177 (r"/projects/location/how\-to\-use", StaticHandler, { "template" : "location/how-to-use.html" }),
d9f7b6e5
MT
178 (r"/projects/location/lookup/(.+)", location.LookupHandler),
179
2fe1d960
MT
180 # Single-Sign-On for Discourse
181 (r"/sso/discourse", auth.SSODiscourse),
182
f2c38da0
MT
183 # User Groups
184 (r"/users/groups", users.GroupIndexHandler),
185 (r"/users/groups/([a-z_][a-z0-9_-]{0,31})", users.GroupShowHandler),
186
b01a1ee3 187 # Users
beb13102 188 (r"/users", users.IndexHandler),
53b2117f
MT
189 (r"/users/([a-z_][a-z0-9_-]{0,31})", users.ShowHandler),
190 (r"/users/([a-z_][a-z0-9_-]{0,31})\.jpg", users.AvatarHandler),
1cd4d7d3 191 (r"/users/([a-z_][a-z0-9_-]{0,31})/delete", users.DeleteHandler),
3c986f14 192 (r"/users/([a-z_][a-z0-9_-]{0,31})/edit", users.EditHandler),
e4d2f51f 193 (r"/users/([a-z_][a-z0-9_-]{0,31})/passwd", users.PasswdHandler),
b01a1ee3 194
bb440bad
MT
195 # Promotional Consent Stuff
196 (r"/subscribe", users.SubscribeHandler),
197 (r"/unsubscribe", users.UnsubscribeHandler),
198
4235ba55
MT
199 # VoIP
200 (r"/voip", voip.IndexHandler),
201
45592df5 202 # Static Pages
930647fc
MT
203 (r"/about", StaticHandler, { "template" : "static/about.html" }),
204 (r"/legal", StaticHandler, { "template" : "static/legal.html" }),
205 (r"/help", StaticHandler, { "template" : "static/help.html" }),
206 (r"/sitemap", StaticHandler, { "template" : "static/sitemap.html" }),
45592df5 207
86d86819
MT
208 # API
209 (r"/api/check/email", auth.APICheckEmail),
210 (r"/api/check/uid", auth.APICheckUID),
211
14cd4fa8 212 # Handle old pages that have moved elsewhere
1f153396 213 (r"/blog/authors/(\w+)", tornado.web.RedirectHandler, { "url" : "/users/{0}" }),
7fa7d38d
MT
214 (r"/donation", tornado.web.RedirectHandler, { "url" : "/donate" }),
215 (r"/download", tornado.web.RedirectHandler, { "url" : "/downloads" }),
216 (r"/download/([0-9a-z\-\.]+)", tornado.web.RedirectHandler, { "url" : "/downloads/{0}" }),
85c977e2 217 (r"/features", tornado.web.RedirectHandler, { "url" : "/about" }),
14cd4fa8 218 (r"/imprint", tornado.web.RedirectHandler, { "url" : "/legal" }),
7fa7d38d
MT
219 (r"/news.rss", tornado.web.RedirectHandler, { "url" : "/blog/feed.xml" }),
220 (r"/news/(.*)", tornado.web.RedirectHandler, { "url" : "/blog/{0}" }),
d2000918 221 (r"/support", tornado.web.RedirectHandler, { "url" : "/help"}),
7fa7d38d 222 (r"/(de|en)/(.*)", tornado.web.RedirectHandler, { "url" : "/{0}"}),
37ed7c3c
MT
223
224 # Export arbitrary error pages
b22bc8e8 225 (r"/error/([45][0-9]{2})", base.ErrorHandler),
0ed3ea5c
MT
226
227 # Serve any static files
228 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
940227cb
MT
229 ])
230
34472923 231 # blog.ipfire.org - LEGACY REDIRECTION
c85f80e2 232 self.add_handlers(r"blog\.([a-z]+\.dev\.)?ipfire\.org", [
34472923
MT
233 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog" }),
234 (r"/authors/(\w+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/authors/{0}" }),
235 (r"/post/([0-9a-z\-\._]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/{0}" }),
236 (r"/tags/([0-9a-z\-\.]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/tags/{0}" }),
f0714277
MT
237
238 # RSS Feed
34472923
MT
239 (r"/feed.xml", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/feed.xml" }),
240 ])
12e5de7e 241
940227cb 242 # downloads.ipfire.org
c85f80e2 243 self.add_handlers(r"downloads\.([a-z]+\.dev\.)?ipfire\.org", [
82d4e789 244 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download" }),
450972a3 245 (r"/release/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download/{0}" }),
aec63a26 246 (r"/(.*)", downloads.FileHandler),
54af860e 247 ])
940227cb
MT
248
249 # mirrors.ipfire.org
c85f80e2 250 self.add_handlers(r"mirrors\.([a-z]+\.dev\.)?ipfire\.org", [
278b3118
MT
251 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download/mirrors" }),
252 (r"/mirrors/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download/mirrors/{0}" }),
3808b871 253 ])
940227cb 254
d0d074e0 255 # planet.ipfire.org
c85f80e2 256 self.add_handlers(r"planet\.([a-z]+\.dev\.)?ipfire\.org", [
3d4ce901 257 (r"/", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/" }),
7fa7d38d
MT
258 (r"/post/([A-Za-z0-9_-]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/{0}" }),
259 (r"/user/([a-z0-9_-]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/authors/{0}" }),
bcc3ed4d
MT
260
261 # RSS
f0714277 262 (r"/rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
d76ec66e 263 (r"/user/([a-z0-9_-]+)/rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
f0714277 264 (r"/news.rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
3808b871 265 ])
d0d074e0 266
66862195 267 # fireinfo.ipfire.org
c85f80e2 268 self.add_handlers(r"fireinfo\.([a-z]+\.dev\.)?ipfire\.org", [
96c9bb79 269 (r"/", fireinfo.IndexHandler),
8ab37e0b 270
dc96f754
MT
271 # Admin
272 (r"/admin", fireinfo.AdminIndexHandler),
273
8ab37e0b
MT
274 # Vendors
275 (r"/vendors", fireinfo.VendorsHandler),
276 (r"/vendors/(pci|usb)/([0-9a-f]{4})", fireinfo.VendorHandler),
66862195 277
1e3b2aad 278 # Driver
0cd21a36 279 (r"/drivers/(.*)", fireinfo.DriverDetail),
1e3b2aad 280
66862195 281 # Show profiles
96c9bb79 282 (r"/profile/random", fireinfo.RandomProfileHandler),
b84b407f 283 (r"/profile/([a-z0-9]{40})", fireinfo.ProfileHandler),
91a446f0 284
ed2e3c1f 285 # Stats
19518d6e 286 (r"/processors", fireinfo.ProcessorsHandler),
ed2e3c1f
MT
287 (r"/releases", fireinfo.ReleasesHandler),
288
19518d6e 289 # Send profiles
96c9bb79 290 (r"/send/([a-z0-9]+)", fireinfo.ProfileSendHandler),
0ed3ea5c
MT
291
292 # Serve any static files
293 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
dc96f754 294 ] + authentication_handlers)
5cf160e0 295
c37ec602 296 # i-use.ipfire.org
c85f80e2 297 self.add_handlers(r"i-use\.([a-z]+\.dev\.)?ipfire\.org", [
e2f2865d 298 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/" }),
395c1ac0 299 (r"/profile/([a-f0-9]{40})/([0-9]+).png", iuse.ImageHandler),
c37ec602
MT
300 ])
301
8e2e1261
MT
302 # boot.ipfire.org
303 BOOT_STATIC_PATH = os.path.join(self.settings["static_path"], "netboot")
c85f80e2 304 self.add_handlers(r"boot\.([a-z]+\.dev\.)?ipfire\.org", [
f301d952 305 (r"/", tornado.web.RedirectHandler, { "url" : "https://wiki.ipfire.org/installation/pxe" }),
8e2e1261
MT
306
307 # Configurations
f301d952
MT
308 (r"/premenu.cfg", boot.PremenuCfgHandler),
309 (r"/menu.gpxe", boot.MenuGPXEHandler),
310 (r"/menu.cfg", boot.MenuCfgHandler),
8e2e1261
MT
311
312 # Static files
37b5c0cf 313 (r"/(boot\.png|pxelinux\.0|menu\.c32|vesamenu\.c32)",
8e2e1261
MT
314 tornado.web.StaticFileHandler, { "path" : BOOT_STATIC_PATH }),
315 ])
316
60024cc8 317 # nopaste.ipfire.org
c85f80e2 318 self.add_handlers(r"nopaste\.([a-z]+\.dev\.)?ipfire\.org", [
a41085fb
MT
319 (r"/", nopaste.CreateHandler),
320 (r"/raw/(.*)", nopaste.RawHandler),
321 (r"/view/(.*)", nopaste.ViewHandler),
0ed3ea5c
MT
322
323 # Serve any static files
324 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
3808b871 325 ] + authentication_handlers)
60024cc8 326
f5b01fc2 327 # location.ipfire.org
c85f80e2 328 self.add_handlers(r"location\.([a-z]+\.dev\.)?ipfire\.org", [
d9f7b6e5 329 (r"/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/projects/location/{0}" }),
f5b01fc2
MT
330 ])
331
9068dba1 332 # geoip.ipfire.org
c85f80e2 333 self.add_handlers(r"geoip\.([a-z]+\.dev\.)?ipfire\.org", [
f5b01fc2 334 (r"/", tornado.web.RedirectHandler, { "url" : "https://location.ipfire.org/" }),
3808b871 335 ])
9068dba1 336
66862195 337 # talk.ipfire.org
c85f80e2 338 self.add_handlers(r"talk\.([a-z]+\.dev\.)?ipfire\.org", [
786e9ca8
MT
339 (r"/", tornado.web.RedirectHandler, { "url" : "https://people.ipfire.org/" }),
340 ])
66862195 341
03706893 342 # people.ipfire.org
c85f80e2 343 self.add_handlers(r"people\.([a-z]+\.dev\.)?ipfire\.org", [
b6026905 344 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/users" }),
268a972b 345 (r"/register", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/join" }),
b6026905
MT
346 (r"/users", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/users" }),
347 (r"/users/([a-z_][a-z0-9_-]{0,31})", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/users/{0}" }),
348 (r"/users/([a-z_][a-z0-9_-]{0,31})\.jpg", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/users/{0}.jpg" }),
349 ])
2cd9af74 350
181d08f3 351 # wiki.ipfire.org
9741abf5
MT
352 self.add_handlers(r"wiki\.([a-z]+\.dev\.)?ipfire\.org", [
353 (r"/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/docs/{0}" }),
181d08f3
MT
354 ])
355
ae0228e1 356 # ipfire.org
e65b9a6d 357 self.add_handlers(r"(.*)ipfire\.org", [
ba43a892 358 (r".*", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org" })
5cf160e0 359 ])
3add293a 360
feb02477
MT
361 logging.info("Successfully initialied application")
362
574a88c7 363 def format_country_name(self, handler, country_code):
e929ed92 364 return self.backend.get_country_name(country_code)
574a88c7 365
6eddfb50
MT
366 def format_language_name(self, handler, language):
367 _ = handler.locale.translate
368
369 if language == "de":
370 return _("German")
371 elif language == "en":
372 return _("English")
373 elif language == "es":
374 return _("Spanish")
375 elif language == "fr":
376 return _("French")
377 elif language == "it":
378 return _("Italian")
379 elif language == "nl":
380 return _("Dutch")
381 elif language == "pl":
382 return _("Polish")
383 elif language == "pt":
384 return _("Portuguese")
385 elif language == "ru":
386 return _("Russian")
387 elif language == "tr":
388 return _("Turkish")
389
390 return language
391
cc3b928d
MT
392 def format_month_name(self, handler, month):
393 _ = handler.locale.translate
394
395 if month == 1:
396 return _("January")
397 elif month == 2:
398 return _("February")
399 elif month == 3:
400 return _("March")
401 elif month == 4:
402 return _("April")
403 elif month == 5:
404 return _("May")
405 elif month == 6:
406 return _("June")
407 elif month == 7:
408 return _("July")
409 elif month == 8:
410 return _("August")
411 elif month == 9:
412 return _("September")
413 elif month == 10:
414 return _("October")
415 elif month == 11:
416 return _("November")
417 elif month == 12:
418 return _("December")
419
420 return month
401827c2 421
e96e445b
MT
422 def format_phone_number(self, handler, number):
423 if not isinstance(number, phonenumbers.PhoneNumber):
424 try:
01e73b0e 425 number = phonenumbers.parse(number, None)
e96e445b
MT
426 except phonenumbers.phonenumberutil.NumberParseException:
427 return number
c01ad253
MT
428
429 return phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
430
e96e445b
MT
431 def format_phone_number_to_e164(self, handler, number):
432 return phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.E164)
433
434 def format_phone_number_location(self, handler, number):
435 s = [
436 phonenumbers.geocoder.description_for_number(number, handler.locale.code),
437 phonenumbers.region_code_for_number(number),
438 ]
439
440 return ", ".join((e for e in s if e))