]> git.ipfire.org Git - ipfire.org.git/blame - src/web/__init__.py
footer: Keep profile navigation and social icons horizontal
[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
c7bcb9ca 20from . import donate
e77cd04c 21from . import download
96c9bb79 22from . import fireinfo
699a0911 23from . import iuse
f5b01fc2 24from . import location
a41085fb 25from . import nopaste
03706893 26from . import people
df6180a5 27from . import ui_modules
b01a1ee3 28from . import users
181d08f3 29from . import wiki
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" : {
f5b01fc2 62 # Blog
7e64f6a3
MT
63 "BlogHistoryNavigation": blog.HistoryNavigationModule,
64 "BlogList" : blog.ListModule,
f91dfcc7
MT
65 "BlogPost" : blog.PostModule,
66
93feb275
MT
67 # Boot
68 "BootMenuConfig" : boot.MenuConfigModule,
69 "BootMenuHeader" : boot.MenuHeaderModule,
70 "BootMenuSeparator" : boot.MenuSeparatorModule,
71
eabe6b8d 72 # People
dbb0c109 73 "AccountsList" : people.AccountsListModule,
c66f2152 74 "Agent" : people.AgentModule,
dbb0c109
MT
75 "CDR" : people.CDRModule,
76 "Channels" : people.ChannelsModule,
68ece434 77 "MOS" : people.MOSModule,
b5e2077f 78 "Password" : people.PasswordModule,
dbb0c109 79 "Registrations" : people.RegistrationsModule,
917434b8 80
e1814f16
MT
81 # Nopaste
82 "Code" : nopaste.CodeModule,
83
23f0179e 84 # Fireinfo
96c9bb79 85 "FireinfoDeviceTable" : fireinfo.DeviceTableModule,
eabe6b8d
MT
86 "FireinfoDeviceAndGroupsTable"
87 : fireinfo.DeviceAndGroupsTableModule,
88
beb13102
MT
89 # Users
90 "UsersList" : users.ListModule,
91
6ac7e934 92 # Wiki
c21ffadb 93 "WikiDiff" : wiki.WikiDiffModule,
6ac7e934 94 "WikiNavbar" : wiki.WikiNavbarModule,
f9db574a 95 "WikiList" : wiki.WikiListModule,
6ac7e934 96
eabe6b8d 97 # Misc
6563eb49 98 "ChristmasBanner" : ui_modules.ChristmasBannerModule,
1c4522dc 99 "Markdown" : ui_modules.MarkdownModule,
eabe6b8d
MT
100 "Map" : ui_modules.MapModule,
101 "ProgressBar" : ui_modules.ProgressBarModule,
81675874 102 },
3403dc5e
MT
103
104 # Call this when a page wasn't found
b22bc8e8 105 "default_handler_class" : base.NotFoundHandler,
9ed02e3b 106 }
9068dba1 107 settings.update(kwargs)
5cf160e0 108
ae0228e1
MT
109 tornado.web.Application.__init__(self, **settings)
110
66862195 111 authentication_handlers = [
08df6527
MT
112 (r"/login", auth.LoginHandler),
113 (r"/logout", auth.LogoutHandler),
66862195
MT
114 ]
115
c85f80e2 116 self.add_handlers(r"(www\.)?([a-z]+\.dev\.)?ipfire\.org", [
940227cb
MT
117 # Entry site that lead the user to index
118 (r"/", IndexHandler),
e9f2963b 119 (r"/about", AboutHandler),
940227cb 120
8505c8cd
MT
121 # Authentication
122 (r"/login", auth.LoginHandler),
123 (r"/logout", auth.LogoutHandler),
124 (r"/register", auth.RegisterHandler),
125
34472923
MT
126 # Blog
127 (r"/blog", blog.IndexHandler),
128 (r"/blog/authors/(\w+)", blog.AuthorHandler),
129 (r"/blog/compose", blog.ComposeHandler),
130 (r"/blog/drafts", blog.DraftsHandler),
131 (r"/blog/feed.xml", blog.FeedHandler),
132 (r"/blog/search", blog.SearchHandler),
133 (r"/blog/tags/([0-9a-z\-\.]+)", blog.TagHandler),
feb245e0 134 (r"/blog/years/([0-9]{4})", blog.YearHandler),
34472923
MT
135 (r"/blog/([0-9a-z\-\._]+)", blog.PostHandler),
136 (r"/blog/([0-9a-z\-\._]+)/delete", blog.DeleteHandler),
137 (r"/blog/([0-9a-z\-\._]+)/edit", blog.EditHandler),
138 (r"/blog/([0-9a-z\-\._]+)/publish", blog.PublishHandler),
139
81675874 140 # Download sites
60b0917c 141 (r"/downloads", tornado.web.RedirectHandler, { "url" : "/download" }),
e77cd04c 142 (r"/download", download.IndexHandler),
278b3118 143 (r"/download/mirrors", download.MirrorsHandler),
baeec765 144 (r"/download/thank-you", download.ThankYouHandler),
e77cd04c 145 (r"/download/([0-9a-z\-\.]+)", download.ReleaseHandler),
940227cb 146
e64ce07e 147 # Donate
c7bcb9ca
MT
148 (r"/donate", donate.DonateHandler),
149 (r"/donate/thank-you", donate.ThankYouHandler),
150 (r"/donate/error", donate.ErrorHandler),
e64ce07e 151 (r"/donation", tornado.web.RedirectHandler, { "url" : "/donate" }),
8d48f4ef 152
b01a1ee3 153 # Users
beb13102 154 (r"/users", users.IndexHandler),
53b2117f
MT
155 (r"/users/([a-z_][a-z0-9_-]{0,31})", users.ShowHandler),
156 (r"/users/([a-z_][a-z0-9_-]{0,31})\.jpg", users.AvatarHandler),
b01a1ee3 157
de683d7c 158 # RSS feed
f0714277 159 (r"/news.rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
7f9dbcc0
MT
160
161 # Redirect news articles to blog
d76ec66e 162 (r"/news/(.*)", handlers.NewsHandler),
de683d7c 163
45592df5 164 # Static Pages
45592df5 165 (r"/features", StaticHandler, { "template" : "features.html" }),
45592df5 166 (r"/legal", StaticHandler, { "template" : "legal.html" }),
d2000918 167 (r"/help", StaticHandler, { "template" : "help.html" }),
45592df5 168
14cd4fa8
MT
169 # Handle old pages that have moved elsewhere
170 (r"/imprint", tornado.web.RedirectHandler, { "url" : "/legal" }),
3808b871 171 (r"/(de|en)/(.*)", LangCompatHandler),
d2000918 172 (r"/support", tornado.web.RedirectHandler, { "url" : "/help"}),
37ed7c3c
MT
173
174 # Export arbitrary error pages
b22bc8e8 175 (r"/error/([45][0-9]{2})", base.ErrorHandler),
0ed3ea5c
MT
176
177 # Serve any static files
178 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
940227cb
MT
179 ])
180
34472923 181 # blog.ipfire.org - LEGACY REDIRECTION
c85f80e2 182 self.add_handlers(r"blog\.([a-z]+\.dev\.)?ipfire\.org", [
34472923
MT
183 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog" }),
184 (r"/authors/(\w+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/authors/{0}" }),
185 (r"/post/([0-9a-z\-\._]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/{0}" }),
186 (r"/tags/([0-9a-z\-\.]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/tags/{0}" }),
f0714277
MT
187
188 # RSS Feed
34472923
MT
189 (r"/feed.xml", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/feed.xml" }),
190 ])
12e5de7e 191
940227cb 192 # downloads.ipfire.org
c85f80e2 193 self.add_handlers(r"downloads\.([a-z]+\.dev\.)?ipfire\.org", [
82d4e789 194 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download" }),
450972a3 195 (r"/release/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download/{0}" }),
ed8116c7 196 (r"/(.*)", download.FileHandler),
54af860e 197 ])
940227cb
MT
198
199 # mirrors.ipfire.org
c85f80e2 200 self.add_handlers(r"mirrors\.([a-z]+\.dev\.)?ipfire\.org", [
278b3118
MT
201 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download/mirrors" }),
202 (r"/mirrors/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download/mirrors/{0}" }),
3808b871 203 ])
940227cb 204
d0d074e0 205 # planet.ipfire.org
c85f80e2 206 self.add_handlers(r"planet\.([a-z]+\.dev\.)?ipfire\.org", [
3d4ce901 207 (r"/", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/" }),
d76ec66e
MT
208 (r"/post/([A-Za-z0-9_-]+)", handlers.PlanetPostHandler),
209 (r"/user/([a-z0-9_-]+)", handlers.PlanetUserHandler),
bcc3ed4d
MT
210
211 # RSS
f0714277 212 (r"/rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
d76ec66e 213 (r"/user/([a-z0-9_-]+)/rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
f0714277 214 (r"/news.rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
3808b871 215 ])
d0d074e0 216
66862195 217 # fireinfo.ipfire.org
c85f80e2 218 self.add_handlers(r"fireinfo\.([a-z]+\.dev\.)?ipfire\.org", [
96c9bb79 219 (r"/", fireinfo.IndexHandler),
8ab37e0b 220
dc96f754
MT
221 # Admin
222 (r"/admin", fireinfo.AdminIndexHandler),
223
8ab37e0b
MT
224 # Vendors
225 (r"/vendors", fireinfo.VendorsHandler),
226 (r"/vendors/(pci|usb)/([0-9a-f]{4})", fireinfo.VendorHandler),
66862195 227
1e3b2aad 228 # Driver
0cd21a36 229 (r"/drivers/(.*)", fireinfo.DriverDetail),
1e3b2aad 230
66862195 231 # Show profiles
96c9bb79 232 (r"/profile/random", fireinfo.RandomProfileHandler),
b84b407f 233 (r"/profile/([a-z0-9]{40})", fireinfo.ProfileHandler),
91a446f0 234
ed2e3c1f 235 # Stats
19518d6e 236 (r"/processors", fireinfo.ProcessorsHandler),
ed2e3c1f
MT
237 (r"/releases", fireinfo.ReleasesHandler),
238
19518d6e 239 # Send profiles
96c9bb79 240 (r"/send/([a-z0-9]+)", fireinfo.ProfileSendHandler),
0ed3ea5c
MT
241
242 # Serve any static files
243 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
dc96f754 244 ] + authentication_handlers)
5cf160e0 245
c37ec602 246 # i-use.ipfire.org
c85f80e2 247 self.add_handlers(r"i-use\.([a-z]+\.dev\.)?ipfire\.org", [
e2f2865d 248 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/" }),
395c1ac0 249 (r"/profile/([a-f0-9]{40})/([0-9]+).png", iuse.ImageHandler),
c37ec602
MT
250 ])
251
8e2e1261
MT
252 # boot.ipfire.org
253 BOOT_STATIC_PATH = os.path.join(self.settings["static_path"], "netboot")
c85f80e2 254 self.add_handlers(r"boot\.([a-z]+\.dev\.)?ipfire\.org", [
f301d952 255 (r"/", tornado.web.RedirectHandler, { "url" : "https://wiki.ipfire.org/installation/pxe" }),
8e2e1261
MT
256
257 # Configurations
f301d952
MT
258 (r"/premenu.cfg", boot.PremenuCfgHandler),
259 (r"/menu.gpxe", boot.MenuGPXEHandler),
260 (r"/menu.cfg", boot.MenuCfgHandler),
8e2e1261
MT
261
262 # Static files
37b5c0cf 263 (r"/(boot\.png|pxelinux\.0|menu\.c32|vesamenu\.c32)",
8e2e1261
MT
264 tornado.web.StaticFileHandler, { "path" : BOOT_STATIC_PATH }),
265 ])
266
60024cc8 267 # nopaste.ipfire.org
c85f80e2 268 self.add_handlers(r"nopaste\.([a-z]+\.dev\.)?ipfire\.org", [
a41085fb
MT
269 (r"/", nopaste.CreateHandler),
270 (r"/raw/(.*)", nopaste.RawHandler),
271 (r"/view/(.*)", nopaste.ViewHandler),
0ed3ea5c
MT
272
273 # Serve any static files
274 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
3808b871 275 ] + authentication_handlers)
60024cc8 276
f5b01fc2 277 # location.ipfire.org
c85f80e2 278 self.add_handlers(r"location\.([a-z]+\.dev\.)?ipfire\.org", [
f5b01fc2 279 (r"/", location.IndexHandler),
9c83876f 280 (r"/download", StaticHandler, { "template" : "../location/download.html" }),
55eea098 281 (r"/how\-to\-use", StaticHandler, { "template" : "../location/how-to-use.html" }),
2517822e 282 (r"/lookup/(.+)/blacklists", location.BlacklistsHandler),
f5b01fc2 283 (r"/lookup/(.+)", location.LookupHandler),
0ed3ea5c
MT
284
285 # Serve any static files
286 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
f5b01fc2
MT
287 ])
288
9068dba1 289 # geoip.ipfire.org
c85f80e2 290 self.add_handlers(r"geoip\.([a-z]+\.dev\.)?ipfire\.org", [
f5b01fc2 291 (r"/", tornado.web.RedirectHandler, { "url" : "https://location.ipfire.org/" }),
3808b871 292 ])
9068dba1 293
66862195 294 # talk.ipfire.org
c85f80e2 295 self.add_handlers(r"talk\.([a-z]+\.dev\.)?ipfire\.org", [
786e9ca8
MT
296 (r"/", tornado.web.RedirectHandler, { "url" : "https://people.ipfire.org/" }),
297 ])
66862195 298
03706893 299 # people.ipfire.org
c85f80e2 300 self.add_handlers(r"people\.([a-z]+\.dev\.)?ipfire\.org", [
786e9ca8 301 (r"/", people.IndexHandler),
2c65e17c 302 (r"/activate/([a-z_][a-z0-9_-]{0,31})/(\w+)", auth.ActivateHandler),
30aeccdb 303 (r"/conferences", people.ConferencesHandler),
18b13823 304 (r"/groups", people.GroupsHandler),
736e7544 305 (r"/groups/([a-z_][a-z0-9_-]{0,31})", people.GroupHandler),
f32dd17f 306 (r"/register", auth.RegisterHandler),
2c65e17c
MT
307 (r"/users/([a-z_][a-z0-9_-]{0,31})/calls/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})", people.CallHandler),
308 (r"/users/([a-z_][a-z0-9_-]{0,31})/calls(?:/(\d{4}-\d{2}-\d{2}))?", people.CallsHandler),
309 (r"/users/([a-z_][a-z0-9_-]{0,31})/edit", people.UserEditHandler),
310 (r"/users/([a-z_][a-z0-9_-]{0,31})/passwd", people.UserPasswdHandler),
311 (r"/users/([a-z_][a-z0-9_-]{0,31})/sip", people.SIPHandler),
2dac7110 312
92c4b559
MT
313 # Promotional Consent Stuff
314 (r"/subscribe", people.SubscribeHandler),
315 (r"/unsubscribe", people.UnsubscribeHandler),
316
2dac7110
MT
317 # Single-Sign-On for Discourse
318 (r"/sso/discourse", people.SSODiscourse),
689effd0 319
c7594d58 320 # Password Reset
391ede9e
MT
321 (r"/password\-reset", auth.PasswordResetInitiationHandler),
322 (r"/password\-reset/([a-z_][a-z0-9_-]{0,31})/(\w+)", auth.PasswordResetHandler),
c7594d58 323
0ed3ea5c
MT
324 # Serve any static files
325 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
326
689effd0 327 # API
66181c96 328 (r"/api/check/email", auth.APICheckEmail),
689effd0 329 (r"/api/check/uid", auth.APICheckUID),
786e9ca8 330 ] + authentication_handlers)
2cd9af74 331
181d08f3 332 # wiki.ipfire.org
c85f80e2 333 self.add_handlers(r"wiki\.([a-z]+\.dev\.)?ipfire\.org",
181d08f3
MT
334 authentication_handlers + [
335
f2cfd873 336 # Actions
b26c705a 337 (r"((?:[A-Za-z0-9\-_\/]+)?(?:.*)\.(?:\w+))/_delete", wiki.ActionDeleteHandler),
40cb87a4 338 (r"([A-Za-z0-9\-_\/]+)?/_edit", wiki.ActionEditHandler),
2901b734 339 (r"([A-Za-z0-9\-_\/]+)?/_render", wiki.ActionRenderHandler),
9db2e89f 340 (r"([A-Za-z0-9\-_\/]+)?/_(watch|unwatch)", wiki.ActionWatchHandler),
d4c68c5c 341 (r"/actions/restore", wiki.ActionRestoreHandler),
f2cfd873
MT
342 (r"/actions/upload", wiki.ActionUploadHandler),
343
f9db574a
MT
344 # Handlers
345 (r"/recent\-changes", wiki.RecentChangesHandler),
181d08f3 346 (r"/search", wiki.SearchHandler),
86368c12 347 (r"/tree", wiki.TreeHandler),
2f23c558 348 (r"/watchlist", wiki.WatchlistHandler),
f9db574a 349
f2cfd873 350 # Media
3b33319e 351 (r"([A-Za-z0-9\-_\/]+)?/_files", wiki.FilesHandler),
f2cfd873
MT
352 (r"((?!/static)(?:[A-Za-z0-9\-_\/]+)?(?:.*)\.(?:\w+))$", wiki.FileHandler),
353
0ed3ea5c
MT
354 # Serve any static files
355 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
356
f9db574a 357 # Render pages
181d08f3
MT
358 (r"([A-Za-z0-9\-_\/]+)?", wiki.PageHandler),
359 ])
360
ae0228e1 361 # ipfire.org
e65b9a6d 362 self.add_handlers(r"(.*)ipfire\.org", [
ba43a892 363 (r".*", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org" })
5cf160e0 364 ])
3add293a 365
feb02477
MT
366 logging.info("Successfully initialied application")
367
574a88c7 368 def format_country_name(self, handler, country_code):
e929ed92 369 return self.backend.get_country_name(country_code)
574a88c7 370
6eddfb50
MT
371 def format_language_name(self, handler, language):
372 _ = handler.locale.translate
373
374 if language == "de":
375 return _("German")
376 elif language == "en":
377 return _("English")
378 elif language == "es":
379 return _("Spanish")
380 elif language == "fr":
381 return _("French")
382 elif language == "it":
383 return _("Italian")
384 elif language == "nl":
385 return _("Dutch")
386 elif language == "pl":
387 return _("Polish")
388 elif language == "pt":
389 return _("Portuguese")
390 elif language == "ru":
391 return _("Russian")
392 elif language == "tr":
393 return _("Turkish")
394
395 return language
396
cc3b928d
MT
397 def format_month_name(self, handler, month):
398 _ = handler.locale.translate
399
400 if month == 1:
401 return _("January")
402 elif month == 2:
403 return _("February")
404 elif month == 3:
405 return _("March")
406 elif month == 4:
407 return _("April")
408 elif month == 5:
409 return _("May")
410 elif month == 6:
411 return _("June")
412 elif month == 7:
413 return _("July")
414 elif month == 8:
415 return _("August")
416 elif month == 9:
417 return _("September")
418 elif month == 10:
419 return _("October")
420 elif month == 11:
421 return _("November")
422 elif month == 12:
423 return _("December")
424
425 return month
401827c2 426
e96e445b
MT
427 def format_phone_number(self, handler, number):
428 if not isinstance(number, phonenumbers.PhoneNumber):
429 try:
01e73b0e 430 number = phonenumbers.parse(number, None)
e96e445b
MT
431 except phonenumbers.phonenumberutil.NumberParseException:
432 return number
c01ad253
MT
433
434 return phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
435
e96e445b
MT
436 def format_phone_number_to_e164(self, handler, number):
437 return phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.E164)
438
439 def format_phone_number_location(self, handler, number):
440 s = [
441 phonenumbers.geocoder.description_for_number(number, handler.locale.code),
442 phonenumbers.region_code_for_number(number),
443 ]
444
445 return ", ".join((e for e in s if e))