]> git.ipfire.org Git - pbs.git/blob - src/web/__init__.py
daedd8bcc3014f29d2e2dec9180f3c6beaa61dad
[pbs.git] / src / web / __init__.py
1 #!/usr/bin/python
2 # encoding: utf-8
3
4 import datetime
5 import logging
6 import tornado.locale
7 import tornado.web
8 import urllib.parse
9
10 from .. import Backend
11 from ..constants import *
12 from .. import misc
13
14 # Import all handlers
15 from . import auth
16 from . import bugs
17 from . import builders
18 from . import builds
19 from . import debuginfo
20 from . import distributions
21 from . import errors
22 from . import events
23 from . import jobs
24 from . import mirrors
25 from . import monitorings
26 from . import packages
27 from . import repos
28 from . import search
29 from . import sources
30 from . import uploads
31 from . import users
32 from .handlers import *
33
34 from . import ui_modules
35
36 class Application(tornado.web.Application):
37 def __init__(self, **kwargs):
38 settings = dict(
39 login_url = "/login",
40 template_path = TEMPLATESDIR,
41 static_path = STATICDIR,
42 ui_modules = {
43 "Highlight" : ui_modules.HighlightModule,
44 "Text" : ui_modules.TextModule,
45
46 # Bugs
47 "BugsList" : bugs.ListModule,
48
49 # Builds
50 "BuildsList" : builds.ListModule,
51 "BuildWatchers" : builds.WatchersModule,
52
53 # BuildGroups
54 "BuildGroupList" : builds.GroupListModule,
55
56 # Builders
57 "BuilderStats" : builders.StatsModule,
58
59 # Distros
60 "DistrosList" : distributions.ListModule,
61
62 # Events
63 "EventsList" : events.ListModule,
64 "EventBuildComment" : events.BuildCommentModule,
65 "EventSystemMessage" : events.SystemMessageModule,
66 "EventUserMessage" : events.UserMessageModule,
67
68 # Jobs
69 "JobsList" : jobs.ListModule,
70 "JobsLogStream" : jobs.LogStreamModule,
71 "JobsQueue" : jobs.QueueModule,
72
73 # Mirrors
74 "MirrorsList" : mirrors.ListModule,
75
76 # Monitorings
77 "MonitoringsReleasesList" : monitorings.ReleasesListModule,
78
79 # Packages
80 "PackageInfo" : packages.InfoModule,
81 "PackageDependencies": packages.DependenciesModule,
82
83 # Releases
84 "ReleasesList" : distributions.ReleasesListModule,
85
86 # Repositories
87 "ReposList" : repos.ListModule,
88
89 # Sources
90 "SourcesList" : sources.ListModule,
91 "CommitsList" : sources.CommitsListModule,
92
93 # Users
94 "UsersList" : users.ListModule,
95 "UserPushSubscribeButton" : users.PushSubscribeButton,
96
97 "CommitMessage" : ui_modules.CommitMessageModule,
98 "LinkToUser" : ui_modules.LinkToUserModule,
99 "PackageFilesTable" : ui_modules.PackageFilesTableModule,
100 },
101 ui_methods = {
102 "extract_hostname" : self.extract_hostname,
103 "format_time" : self.format_time,
104 "group" : self.group,
105 "make_url" : self.make_url,
106 },
107 xsrf_cookies = True,
108 )
109 settings.update(kwargs)
110
111 # Load translations.
112 tornado.locale.load_gettext_translations(LOCALEDIR, PACKAGE_NAME)
113
114 tornado.web.Application.__init__(self, [
115 # Entry site that lead the user to index
116 (r"/", IndexHandler),
117
118 # Authentication
119 (r"/login", auth.LoginHandler),
120 (r"/logout", auth.LogoutHandler),
121
122 # Users
123 (r"/users", users.IndexHandler),
124 (r"/users/(\w+)", users.ShowHandler),
125 (r"/users/(\w+)/delete", users.DeleteHandler),
126 (r"/users/(\w+)/edit", users.EditHandler),
127 (r"/users/push/subscribe", users.PushSubscribeHandler),
128
129 # User Repositories
130 (r"/users/(\w+)/repos/create", repos.CreateCustomHandler),
131 (r"/users/(?P<user_slug>\w+)/repos/(?P<distro_slug>[A-Za-z0-9\-\.]+)/(?P<repo_slug>[A-Za-z0-9\-]+)",
132 repos.ShowHandler),
133 (r"/users/(?P<user_slug>\w+)/repos/(?P<distro_slug>[A-Za-z0-9\-\.]+)/(?P<repo_slug>[A-Za-z0-9\-]+)\.repo",
134 repos.ConfigHandler),
135 (r"/users/(?P<user_slug>\w+)/repos/(?P<distro_slug>[A-Za-z0-9\-\.]+)/(?P<repo_slug>[A-Za-z0-9\-]+)/builds",
136 repos.BuildsHandler),
137 (r"/users/(?P<user_slug>\w+)/repos/(?P<distro_slug>[A-Za-z0-9\-\.]+)/(?P<repo_slug>[A-Za-z0-9\-]+)/delete",
138 repos.DeleteHandler),
139 (r"/users/(?P<user_slug>\w+)/repos/(?P<distro_slug>[A-Za-z0-9\-\.]+)/(?P<repo_slug>[A-Za-z0-9\-]+)/edit",
140 repos.EditHandler),
141 (r"/users/(?P<user_slug>\w+)/repos/(?P<distro_slug>[A-Za-z0-9\-\.]+)/(?P<repo_slug>[A-Za-z0-9\-]+)/mirrorlist",
142 repos.MirrorlistHandler),
143 (r"/users/(?P<user_slug>\w+)/repos/(?P<distro_slug>[A-Za-z0-9\-\.]+)/(?P<repo_slug>[A-Za-z0-9\-]+)/sources/(?P<source_slug>[A-Za-z0-9\-]+)",
144 sources.ShowHandler),
145 (r"/users/(?P<user_slug>\w+)/repos/(?P<distro_slug>[A-Za-z0-9\-\.]+)/(?P<repo_slug>[A-Za-z0-9\-]+)/sources/(?P<source_slug>[A-Za-z0-9\-]+)/commits/(?P<commit_slug>[a-f0-9]{40})",
146 sources.ShowCommitHandler),
147
148 # Packages
149 (r"/packages", packages.IndexHandler),
150 (r"/packages/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})", packages.ShowHandler),
151 (r"/packages/([\w\-\+]+)", packages.NameHandler),
152 (r"/packages/([\w\-\+]+)/builds", packages.NameBuildsHandler),
153 (r"/packages/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/download(.*)",
154 packages.FileDownloadHandler),
155 (r"/packages/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/view(.*)",
156 packages.FileViewHandler),
157
158 # Builds
159 (r"/builds", builds.IndexHandler),
160 (r"/builds/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})", builds.ShowHandler),
161 (r"/builds/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/approve", builds.ApproveHandler),
162 (r"/builds/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/bug", builds.BugHandler),
163 (r"/builds/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/clone", builds.CloneHandler),
164 (r"/builds/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/comment", builds.CommentHandler),
165 (r"/builds/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/delete", builds.DeleteHandler),
166 (r"/builds/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/repos/add", builds.ReposAddHandler),
167 (r"/builds/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/repos/remove", builds.ReposRemoveHandler),
168 (r"/builds/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/watch", builds.WatchHandler),
169 (r"/builds/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/unwatch", builds.UnwatchHandler),
170
171 (r"/api/v1/builds", builds.APIv1IndexHandler),
172
173 # Build Groups
174 (r"/builds/groups/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})", builds.GroupShowHandler),
175
176 # Jobs
177 (r"/jobs", jobs.IndexHandler),
178 (r"/jobs/queue", jobs.QueueHandler),
179 (r"/jobs/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/abort", jobs.AbortHandler),
180 (r"/jobs/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/log", jobs.LogHandler),
181 (r"/jobs/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/retry", jobs.RetryHandler),
182 (r"/api/v1/jobs/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})",
183 jobs.APIv1ControlHandler),
184 (r"/api/v1/jobs/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/finished",
185 jobs.APIv1FinishedHandler),
186 (r"/api/v1/jobs/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/log/stream",
187 jobs.APIv1LogStreamHandler),
188
189 # Builders
190 (r"/builders", builders.IndexHandler),
191 (r"/builders/create", builders.CreateHandler),
192 (r"/builders/([A-Za-z0-9\-\.]+)", builders.ShowHandler),
193 (r"/builders/([A-Za-z0-9\-\.]+)/delete", builders.DeleteHandler),
194 (r"/builders/([A-Za-z0-9\-\.]+)/edit", builders.BuilderEditHandler),
195 (r"/builders/([A-Za-z0-9\-\.]+)/start", builders.StartHandler),
196 (r"/builders/([A-Za-z0-9\-\.]+)/stats", builders.StatsHandler),
197 (r"/builders/([A-Za-z0-9\-\.]+)/stop", builders.StopHandler),
198 (r"/api/v1/builders/control", builders.APIv1ControlHandler),
199
200 # Distributions
201 (r"/distros", distributions.IndexHandler),
202 (r"/distros/([A-Za-z0-9\-\.]+)", distributions.ShowHandler),
203 (r"/distros/([A-Za-z0-9\-\.]+)/edit", distributions.EditHandler),
204 (r"/distros/(?P<distro_slug>[A-Za-z0-9\-\.]+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)",
205 repos.ShowHandler),
206 (r"/distros/(?P<distro_slug>[A-Za-z0-9\-\.]+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)\.repo",
207 repos.ConfigHandler),
208 (r"/distros/(?P<distro_slug>[A-Za-z0-9\-\.]+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)/builds",
209 repos.BuildsHandler),
210 (r"/distros/(?P<distro_slug>[A-Za-z0-9\-\.]+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)/delete",
211 repos.DeleteHandler),
212 (r"/distros/(?P<distro_slug>[A-Za-z0-9\-\.]+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)/edit",
213 repos.EditHandler),
214 (r"/distros/(?P<distro_slug>[A-Za-z0-9\-\.]+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)/mirrorlist",
215 repos.MirrorlistHandler),
216 (r"/distros/(?P<distro_slug>[A-Za-z0-9\-\.]+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)/sources/(?P<source_slug>[A-Za-z0-9\-]+)",
217 sources.ShowHandler),
218 (r"/distros/(?P<distro_slug>[A-Za-z0-9\-\.]+)/repos/(?P<repo_slug>[A-Za-z0-9\-]+)/sources/(?P<source_slug>[A-Za-z0-9\-]+)/commits/(?P<commit_slug>[a-f0-9]{40})",
219 sources.ShowCommitHandler),
220
221 # Distro Monitorings
222 (r"/distros/([A-Za-z0-9\-\.]+)/monitorings/([\w\-_]+)", monitorings.ShowHandler),
223 (r"/distros/([A-Za-z0-9\-\.]+)/monitorings/([\w\-_]+)/check", monitorings.CheckHandler),
224 (r"/distros/([A-Za-z0-9\-\.]+)/monitorings/([\w\-_]+)/create", monitorings.CreateHandler),
225 (r"/distros/([A-Za-z0-9\-\.]+)/monitorings/([\w\-_]+)/delete", monitorings.DeleteHandler),
226 (r"/distros/([A-Za-z0-9\-\.]+)/monitorings/([\w\-_]+)/edit", monitorings.EditHandler),
227
228 # Distro Releases
229 (r"/distros/([A-Za-z0-9\-\.]+)/releases", distributions.ReleasesIndexHandler),
230 (r"/distros/([A-Za-z0-9\-\.]+)/releases/create", distributions.ReleasesCreateHandler),
231 (r"/distros/([A-Za-z0-9\-\.]+)/releases/([\w\-_]+)", distributions.ReleasesShowHandler),
232 (r"/distros/([A-Za-z0-9\-\.]+)/releases/([\w\-_]+)/delete", distributions.ReleasesDeleteHandler),
233 (r"/distros/([A-Za-z0-9\-\.]+)/releases/([\w\-_]+)/edit", distributions.ReleasesEditHandler),
234 (r"/distros/([A-Za-z0-9\-\.]+)/releases/([\w\-_]+)/publish", distributions.ReleasesPublishHandler),
235
236 # Mirrors
237 (r"/mirrors", mirrors.IndexHandler),
238 (r"/mirrors/create", mirrors.CreateHandler),
239 (r"/mirrors/([\w\-\.]+)", mirrors.ShowHandler),
240 (r"/mirrors/([\w\-\.]+)/check", mirrors.CheckHandler),
241 (r"/mirrors/([\w\-\.]+)/delete", mirrors.DeleteHandler),
242 (r"/mirrors/([\w\-\.]+)/edit", mirrors.EditHandler),
243
244 # Search
245 (r"/search", search.SearchHandler),
246
247 # Log
248 (r"/log", handlers.LogHandler),
249
250 # Debuginfo
251 (r"/buildid/([0-9a-f]{40})/debuginfo", debuginfo.DebugInfoHandler),
252
253 # Repositories
254 (r"/api/v1/repos/([\w\d\-]+)", repos.APIv1IndexHandler),
255 (r"/api/v1/repos/([\w\d\-]+)/([\w\d\-]+)", repos.APIv1ShowHandler),
256
257 # Uploads
258 (r"/api/v1/uploads", uploads.APIv1IndexHandler),
259 (r"/api/v1/uploads/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})",
260 uploads.APIv1DetailHandler),
261 ], default_handler_class=errors.Error404Handler, **settings)
262
263 # Launch backend & background tasks
264 self.backend = Backend("/etc/pakfire/pbs.conf")
265 self.backend.launch_background_tasks()
266
267 logging.info("Successfully initialied application")
268
269 ## UI methods
270
271 def extract_hostname(self, handler, url):
272 url = urllib.parse.urlparse(url)
273
274 return url.hostname
275
276 def format_time(self, handler, s, shorter=False):
277 _ = handler.locale.translate
278
279 if isinstance(s, datetime.timedelta):
280 s = s.total_seconds()
281
282 args = {
283 "s" : round(s % 60),
284 "m" : round(s / 60 % 60),
285 "h" : round(s / 3600 % 3600),
286 "d" : round(s / 86400),
287 }
288
289 # Less than one minute
290 if s < 60:
291 return _("%(s)d s") % args
292
293 # Less than one hour
294 elif s < 3600:
295 return _("%(m)d:%(s)02d m") % args
296
297 # Less than one day
298 elif s < 86400:
299 return _("%(h)d:%(m)02d h") % args
300
301 # More than one day
302 else:
303 return _("%(d)d:%(h)02d d") % args
304
305 def group(self, handler, *args, **kwargs):
306 return misc.group(*args, **kwargs)
307
308 def make_url(self, handler, url, **kwargs):
309 # Format any query arguments and append them to the URL
310 if kwargs:
311 # Filter out None
312 args = { k : kwargs[k] for k in kwargs if kwargs[k] is not None }
313
314 # Encode into URL format
315 args = urllib.parse.urlencode(args)
316
317 url = "%s?%s" % (url, args)
318
319 return url