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