]> git.ipfire.org Git - ipfire.org.git/blame - src/web/__init__.py
blog: Move history navigation to the bottom of the page
[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
f5b01fc2 25from . import location
a41085fb 26from . import nopaste
df6180a5 27from . import ui_modules
b01a1ee3 28from . import users
4235ba55 29from . import voip
12e5de7e 30
81675874 31class Application(tornado.web.Application):
3e7c6ccd
MT
32 def __init__(self, config, **kwargs):
33 # Initialize backend
a95c2f97 34 self.backend = ipfire.Backend(config)
a6dc0bad 35
9ed02e3b
MT
36 settings = {
37 # Do not compress responses
38 "gzip" : False,
39
40 # Enable XSRF cookies
41 "xsrf_cookies" : True,
42
43 # Login
44 "login_url" : "/login",
45
46 # Setup directory structure
47 "static_path" : self.backend.config.get("global", "static_dir"),
48 "template_path" : self.backend.config.get("global", "templates_dir"),
49
eabe6b8d 50 # UI Methods
9ed02e3b 51 "ui_methods" : {
574a88c7 52 "format_country_name" : self.format_country_name,
6eddfb50 53 "format_language_name" : self.format_language_name,
e96e445b
MT
54 "format_month_name" : self.format_month_name,
55 "format_phone_number" : self.format_phone_number,
56 "format_phone_number_to_e164" : self.format_phone_number_to_e164,
57 "format_phone_number_location" : self.format_phone_number_location,
cc3b928d 58 },
eabe6b8d
MT
59
60 # UI Modules
9ed02e3b 61 "ui_modules" : {
5806d6fc
MT
62 # Auth
63 "Password" : auth.PasswordModule,
64
f5b01fc2 65 # Blog
7e64f6a3
MT
66 "BlogHistoryNavigation": blog.HistoryNavigationModule,
67 "BlogList" : blog.ListModule,
f91dfcc7
MT
68 "BlogPost" : blog.PostModule,
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
6563eb49 99 "ChristmasBanner" : ui_modules.ChristmasBannerModule,
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
MT
121 # Authentication
122 (r"/login", auth.LoginHandler),
123 (r"/logout", auth.LogoutHandler),
124 (r"/register", auth.RegisterHandler),
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),
34472923 131 (r"/blog/tags/([0-9a-z\-\.]+)", blog.TagHandler),
4d657f4f 132 (r"/blog/write", blog.WriteHandler),
feb245e0 133 (r"/blog/years/([0-9]{4})", blog.YearHandler),
34472923
MT
134 (r"/blog/([0-9a-z\-\._]+)", blog.PostHandler),
135 (r"/blog/([0-9a-z\-\._]+)/delete", blog.DeleteHandler),
136 (r"/blog/([0-9a-z\-\._]+)/edit", blog.EditHandler),
137 (r"/blog/([0-9a-z\-\._]+)/publish", blog.PublishHandler),
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),
ec17fa2b
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),
16510618 149 (r"/docs/((?:[A-Za-z0-9\-_\/]+)?(?:.*)\.(?:\w+))/_delete", docs.DeleteFileHandler),
4a1bfdd5 150 (r"/docs((?:[A-Za-z0-9\-_\/]+)?(?:.*)\.(?:\w+))$", docs.FileHandler),
efaf0fa6 151 (r"/docs([A-Za-z0-9\-_\/]+)?/_files", docs.FilesHandler),
1958a22b
MT
152 (r"/docs([A-Za-z0-9\-_\/]+)?", docs.PageHandler),
153
aec63a26
MT
154 # Downloads
155 (r"/downloads", downloads.IndexHandler),
156 (r"/downloads/mirrors", downloads.MirrorsHandler),
157 (r"/downloads/thank-you", downloads.ThankYouHandler),
158 (r"/downloads/([0-9a-z\-\.]+)", downloads.ReleaseHandler),
159
e64ce07e 160 # Donate
c7bcb9ca
MT
161 (r"/donate", donate.DonateHandler),
162 (r"/donate/thank-you", donate.ThankYouHandler),
163 (r"/donate/error", donate.ErrorHandler),
8d48f4ef 164
8066a1e7
MT
165 # Password Reset
166 (r"/password\-reset", auth.PasswordResetInitiationHandler),
167 (r"/password\-reset/([a-z_][a-z0-9_-]{0,31})/(\w+)", auth.PasswordResetHandler),
168
d9f7b6e5
MT
169 # Projects
170 (r"/projects/location", location.IndexHandler),
171 (r"/projects/location/download", StaticHandler, { "template" : "../location/download.html" }),
172 (r"/projects/location/how\-to\-use", StaticHandler, { "template" : "../location/how-to-use.html" }),
d9f7b6e5
MT
173 (r"/projects/location/lookup/(.+)", location.LookupHandler),
174
2fe1d960
MT
175 # Single-Sign-On for Discourse
176 (r"/sso/discourse", auth.SSODiscourse),
177
f2c38da0
MT
178 # User Groups
179 (r"/users/groups", users.GroupIndexHandler),
180 (r"/users/groups/([a-z_][a-z0-9_-]{0,31})", users.GroupShowHandler),
181
b01a1ee3 182 # Users
beb13102 183 (r"/users", users.IndexHandler),
53b2117f
MT
184 (r"/users/([a-z_][a-z0-9_-]{0,31})", users.ShowHandler),
185 (r"/users/([a-z_][a-z0-9_-]{0,31})\.jpg", users.AvatarHandler),
1cd4d7d3 186 (r"/users/([a-z_][a-z0-9_-]{0,31})/delete", users.DeleteHandler),
3c986f14 187 (r"/users/([a-z_][a-z0-9_-]{0,31})/edit", users.EditHandler),
e4d2f51f 188 (r"/users/([a-z_][a-z0-9_-]{0,31})/passwd", users.PasswdHandler),
b01a1ee3 189
bb440bad
MT
190 # Promotional Consent Stuff
191 (r"/subscribe", users.SubscribeHandler),
192 (r"/unsubscribe", users.UnsubscribeHandler),
193
4235ba55
MT
194 # VoIP
195 (r"/voip", voip.IndexHandler),
196
45592df5 197 # Static Pages
8ea3eaa2 198 (r"/about", StaticHandler, { "template" : "about.html" }),
45592df5 199 (r"/legal", StaticHandler, { "template" : "legal.html" }),
d2000918 200 (r"/help", StaticHandler, { "template" : "help.html" }),
d1ec64e1 201 (r"/sitemap", StaticHandler, { "template" : "sitemap.html" }),
45592df5 202
86d86819
MT
203 # API
204 (r"/api/check/email", auth.APICheckEmail),
205 (r"/api/check/uid", auth.APICheckUID),
206
14cd4fa8 207 # Handle old pages that have moved elsewhere
1f153396 208 (r"/blog/authors/(\w+)", tornado.web.RedirectHandler, { "url" : "/users/{0}" }),
7fa7d38d
MT
209 (r"/donation", tornado.web.RedirectHandler, { "url" : "/donate" }),
210 (r"/download", tornado.web.RedirectHandler, { "url" : "/downloads" }),
211 (r"/download/([0-9a-z\-\.]+)", tornado.web.RedirectHandler, { "url" : "/downloads/{0}" }),
85c977e2 212 (r"/features", tornado.web.RedirectHandler, { "url" : "/about" }),
14cd4fa8 213 (r"/imprint", tornado.web.RedirectHandler, { "url" : "/legal" }),
7fa7d38d
MT
214 (r"/news.rss", tornado.web.RedirectHandler, { "url" : "/blog/feed.xml" }),
215 (r"/news/(.*)", tornado.web.RedirectHandler, { "url" : "/blog/{0}" }),
d2000918 216 (r"/support", tornado.web.RedirectHandler, { "url" : "/help"}),
7fa7d38d 217 (r"/(de|en)/(.*)", tornado.web.RedirectHandler, { "url" : "/{0}"}),
37ed7c3c
MT
218
219 # Export arbitrary error pages
b22bc8e8 220 (r"/error/([45][0-9]{2})", base.ErrorHandler),
0ed3ea5c
MT
221
222 # Serve any static files
223 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
940227cb
MT
224 ])
225
34472923 226 # blog.ipfire.org - LEGACY REDIRECTION
c85f80e2 227 self.add_handlers(r"blog\.([a-z]+\.dev\.)?ipfire\.org", [
34472923
MT
228 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog" }),
229 (r"/authors/(\w+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/authors/{0}" }),
230 (r"/post/([0-9a-z\-\._]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/{0}" }),
231 (r"/tags/([0-9a-z\-\.]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/tags/{0}" }),
f0714277
MT
232
233 # RSS Feed
34472923
MT
234 (r"/feed.xml", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/feed.xml" }),
235 ])
12e5de7e 236
940227cb 237 # downloads.ipfire.org
c85f80e2 238 self.add_handlers(r"downloads\.([a-z]+\.dev\.)?ipfire\.org", [
82d4e789 239 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download" }),
450972a3 240 (r"/release/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download/{0}" }),
aec63a26 241 (r"/(.*)", downloads.FileHandler),
54af860e 242 ])
940227cb
MT
243
244 # mirrors.ipfire.org
c85f80e2 245 self.add_handlers(r"mirrors\.([a-z]+\.dev\.)?ipfire\.org", [
278b3118
MT
246 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download/mirrors" }),
247 (r"/mirrors/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download/mirrors/{0}" }),
3808b871 248 ])
940227cb 249
d0d074e0 250 # planet.ipfire.org
c85f80e2 251 self.add_handlers(r"planet\.([a-z]+\.dev\.)?ipfire\.org", [
3d4ce901 252 (r"/", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/" }),
7fa7d38d
MT
253 (r"/post/([A-Za-z0-9_-]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/{0}" }),
254 (r"/user/([a-z0-9_-]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/authors/{0}" }),
bcc3ed4d
MT
255
256 # RSS
f0714277 257 (r"/rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
d76ec66e 258 (r"/user/([a-z0-9_-]+)/rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
f0714277 259 (r"/news.rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
3808b871 260 ])
d0d074e0 261
66862195 262 # fireinfo.ipfire.org
c85f80e2 263 self.add_handlers(r"fireinfo\.([a-z]+\.dev\.)?ipfire\.org", [
96c9bb79 264 (r"/", fireinfo.IndexHandler),
8ab37e0b 265
dc96f754
MT
266 # Admin
267 (r"/admin", fireinfo.AdminIndexHandler),
268
8ab37e0b
MT
269 # Vendors
270 (r"/vendors", fireinfo.VendorsHandler),
271 (r"/vendors/(pci|usb)/([0-9a-f]{4})", fireinfo.VendorHandler),
66862195 272
1e3b2aad 273 # Driver
0cd21a36 274 (r"/drivers/(.*)", fireinfo.DriverDetail),
1e3b2aad 275
66862195 276 # Show profiles
96c9bb79 277 (r"/profile/random", fireinfo.RandomProfileHandler),
b84b407f 278 (r"/profile/([a-z0-9]{40})", fireinfo.ProfileHandler),
91a446f0 279
ed2e3c1f 280 # Stats
19518d6e 281 (r"/processors", fireinfo.ProcessorsHandler),
ed2e3c1f
MT
282 (r"/releases", fireinfo.ReleasesHandler),
283
19518d6e 284 # Send profiles
96c9bb79 285 (r"/send/([a-z0-9]+)", fireinfo.ProfileSendHandler),
0ed3ea5c
MT
286
287 # Serve any static files
288 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
dc96f754 289 ] + authentication_handlers)
5cf160e0 290
c37ec602 291 # i-use.ipfire.org
c85f80e2 292 self.add_handlers(r"i-use\.([a-z]+\.dev\.)?ipfire\.org", [
e2f2865d 293 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/" }),
395c1ac0 294 (r"/profile/([a-f0-9]{40})/([0-9]+).png", iuse.ImageHandler),
c37ec602
MT
295 ])
296
8e2e1261
MT
297 # boot.ipfire.org
298 BOOT_STATIC_PATH = os.path.join(self.settings["static_path"], "netboot")
c85f80e2 299 self.add_handlers(r"boot\.([a-z]+\.dev\.)?ipfire\.org", [
f301d952 300 (r"/", tornado.web.RedirectHandler, { "url" : "https://wiki.ipfire.org/installation/pxe" }),
8e2e1261
MT
301
302 # Configurations
f301d952
MT
303 (r"/premenu.cfg", boot.PremenuCfgHandler),
304 (r"/menu.gpxe", boot.MenuGPXEHandler),
305 (r"/menu.cfg", boot.MenuCfgHandler),
8e2e1261
MT
306
307 # Static files
37b5c0cf 308 (r"/(boot\.png|pxelinux\.0|menu\.c32|vesamenu\.c32)",
8e2e1261
MT
309 tornado.web.StaticFileHandler, { "path" : BOOT_STATIC_PATH }),
310 ])
311
60024cc8 312 # nopaste.ipfire.org
c85f80e2 313 self.add_handlers(r"nopaste\.([a-z]+\.dev\.)?ipfire\.org", [
a41085fb
MT
314 (r"/", nopaste.CreateHandler),
315 (r"/raw/(.*)", nopaste.RawHandler),
316 (r"/view/(.*)", nopaste.ViewHandler),
0ed3ea5c
MT
317
318 # Serve any static files
319 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
3808b871 320 ] + authentication_handlers)
60024cc8 321
f5b01fc2 322 # location.ipfire.org
c85f80e2 323 self.add_handlers(r"location\.([a-z]+\.dev\.)?ipfire\.org", [
d9f7b6e5 324 (r"/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/projects/location/{0}" }),
f5b01fc2
MT
325 ])
326
9068dba1 327 # geoip.ipfire.org
c85f80e2 328 self.add_handlers(r"geoip\.([a-z]+\.dev\.)?ipfire\.org", [
f5b01fc2 329 (r"/", tornado.web.RedirectHandler, { "url" : "https://location.ipfire.org/" }),
3808b871 330 ])
9068dba1 331
66862195 332 # talk.ipfire.org
c85f80e2 333 self.add_handlers(r"talk\.([a-z]+\.dev\.)?ipfire\.org", [
786e9ca8
MT
334 (r"/", tornado.web.RedirectHandler, { "url" : "https://people.ipfire.org/" }),
335 ])
66862195 336
03706893 337 # people.ipfire.org
c85f80e2 338 self.add_handlers(r"people\.([a-z]+\.dev\.)?ipfire\.org", [
b6026905
MT
339 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/users" }),
340 (r"/register", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/register" }),
341 (r"/users", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/users" }),
342 (r"/users/([a-z_][a-z0-9_-]{0,31})", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/users/{0}" }),
343 (r"/users/([a-z_][a-z0-9_-]{0,31})\.jpg", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/users/{0}.jpg" }),
344 ])
2cd9af74 345
181d08f3 346 # wiki.ipfire.org
9741abf5
MT
347 self.add_handlers(r"wiki\.([a-z]+\.dev\.)?ipfire\.org", [
348 (r"/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/docs/{0}" }),
181d08f3
MT
349 ])
350
ae0228e1 351 # ipfire.org
e65b9a6d 352 self.add_handlers(r"(.*)ipfire\.org", [
ba43a892 353 (r".*", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org" })
5cf160e0 354 ])
3add293a 355
feb02477
MT
356 logging.info("Successfully initialied application")
357
574a88c7 358 def format_country_name(self, handler, country_code):
e929ed92 359 return self.backend.get_country_name(country_code)
574a88c7 360
6eddfb50
MT
361 def format_language_name(self, handler, language):
362 _ = handler.locale.translate
363
364 if language == "de":
365 return _("German")
366 elif language == "en":
367 return _("English")
368 elif language == "es":
369 return _("Spanish")
370 elif language == "fr":
371 return _("French")
372 elif language == "it":
373 return _("Italian")
374 elif language == "nl":
375 return _("Dutch")
376 elif language == "pl":
377 return _("Polish")
378 elif language == "pt":
379 return _("Portuguese")
380 elif language == "ru":
381 return _("Russian")
382 elif language == "tr":
383 return _("Turkish")
384
385 return language
386
cc3b928d
MT
387 def format_month_name(self, handler, month):
388 _ = handler.locale.translate
389
390 if month == 1:
391 return _("January")
392 elif month == 2:
393 return _("February")
394 elif month == 3:
395 return _("March")
396 elif month == 4:
397 return _("April")
398 elif month == 5:
399 return _("May")
400 elif month == 6:
401 return _("June")
402 elif month == 7:
403 return _("July")
404 elif month == 8:
405 return _("August")
406 elif month == 9:
407 return _("September")
408 elif month == 10:
409 return _("October")
410 elif month == 11:
411 return _("November")
412 elif month == 12:
413 return _("December")
414
415 return month
401827c2 416
e96e445b
MT
417 def format_phone_number(self, handler, number):
418 if not isinstance(number, phonenumbers.PhoneNumber):
419 try:
01e73b0e 420 number = phonenumbers.parse(number, None)
e96e445b
MT
421 except phonenumbers.phonenumberutil.NumberParseException:
422 return number
c01ad253
MT
423
424 return phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
425
e96e445b
MT
426 def format_phone_number_to_e164(self, handler, number):
427 return phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.E164)
428
429 def format_phone_number_location(self, handler, number):
430 s = [
431 phonenumbers.geocoder.description_for_number(number, handler.locale.code),
432 phonenumbers.region_code_for_number(number),
433 ]
434
435 return ", ".join((e for e in s if e))