]> git.ipfire.org Git - ipfire.org.git/blame - src/web/__init__.py
lists: Implement some basic code to talk to Mailman
[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
97e15cf6 25from . import lists
f5b01fc2 26from . import location
a41085fb 27from . import nopaste
df6180a5 28from . import ui_modules
b01a1ee3 29from . import users
4235ba55 30from . import voip
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" : {
5806d6fc
MT
63 # Auth
64 "Password" : auth.PasswordModule,
65
f5b01fc2 66 # Blog
7e64f6a3
MT
67 "BlogHistoryNavigation": blog.HistoryNavigationModule,
68 "BlogList" : blog.ListModule,
f91dfcc7
MT
69 "BlogPost" : blog.PostModule,
70
93feb275
MT
71 # Boot
72 "BootMenuConfig" : boot.MenuConfigModule,
73 "BootMenuHeader" : boot.MenuHeaderModule,
74 "BootMenuSeparator" : boot.MenuSeparatorModule,
75
cf59466c 76 # Docs
739fff76 77 "DocsDiff" : docs.DiffModule,
cf59466c 78 "DocsHeader" : docs.HeaderModule,
d25f886f 79 "DocsList" : docs.ListModule,
cf59466c 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
4235ba55 92 # VoIP
214a68a0 93 "VoIPConferences" : voip.ConferencesModule,
00465786
MT
94 "VoIPOutboundRegistrations" :
95 voip.OutboundRegistrationsModule,
8e93325b 96 "VoIPQueues" : voip.QueuesModule,
4235ba55
MT
97 "VoIPRegistrations" : voip.RegistrationsModule,
98
eabe6b8d 99 # Misc
6563eb49 100 "ChristmasBanner" : ui_modules.ChristmasBannerModule,
6c6de80a 101 "IPFireLogo" : ui_modules.IPFireLogoModule,
1c4522dc 102 "Markdown" : ui_modules.MarkdownModule,
eabe6b8d
MT
103 "Map" : ui_modules.MapModule,
104 "ProgressBar" : ui_modules.ProgressBarModule,
81675874 105 },
3403dc5e
MT
106
107 # Call this when a page wasn't found
b22bc8e8 108 "default_handler_class" : base.NotFoundHandler,
9ed02e3b 109 }
9068dba1 110 settings.update(kwargs)
5cf160e0 111
ae0228e1
MT
112 tornado.web.Application.__init__(self, **settings)
113
66862195 114 authentication_handlers = [
08df6527
MT
115 (r"/login", auth.LoginHandler),
116 (r"/logout", auth.LogoutHandler),
66862195
MT
117 ]
118
c85f80e2 119 self.add_handlers(r"(www\.)?([a-z]+\.dev\.)?ipfire\.org", [
940227cb
MT
120 # Entry site that lead the user to index
121 (r"/", IndexHandler),
940227cb 122
8505c8cd
MT
123 # Authentication
124 (r"/login", auth.LoginHandler),
125 (r"/logout", auth.LogoutHandler),
126 (r"/register", auth.RegisterHandler),
42c7cc66 127 (r"/activate/([a-z_][a-z0-9_-]{0,31})/(\w+)", auth.ActivateHandler),
8505c8cd 128
34472923
MT
129 # Blog
130 (r"/blog", blog.IndexHandler),
34472923
MT
131 (r"/blog/drafts", blog.DraftsHandler),
132 (r"/blog/feed.xml", blog.FeedHandler),
34472923 133 (r"/blog/tags/([0-9a-z\-\.]+)", blog.TagHandler),
4d657f4f 134 (r"/blog/write", blog.WriteHandler),
feb245e0 135 (r"/blog/years/([0-9]{4})", blog.YearHandler),
34472923
MT
136 (r"/blog/([0-9a-z\-\._]+)", blog.PostHandler),
137 (r"/blog/([0-9a-z\-\._]+)/delete", blog.DeleteHandler),
138 (r"/blog/([0-9a-z\-\._]+)/edit", blog.EditHandler),
139 (r"/blog/([0-9a-z\-\._]+)/publish", blog.PublishHandler),
56801afb 140 (r"/blog/([0-9a-z\-\._]+)/debug/email", blog.DebugEmailHandler),
34472923 141
1958a22b 142 # Docs
5f0d294e 143 (r"/docs/recent\-changes", docs.RecentChangesHandler),
0ce8cc32 144 (r"/docs/search", docs.SearchHandler),
350f391e 145 (r"/docs/tree", docs.TreeHandler),
16619e57 146 (r"/docs/watchlist", docs.WatchlistHandler),
bb998aca 147 (r"/docs/_restore", docs.RestoreHandler),
26ade731 148 (r"/docs/_upload", docs.UploadHandler),
a7342d24
MT
149 (r"/docs(?:/([A-Za-z0-9\-_\/]+))?/_edit", docs.EditHandler),
150 (r"/docs(?:/([A-Za-z0-9\-_\/]+))?/_render", docs.RenderHandler),
151 (r"/docs(?:/([A-Za-z0-9\-_\/]+))?/_(watch|unwatch)", docs.WatchHandler),
16510618 152 (r"/docs/((?:[A-Za-z0-9\-_\/]+)?(?:.*)\.(?:\w+))/_delete", docs.DeleteFileHandler),
4a1bfdd5 153 (r"/docs((?:[A-Za-z0-9\-_\/]+)?(?:.*)\.(?:\w+))$", docs.FileHandler),
a7342d24
MT
154 (r"/docs(?:/([A-Za-z0-9\-_\/]+))?/_files", docs.FilesHandler),
155 (r"/docs(?:/([A-Za-z0-9\-_\/]+))?", docs.PageHandler),
1958a22b 156
aec63a26
MT
157 # Downloads
158 (r"/downloads", downloads.IndexHandler),
159 (r"/downloads/mirrors", downloads.MirrorsHandler),
160 (r"/downloads/thank-you", downloads.ThankYouHandler),
161 (r"/downloads/([0-9a-z\-\.]+)", downloads.ReleaseHandler),
162
e64ce07e 163 # Donate
c7bcb9ca
MT
164 (r"/donate", donate.DonateHandler),
165 (r"/donate/thank-you", donate.ThankYouHandler),
166 (r"/donate/error", donate.ErrorHandler),
8d48f4ef 167
97e15cf6
MT
168 # Lists
169 (r"/lists", lists.IndexHandler),
170
8066a1e7
MT
171 # Password Reset
172 (r"/password\-reset", auth.PasswordResetInitiationHandler),
173 (r"/password\-reset/([a-z_][a-z0-9_-]{0,31})/(\w+)", auth.PasswordResetHandler),
174
d9f7b6e5
MT
175 # Projects
176 (r"/projects/location", location.IndexHandler),
177 (r"/projects/location/download", StaticHandler, { "template" : "../location/download.html" }),
178 (r"/projects/location/how\-to\-use", StaticHandler, { "template" : "../location/how-to-use.html" }),
d9f7b6e5
MT
179 (r"/projects/location/lookup/(.+)", location.LookupHandler),
180
2fe1d960
MT
181 # Single-Sign-On for Discourse
182 (r"/sso/discourse", auth.SSODiscourse),
183
f2c38da0
MT
184 # User Groups
185 (r"/users/groups", users.GroupIndexHandler),
186 (r"/users/groups/([a-z_][a-z0-9_-]{0,31})", users.GroupShowHandler),
187
b01a1ee3 188 # Users
beb13102 189 (r"/users", users.IndexHandler),
53b2117f
MT
190 (r"/users/([a-z_][a-z0-9_-]{0,31})", users.ShowHandler),
191 (r"/users/([a-z_][a-z0-9_-]{0,31})\.jpg", users.AvatarHandler),
1cd4d7d3 192 (r"/users/([a-z_][a-z0-9_-]{0,31})/delete", users.DeleteHandler),
3c986f14 193 (r"/users/([a-z_][a-z0-9_-]{0,31})/edit", users.EditHandler),
e4d2f51f 194 (r"/users/([a-z_][a-z0-9_-]{0,31})/passwd", users.PasswdHandler),
b01a1ee3 195
bb440bad
MT
196 # Promotional Consent Stuff
197 (r"/subscribe", users.SubscribeHandler),
198 (r"/unsubscribe", users.UnsubscribeHandler),
199
4235ba55
MT
200 # VoIP
201 (r"/voip", voip.IndexHandler),
202
45592df5 203 # Static Pages
8ea3eaa2 204 (r"/about", StaticHandler, { "template" : "about.html" }),
45592df5 205 (r"/legal", StaticHandler, { "template" : "legal.html" }),
d2000918 206 (r"/help", StaticHandler, { "template" : "help.html" }),
d1ec64e1 207 (r"/sitemap", StaticHandler, { "template" : "sitemap.html" }),
45592df5 208
86d86819
MT
209 # API
210 (r"/api/check/email", auth.APICheckEmail),
211 (r"/api/check/uid", auth.APICheckUID),
212
14cd4fa8 213 # Handle old pages that have moved elsewhere
1f153396 214 (r"/blog/authors/(\w+)", tornado.web.RedirectHandler, { "url" : "/users/{0}" }),
7fa7d38d
MT
215 (r"/donation", tornado.web.RedirectHandler, { "url" : "/donate" }),
216 (r"/download", tornado.web.RedirectHandler, { "url" : "/downloads" }),
217 (r"/download/([0-9a-z\-\.]+)", tornado.web.RedirectHandler, { "url" : "/downloads/{0}" }),
85c977e2 218 (r"/features", tornado.web.RedirectHandler, { "url" : "/about" }),
14cd4fa8 219 (r"/imprint", tornado.web.RedirectHandler, { "url" : "/legal" }),
7fa7d38d
MT
220 (r"/news.rss", tornado.web.RedirectHandler, { "url" : "/blog/feed.xml" }),
221 (r"/news/(.*)", tornado.web.RedirectHandler, { "url" : "/blog/{0}" }),
d2000918 222 (r"/support", tornado.web.RedirectHandler, { "url" : "/help"}),
7fa7d38d 223 (r"/(de|en)/(.*)", tornado.web.RedirectHandler, { "url" : "/{0}"}),
37ed7c3c
MT
224
225 # Export arbitrary error pages
b22bc8e8 226 (r"/error/([45][0-9]{2})", base.ErrorHandler),
0ed3ea5c
MT
227
228 # Serve any static files
229 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
940227cb
MT
230 ])
231
34472923 232 # blog.ipfire.org - LEGACY REDIRECTION
c85f80e2 233 self.add_handlers(r"blog\.([a-z]+\.dev\.)?ipfire\.org", [
34472923
MT
234 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog" }),
235 (r"/authors/(\w+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/authors/{0}" }),
236 (r"/post/([0-9a-z\-\._]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/{0}" }),
237 (r"/tags/([0-9a-z\-\.]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/tags/{0}" }),
f0714277
MT
238
239 # RSS Feed
34472923
MT
240 (r"/feed.xml", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/feed.xml" }),
241 ])
12e5de7e 242
940227cb 243 # downloads.ipfire.org
c85f80e2 244 self.add_handlers(r"downloads\.([a-z]+\.dev\.)?ipfire\.org", [
82d4e789 245 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download" }),
450972a3 246 (r"/release/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download/{0}" }),
aec63a26 247 (r"/(.*)", downloads.FileHandler),
54af860e 248 ])
940227cb
MT
249
250 # mirrors.ipfire.org
c85f80e2 251 self.add_handlers(r"mirrors\.([a-z]+\.dev\.)?ipfire\.org", [
278b3118
MT
252 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download/mirrors" }),
253 (r"/mirrors/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/download/mirrors/{0}" }),
3808b871 254 ])
940227cb 255
d0d074e0 256 # planet.ipfire.org
c85f80e2 257 self.add_handlers(r"planet\.([a-z]+\.dev\.)?ipfire\.org", [
3d4ce901 258 (r"/", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/" }),
7fa7d38d
MT
259 (r"/post/([A-Za-z0-9_-]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/{0}" }),
260 (r"/user/([a-z0-9_-]+)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/blog/authors/{0}" }),
bcc3ed4d
MT
261
262 # RSS
f0714277 263 (r"/rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
d76ec66e 264 (r"/user/([a-z0-9_-]+)/rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
f0714277 265 (r"/news.rss", tornado.web.RedirectHandler, { "url" : "https://blog.ipfire.org/feed.xml" }),
3808b871 266 ])
d0d074e0 267
66862195 268 # fireinfo.ipfire.org
c85f80e2 269 self.add_handlers(r"fireinfo\.([a-z]+\.dev\.)?ipfire\.org", [
96c9bb79 270 (r"/", fireinfo.IndexHandler),
8ab37e0b 271
dc96f754
MT
272 # Admin
273 (r"/admin", fireinfo.AdminIndexHandler),
274
8ab37e0b
MT
275 # Vendors
276 (r"/vendors", fireinfo.VendorsHandler),
277 (r"/vendors/(pci|usb)/([0-9a-f]{4})", fireinfo.VendorHandler),
66862195 278
1e3b2aad 279 # Driver
0cd21a36 280 (r"/drivers/(.*)", fireinfo.DriverDetail),
1e3b2aad 281
66862195 282 # Show profiles
96c9bb79 283 (r"/profile/random", fireinfo.RandomProfileHandler),
b84b407f 284 (r"/profile/([a-z0-9]{40})", fireinfo.ProfileHandler),
91a446f0 285
ed2e3c1f 286 # Stats
19518d6e 287 (r"/processors", fireinfo.ProcessorsHandler),
ed2e3c1f
MT
288 (r"/releases", fireinfo.ReleasesHandler),
289
19518d6e 290 # Send profiles
96c9bb79 291 (r"/send/([a-z0-9]+)", fireinfo.ProfileSendHandler),
0ed3ea5c
MT
292
293 # Serve any static files
294 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
dc96f754 295 ] + authentication_handlers)
5cf160e0 296
c37ec602 297 # i-use.ipfire.org
c85f80e2 298 self.add_handlers(r"i-use\.([a-z]+\.dev\.)?ipfire\.org", [
e2f2865d 299 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/" }),
395c1ac0 300 (r"/profile/([a-f0-9]{40})/([0-9]+).png", iuse.ImageHandler),
c37ec602
MT
301 ])
302
8e2e1261
MT
303 # boot.ipfire.org
304 BOOT_STATIC_PATH = os.path.join(self.settings["static_path"], "netboot")
c85f80e2 305 self.add_handlers(r"boot\.([a-z]+\.dev\.)?ipfire\.org", [
f301d952 306 (r"/", tornado.web.RedirectHandler, { "url" : "https://wiki.ipfire.org/installation/pxe" }),
8e2e1261
MT
307
308 # Configurations
f301d952
MT
309 (r"/premenu.cfg", boot.PremenuCfgHandler),
310 (r"/menu.gpxe", boot.MenuGPXEHandler),
311 (r"/menu.cfg", boot.MenuCfgHandler),
8e2e1261
MT
312
313 # Static files
37b5c0cf 314 (r"/(boot\.png|pxelinux\.0|menu\.c32|vesamenu\.c32)",
8e2e1261
MT
315 tornado.web.StaticFileHandler, { "path" : BOOT_STATIC_PATH }),
316 ])
317
60024cc8 318 # nopaste.ipfire.org
c85f80e2 319 self.add_handlers(r"nopaste\.([a-z]+\.dev\.)?ipfire\.org", [
a41085fb
MT
320 (r"/", nopaste.CreateHandler),
321 (r"/raw/(.*)", nopaste.RawHandler),
322 (r"/view/(.*)", nopaste.ViewHandler),
0ed3ea5c
MT
323
324 # Serve any static files
325 (r"/static/(.*)", tornado.web.StaticFileHandler, { "path" : self.settings.get("static_path") }),
3808b871 326 ] + authentication_handlers)
60024cc8 327
f5b01fc2 328 # location.ipfire.org
c85f80e2 329 self.add_handlers(r"location\.([a-z]+\.dev\.)?ipfire\.org", [
d9f7b6e5 330 (r"/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/projects/location/{0}" }),
f5b01fc2
MT
331 ])
332
9068dba1 333 # geoip.ipfire.org
c85f80e2 334 self.add_handlers(r"geoip\.([a-z]+\.dev\.)?ipfire\.org", [
f5b01fc2 335 (r"/", tornado.web.RedirectHandler, { "url" : "https://location.ipfire.org/" }),
3808b871 336 ])
9068dba1 337
66862195 338 # talk.ipfire.org
c85f80e2 339 self.add_handlers(r"talk\.([a-z]+\.dev\.)?ipfire\.org", [
786e9ca8
MT
340 (r"/", tornado.web.RedirectHandler, { "url" : "https://people.ipfire.org/" }),
341 ])
66862195 342
03706893 343 # people.ipfire.org
c85f80e2 344 self.add_handlers(r"people\.([a-z]+\.dev\.)?ipfire\.org", [
b6026905
MT
345 (r"/", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/users" }),
346 (r"/register", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/register" }),
347 (r"/users", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/users" }),
348 (r"/users/([a-z_][a-z0-9_-]{0,31})", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/users/{0}" }),
349 (r"/users/([a-z_][a-z0-9_-]{0,31})\.jpg", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/users/{0}.jpg" }),
350 ])
2cd9af74 351
181d08f3 352 # wiki.ipfire.org
9741abf5
MT
353 self.add_handlers(r"wiki\.([a-z]+\.dev\.)?ipfire\.org", [
354 (r"/(.*)", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org/docs/{0}" }),
181d08f3
MT
355 ])
356
ae0228e1 357 # ipfire.org
e65b9a6d 358 self.add_handlers(r"(.*)ipfire\.org", [
ba43a892 359 (r".*", tornado.web.RedirectHandler, { "url" : "https://www.ipfire.org" })
5cf160e0 360 ])
3add293a 361
feb02477
MT
362 logging.info("Successfully initialied application")
363
574a88c7 364 def format_country_name(self, handler, country_code):
e929ed92 365 return self.backend.get_country_name(country_code)
574a88c7 366
6eddfb50
MT
367 def format_language_name(self, handler, language):
368 _ = handler.locale.translate
369
370 if language == "de":
371 return _("German")
372 elif language == "en":
373 return _("English")
374 elif language == "es":
375 return _("Spanish")
376 elif language == "fr":
377 return _("French")
378 elif language == "it":
379 return _("Italian")
380 elif language == "nl":
381 return _("Dutch")
382 elif language == "pl":
383 return _("Polish")
384 elif language == "pt":
385 return _("Portuguese")
386 elif language == "ru":
387 return _("Russian")
388 elif language == "tr":
389 return _("Turkish")
390
391 return language
392
cc3b928d
MT
393 def format_month_name(self, handler, month):
394 _ = handler.locale.translate
395
396 if month == 1:
397 return _("January")
398 elif month == 2:
399 return _("February")
400 elif month == 3:
401 return _("March")
402 elif month == 4:
403 return _("April")
404 elif month == 5:
405 return _("May")
406 elif month == 6:
407 return _("June")
408 elif month == 7:
409 return _("July")
410 elif month == 8:
411 return _("August")
412 elif month == 9:
413 return _("September")
414 elif month == 10:
415 return _("October")
416 elif month == 11:
417 return _("November")
418 elif month == 12:
419 return _("December")
420
421 return month
401827c2 422
e96e445b
MT
423 def format_phone_number(self, handler, number):
424 if not isinstance(number, phonenumbers.PhoneNumber):
425 try:
01e73b0e 426 number = phonenumbers.parse(number, None)
e96e445b
MT
427 except phonenumbers.phonenumberutil.NumberParseException:
428 return number
c01ad253
MT
429
430 return phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
431
e96e445b
MT
432 def format_phone_number_to_e164(self, handler, number):
433 return phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.E164)
434
435 def format_phone_number_location(self, handler, number):
436 s = [
437 phonenumbers.geocoder.description_for_number(number, handler.locale.code),
438 phonenumbers.region_code_for_number(number),
439 ]
440
441 return ", ".join((e for e in s if e))