]> git.ipfire.org Git - ipfire.org.git/blame - src/web/__init__.py
accounts: Make path to avatar relative unless specifically asking for absolute
[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),
b01a1ee3
MT
155 (r"/users/([\w]+)", users.ShowHandler),
156
de683d7c 157 # RSS feed
f0714277 158 (r"/news.rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
7f9dbcc0
MT
159
160 # Redirect news articles to blog
d76ec66e 161 (r"/news/(.*)", handlers.NewsHandler),
de683d7c 162
45592df5 163 # Static Pages
45592df5 164 (r"/features", StaticHandler, { "template" : "features.html" }),
45592df5 165 (r"/legal", StaticHandler, { "template" : "legal.html" }),
d2000918 166 (r"/help", StaticHandler, { "template" : "help.html" }),
45592df5 167
14cd4fa8
MT
168 # Handle old pages that have moved elsewhere
169 (r"/imprint", tornado.web.RedirectHandler, { "url" : "/legal" }),
3808b871 170 (r"/(de|en)/(.*)", LangCompatHandler),
d2000918 171 (r"/support", tornado.web.RedirectHandler, { "url" : "/help"}),
37ed7c3c
MT
172
173 # Export arbitrary error pages
b22bc8e8 174 (r"/error/([45][0-9]{2})", base.ErrorHandler),
0ed3ea5c
MT
175
176 # Serve any static files
177 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
940227cb
MT
178 ])
179
34472923 180 # blog.ipfire.org - LEGACY REDIRECTION
c85f80e2 181 self.add_handlers(r"blog\.([a-z]+\.dev\.)?ipfire\.org", [
34472923
MT
182 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog" }),
183 (r"/authors/(\w+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/authors/{0}" }),
184 (r"/post/([0-9a-z\-\._]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/{0}" }),
185 (r"/tags/([0-9a-z\-\.]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/tags/{0}" }),
f0714277
MT
186
187 # RSS Feed
34472923
MT
188 (r"/feed.xml", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/feed.xml" }),
189 ])
12e5de7e 190
940227cb 191 # downloads.ipfire.org
c85f80e2 192 self.add_handlers(r"downloads\.([a-z]+\.dev\.)?ipfire\.org", [
82d4e789 193 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download" }),
450972a3 194 (r"/release/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download/{0}" }),
ed8116c7 195 (r"/(.*)", download.FileHandler),
54af860e 196 ])
940227cb
MT
197
198 # mirrors.ipfire.org
c85f80e2 199 self.add_handlers(r"mirrors\.([a-z]+\.dev\.)?ipfire\.org", [
278b3118
MT
200 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download/mirrors" }),
201 (r"/mirrors/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download/mirrors/{0}" }),
3808b871 202 ])
940227cb 203
d0d074e0 204 # planet.ipfire.org
c85f80e2 205 self.add_handlers(r"planet\.([a-z]+\.dev\.)?ipfire\.org", [
3d4ce901 206 (r"/", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/" }),
d76ec66e
MT
207 (r"/post/([A-Za-z0-9_-]+)", handlers.PlanetPostHandler),
208 (r"/user/([a-z0-9_-]+)", handlers.PlanetUserHandler),
bcc3ed4d
MT
209
210 # RSS
f0714277 211 (r"/rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
d76ec66e 212 (r"/user/([a-z0-9_-]+)/rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
f0714277 213 (r"/news.rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
3808b871 214 ])
d0d074e0 215
66862195 216 # fireinfo.ipfire.org
c85f80e2 217 self.add_handlers(r"fireinfo\.([a-z]+\.dev\.)?ipfire\.org", [
96c9bb79 218 (r"/", fireinfo.IndexHandler),
8ab37e0b 219
dc96f754
MT
220 # Admin
221 (r"/admin", fireinfo.AdminIndexHandler),
222
8ab37e0b
MT
223 # Vendors
224 (r"/vendors", fireinfo.VendorsHandler),
225 (r"/vendors/(pci|usb)/([0-9a-f]{4})", fireinfo.VendorHandler),
66862195 226
1e3b2aad 227 # Driver
0cd21a36 228 (r"/drivers/(.*)", fireinfo.DriverDetail),
1e3b2aad 229
66862195 230 # Show profiles
96c9bb79 231 (r"/profile/random", fireinfo.RandomProfileHandler),
b84b407f 232 (r"/profile/([a-z0-9]{40})", fireinfo.ProfileHandler),
91a446f0 233
ed2e3c1f 234 # Stats
19518d6e 235 (r"/processors", fireinfo.ProcessorsHandler),
ed2e3c1f
MT
236 (r"/releases", fireinfo.ReleasesHandler),
237
19518d6e 238 # Send profiles
96c9bb79 239 (r"/send/([a-z0-9]+)", fireinfo.ProfileSendHandler),
0ed3ea5c
MT
240
241 # Serve any static files
242 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
dc96f754 243 ] + authentication_handlers)
5cf160e0 244
c37ec602 245 # i-use.ipfire.org
c85f80e2 246 self.add_handlers(r"i-use\.([a-z]+\.dev\.)?ipfire\.org", [
e2f2865d 247 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/" }),
395c1ac0 248 (r"/profile/([a-f0-9]{40})/([0-9]+).png", iuse.ImageHandler),
c37ec602
MT
249 ])
250
8e2e1261
MT
251 # boot.ipfire.org
252 BOOT_STATIC_PATH = os.path.join(self.settings["static_path"], "netboot")
c85f80e2 253 self.add_handlers(r"boot\.([a-z]+\.dev\.)?ipfire\.org", [
f301d952 254 (r"/", tornado.web.RedirectHandler, { "url" : "https://wiki.ipfire.org/installation/pxe" }),
8e2e1261
MT
255
256 # Configurations
f301d952
MT
257 (r"/premenu.cfg", boot.PremenuCfgHandler),
258 (r"/menu.gpxe", boot.MenuGPXEHandler),
259 (r"/menu.cfg", boot.MenuCfgHandler),
8e2e1261
MT
260
261 # Static files
37b5c0cf 262 (r"/(boot\.png|pxelinux\.0|menu\.c32|vesamenu\.c32)",
8e2e1261
MT
263 tornado.web.StaticFileHandler, { "path" : BOOT_STATIC_PATH }),
264 ])
265
60024cc8 266 # nopaste.ipfire.org
c85f80e2 267 self.add_handlers(r"nopaste\.([a-z]+\.dev\.)?ipfire\.org", [
a41085fb
MT
268 (r"/", nopaste.CreateHandler),
269 (r"/raw/(.*)", nopaste.RawHandler),
270 (r"/view/(.*)", nopaste.ViewHandler),
0ed3ea5c
MT
271
272 # Serve any static files
273 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
3808b871 274 ] + authentication_handlers)
60024cc8 275
f5b01fc2 276 # location.ipfire.org
c85f80e2 277 self.add_handlers(r"location\.([a-z]+\.dev\.)?ipfire\.org", [
f5b01fc2 278 (r"/", location.IndexHandler),
9c83876f 279 (r"/download", StaticHandler, { "template" : "../location/download.html" }),
55eea098 280 (r"/how\-to\-use", StaticHandler, { "template" : "../location/how-to-use.html" }),
2517822e 281 (r"/lookup/(.+)/blacklists", location.BlacklistsHandler),
f5b01fc2 282 (r"/lookup/(.+)", location.LookupHandler),
0ed3ea5c
MT
283
284 # Serve any static files
285 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
f5b01fc2
MT
286 ])
287
9068dba1 288 # geoip.ipfire.org
c85f80e2 289 self.add_handlers(r"geoip\.([a-z]+\.dev\.)?ipfire\.org", [
f5b01fc2 290 (r"/", tornado.web.RedirectHandler, { "url" : "https://location.ipfire.org/" }),
3808b871 291 ])
9068dba1 292
66862195 293 # talk.ipfire.org
c85f80e2 294 self.add_handlers(r"talk\.([a-z]+\.dev\.)?ipfire\.org", [
786e9ca8
MT
295 (r"/", tornado.web.RedirectHandler, { "url" : "https://people.ipfire.org/" }),
296 ])
66862195 297
03706893 298 # people.ipfire.org
c85f80e2 299 self.add_handlers(r"people\.([a-z]+\.dev\.)?ipfire\.org", [
786e9ca8 300 (r"/", people.IndexHandler),
2c65e17c 301 (r"/activate/([a-z_][a-z0-9_-]{0,31})/(\w+)", auth.ActivateHandler),
30aeccdb 302 (r"/conferences", people.ConferencesHandler),
18b13823 303 (r"/groups", people.GroupsHandler),
736e7544 304 (r"/groups/([a-z_][a-z0-9_-]{0,31})", people.GroupHandler),
f32dd17f 305 (r"/register", auth.RegisterHandler),
786e9ca8 306 (r"/search", people.SearchHandler),
2c65e17c
MT
307 (r"/users/([a-z_][a-z0-9_-]{0,31})\.jpg", people.AvatarHandler),
308 (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),
309 (r"/users/([a-z_][a-z0-9_-]{0,31})/calls(?:/(\d{4}-\d{2}-\d{2}))?", people.CallsHandler),
310 (r"/users/([a-z_][a-z0-9_-]{0,31})/edit", people.UserEditHandler),
311 (r"/users/([a-z_][a-z0-9_-]{0,31})/passwd", people.UserPasswdHandler),
312 (r"/users/([a-z_][a-z0-9_-]{0,31})/sip", people.SIPHandler),
2dac7110 313
92c4b559
MT
314 # Promotional Consent Stuff
315 (r"/subscribe", people.SubscribeHandler),
316 (r"/unsubscribe", people.UnsubscribeHandler),
317
2dac7110
MT
318 # Single-Sign-On for Discourse
319 (r"/sso/discourse", people.SSODiscourse),
689effd0 320
c7594d58 321 # Password Reset
391ede9e
MT
322 (r"/password\-reset", auth.PasswordResetInitiationHandler),
323 (r"/password\-reset/([a-z_][a-z0-9_-]{0,31})/(\w+)", auth.PasswordResetHandler),
c7594d58 324
226d2676
MT
325 # Stats
326 (r"/stats", people.StatsHandler),
327
0ed3ea5c
MT
328 # Serve any static files
329 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
330
689effd0 331 # API
66181c96 332 (r"/api/check/email", auth.APICheckEmail),
689effd0 333 (r"/api/check/uid", auth.APICheckUID),
786e9ca8 334 ] + authentication_handlers)
2cd9af74 335
181d08f3 336 # wiki.ipfire.org
c85f80e2 337 self.add_handlers(r"wiki\.([a-z]+\.dev\.)?ipfire\.org",
181d08f3
MT
338 authentication_handlers + [
339
f2cfd873 340 # Actions
b26c705a 341 (r"((?:[A-Za-z0-9\-_\/]+)?(?:.*)\.(?:\w+))/_delete", wiki.ActionDeleteHandler),
40cb87a4 342 (r"([A-Za-z0-9\-_\/]+)?/_edit", wiki.ActionEditHandler),
2901b734 343 (r"([A-Za-z0-9\-_\/]+)?/_render", wiki.ActionRenderHandler),
9db2e89f 344 (r"([A-Za-z0-9\-_\/]+)?/_(watch|unwatch)", wiki.ActionWatchHandler),
d4c68c5c 345 (r"/actions/restore", wiki.ActionRestoreHandler),
f2cfd873
MT
346 (r"/actions/upload", wiki.ActionUploadHandler),
347
f9db574a
MT
348 # Handlers
349 (r"/recent\-changes", wiki.RecentChangesHandler),
181d08f3 350 (r"/search", wiki.SearchHandler),
86368c12 351 (r"/tree", wiki.TreeHandler),
2f23c558 352 (r"/watchlist", wiki.WatchlistHandler),
f9db574a 353
f2cfd873 354 # Media
3b33319e 355 (r"([A-Za-z0-9\-_\/]+)?/_files", wiki.FilesHandler),
f2cfd873
MT
356 (r"((?!/static)(?:[A-Za-z0-9\-_\/]+)?(?:.*)\.(?:\w+))$", wiki.FileHandler),
357
0ed3ea5c
MT
358 # Serve any static files
359 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
360
f9db574a 361 # Render pages
181d08f3
MT
362 (r"([A-Za-z0-9\-_\/]+)?", wiki.PageHandler),
363 ])
364
ae0228e1 365 # ipfire.org
e65b9a6d 366 self.add_handlers(r"(.*)ipfire\.org", [
ba43a892 367 (r".*", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org" })
5cf160e0 368 ])
3add293a 369
feb02477
MT
370 logging.info("Successfully initialied application")
371
574a88c7 372 def format_country_name(self, handler, country_code):
e929ed92 373 return self.backend.get_country_name(country_code)
574a88c7 374
6eddfb50
MT
375 def format_language_name(self, handler, language):
376 _ = handler.locale.translate
377
378 if language == "de":
379 return _("German")
380 elif language == "en":
381 return _("English")
382 elif language == "es":
383 return _("Spanish")
384 elif language == "fr":
385 return _("French")
386 elif language == "it":
387 return _("Italian")
388 elif language == "nl":
389 return _("Dutch")
390 elif language == "pl":
391 return _("Polish")
392 elif language == "pt":
393 return _("Portuguese")
394 elif language == "ru":
395 return _("Russian")
396 elif language == "tr":
397 return _("Turkish")
398
399 return language
400
cc3b928d
MT
401 def format_month_name(self, handler, month):
402 _ = handler.locale.translate
403
404 if month == 1:
405 return _("January")
406 elif month == 2:
407 return _("February")
408 elif month == 3:
409 return _("March")
410 elif month == 4:
411 return _("April")
412 elif month == 5:
413 return _("May")
414 elif month == 6:
415 return _("June")
416 elif month == 7:
417 return _("July")
418 elif month == 8:
419 return _("August")
420 elif month == 9:
421 return _("September")
422 elif month == 10:
423 return _("October")
424 elif month == 11:
425 return _("November")
426 elif month == 12:
427 return _("December")
428
429 return month
401827c2 430
e96e445b
MT
431 def format_phone_number(self, handler, number):
432 if not isinstance(number, phonenumbers.PhoneNumber):
433 try:
01e73b0e 434 number = phonenumbers.parse(number, None)
e96e445b
MT
435 except phonenumbers.phonenumberutil.NumberParseException:
436 return number
c01ad253
MT
437
438 return phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
439
e96e445b
MT
440 def format_phone_number_to_e164(self, handler, number):
441 return phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.E164)
442
443 def format_phone_number_location(self, handler, number):
444 s = [
445 phonenumbers.geocoder.description_for_number(number, handler.locale.code),
446 phonenumbers.region_code_for_number(number),
447 ]
448
449 return ", ".join((e for e in s if e))