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