1 import os
2 import time
3
4 import flask
5 import platform
6 import smtplib
7 import sqlalchemy
8 from email.mime.text import MIMEText
9
10 from coprs import app
11 from coprs import db
12 from coprs import exceptions
13 from coprs import forms
14 from coprs import helpers
15 from coprs import models
16
17 from coprs.views.misc import login_required, page_not_found
18
19 from coprs.views.coprs_ns import coprs_ns
20
21 from coprs.logic import builds_logic
22 from coprs.logic import coprs_logic
23 from coprs.helpers import parse_package_name, render_repo
24
25
26 @coprs_ns.route('/', defaults = {'page': 1})
27 @coprs_ns.route('/<int:page>/')
28 -def coprs_show(page=1):
34
35
36 @coprs_ns.route('/<username>/', defaults = {'page': 1})
37 @coprs_ns.route('/<username>/<int:page>/')
38 -def coprs_by_owner(username=None, page=1):
47
48
49 @coprs_ns.route('/<username>/allowed/', defaults = {'page': 1})
50 @coprs_ns.route('/<username>/allowed/<int:page>/')
51 -def coprs_by_allowed(username=None, page=1):
60
61
62 @coprs_ns.route('/fulltext/', defaults = {'page': 1})
63 @coprs_ns.route('/fulltext/<int:page>/')
64 -def coprs_fulltext_search(page=1):
65 fulltext = flask.request.args.get('fulltext', '')
66 try:
67 query = coprs_logic.CoprsLogic.get_multiple_fulltext(flask.g.user, fulltext)
68 except ValueError, e:
69 flask.flash(str(e))
70 return flask.redirect(flask.request.referrer or flask.url_for('coprs_ns.coprs_show'))
71 paginator = helpers.Paginator(query, query.count(), page)
72
73 coprs = paginator.sliced_query
74 return flask.render_template('coprs/show.html',
75 coprs=coprs,
76 paginator=paginator,
77 fulltext=fulltext)
78
79
80 @coprs_ns.route('/<username>/add/')
81 @login_required
82 -def copr_add(username):
86
87
88 @coprs_ns.route('/<username>/new/', methods=['POST'])
89 @login_required
90 -def copr_new(username):
91 """ Receive information from the user on how to create its new copr
92 and create it accordingly.
93 """
94 form = forms.CoprFormFactory.create_form_cls()()
95 if form.validate_on_submit():
96 copr = coprs_logic.CoprsLogic.add(flask.g.user,
97 name=form.name.data,
98 repos=form.repos.data.replace('\n', ' '),
99 selected_chroots=form.selected_chroots,
100 description=form.description.data,
101 instructions=form.instructions.data)
102 db.session.commit()
103 flask.flash('New project was successfully created.')
104
105 if form.initial_pkgs.data:
106 builds_logic.BuildsLogic.add(flask.g.user,
107 pkgs=form.initial_pkgs.data.replace('\n', ' '),
108 copr=copr)
109 db.session.commit()
110 flask.flash('Initial packages were successfully submitted '
111 'for building.')
112
113 return flask.redirect(flask.url_for('coprs_ns.copr_detail', username=flask.g.user.name, coprname=copr.name))
114 else:
115 return flask.render_template('coprs/add.html', form = form)
116
117
118 @coprs_ns.route('/<username>/<coprname>/')
119 -def copr_detail(username, coprname):
120 query = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname, with_mock_chroots=True)
121 form = forms.CoprLegalFlagForm()
122 try:
123 copr = query.one()
124 except sqlalchemy.orm.exc.NoResultFound:
125 return page_not_found('Copr with name {0} does not exist.'.format(coprname))
126
127 return flask.render_template('coprs/detail/overview.html',
128 copr=copr,
129 form=form)
130
131
132 @coprs_ns.route('/<username>/<coprname>/permissions/')
133 -def copr_permissions(username, coprname):
162
163
164 @coprs_ns.route('/<username>/<coprname>/edit/')
165 @login_required
166 -def copr_edit(username, coprname, form=None):
178
179
180 @coprs_ns.route('/<username>/<coprname>/update/', methods = ['POST'])
181 @login_required
182 -def copr_update(username, coprname):
183 form = forms.CoprFormFactory.create_form_cls()()
184 copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first()
185
186 if form.validate_on_submit():
187
188 copr.name = form.name.data
189 copr.repos = form.repos.data.replace('\n', ' ')
190 copr.description = form.description.data
191 copr.instructions = form.instructions.data
192 coprs_logic.CoprChrootsLogic.update_from_names(flask.g.user, copr, form.selected_chroots)
193
194 try:
195 coprs_logic.CoprsLogic.update(flask.g.user, copr, check_for_duplicates = False)
196 except (exceptions.ActionInProgressException, exceptions.InsufficientRightsException) as e:
197 flask.flash(str(e))
198 db.session.rollback()
199 else:
200 flask.flash('Project was updated successfully.')
201 db.session.commit()
202
203 return flask.redirect(flask.url_for('coprs_ns.copr_detail', username = username, coprname = copr.name))
204 else:
205 return copr_edit(username, coprname, form)
206
207
208 @coprs_ns.route('/<username>/<coprname>/permissions_applier_change/', methods = ['POST'])
209 @login_required
210 -def copr_permissions_applier_change(username, coprname):
211 copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first()
212 permission = coprs_logic.CoprPermissionsLogic.get(flask.g.user, copr, flask.g.user).first()
213 applier_permissions_form = forms.PermissionsApplierFormFactory.create_form_cls(permission)()
214
215 if not copr:
216 return page_not_found('Project with name {0} does not exist.'.format(coprname))
217 if copr.owner == flask.g.user:
218 flask.flash('Owner cannot request permissions for his own project.')
219 elif applier_permissions_form.validate_on_submit():
220
221 new_builder = applier_permissions_form.copr_builder.data
222 new_admin = applier_permissions_form.copr_admin.data
223 coprs_logic.CoprPermissionsLogic.update_permissions_by_applier(flask.g.user, copr, permission, new_builder, new_admin)
224 db.session.commit()
225 flask.flash('Successfuly updated permissions for project "{0}".'.format(copr.name))
226
227 return flask.redirect(flask.url_for('coprs_ns.copr_detail', username = copr.owner.name, coprname = copr.name))
228
229
230 @coprs_ns.route('/<username>/<coprname>/update_permissions/', methods = ['POST'])
231 @login_required
232 -def copr_update_permissions(username, coprname):
257
258
259 @coprs_ns.route('/<username>/<coprname>/delete/', methods=['GET', 'POST'])
260 @login_required
261 -def copr_delete(username, coprname):
262 form = forms.CoprDeleteForm()
263 copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first()
264
265 if form.validate_on_submit():
266 try:
267 coprs_logic.CoprsLogic.delete(flask.g.user, copr)
268 except (exceptions.ActionInProgressException, exceptions.InsufficientRightsException) as e:
269 db.session.rollback()
270 flask.flash(str(e))
271 return flask.redirect(flask.url_for('coprs_ns.copr_detail', username=username, coprname=coprname))
272 else:
273 db.session.commit()
274 flask.flash('Project was deleted successfully.')
275 return flask.redirect(flask.url_for('coprs_ns.coprs_by_owner', username=username))
276 else:
277 if copr:
278 return flask.render_template('coprs/detail/delete.html', form=form, copr=copr)
279 else:
280 return page_not_found('Project {0}/{1} does not exist'.format(username, coprname))
281
282
283 @coprs_ns.route('/<username>/<coprname>/legal_flag/', methods=['POST'])
284 @login_required
285 -def copr_legal_flag(username, coprname):
286 form = forms.CoprLegalFlagForm()
287 copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first()
288
289 legal_flag = models.LegalFlag(raise_message=form.comment.data,
290 raised_on=int(time.time()),
291 copr=copr,
292 reporter=flask.g.user)
293 db.session.add(legal_flag)
294 db.session.commit()
295
296 send_to = app.config['SEND_LEGAL_TO'] or ['root@localhost']
297 hostname = platform.node()
298 navigate_to = "\nNavigate to http://%s%s" % (hostname, flask.url_for('admin_ns.legal_flag'))
299 contact = "\nContact on owner is: %s <%s>" % (username, copr.owner.mail)
300 reported_by = "\nReported by %s <%s>" % (flask.g.user.name, flask.g.user.mail)
301 try:
302 msg = MIMEText(form.comment.data + navigate_to + contact + reported_by, "plain")
303 except UnicodeEncodeError:
304 msg = MIMEText(form.comment.data.encode('utf-8') + navigate_to + contact + reported_by, "plain", "utf-8")
305 msg['Subject'] = 'Legal flag raised on %s' % coprname
306 msg['From'] = 'root@%s' % hostname
307 msg['To'] = ', '.join(send_to)
308 s = smtplib.SMTP('localhost')
309 s.sendmail('root@%s' % hostname, send_to, msg.as_string())
310 s.quit()
311
312 flask.flash('Admin was noticed about your report and will investigate the project shortly.')
313 return flask.redirect(flask.url_for('coprs_ns.copr_detail', username=username, coprname=coprname))
314
315
316 @coprs_ns.route('/<username>/<coprname>/repo/<chroot>/')
317 -def generate_repo_file(username, coprname, chroot):
318 ''' Generate repo file for a given repo name.
319 Reponame = username-coprname '''
320
321
322
323
324 reponame = "%s-%s" % (username, coprname)
325
326 if '-' not in reponame:
327 return page_not_found('Bad repository name: {0}. Must be username-projectname'.format(reponame))
328
329 copr = None
330 try:
331
332 copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname,
333 with_builds=True).one()
334 except sqlalchemy.orm.exc.NoResultFound:
335 return page_not_found('Project {0}/{1} does not exist'.format(username, coprname))
336
337 try:
338 mock_chroot = coprs_logic.MockChrootsLogic.get_from_name(chroot).one()
339 except sqlalchemy.orm.exc.NoResultFound:
340 return page_not_found('Chroot %s does not exist' % chroot)
341 except ValueError, e:
342 return page_not_found("%s" % e)
343
344 url = ''
345 for build in copr.builds:
346 if build.results:
347 url = build.results
348 break
349
350 if not url:
351 return page_not_found('Repository not initialized: No finished builds in {0}/{1}.'.format(username, coprname))
352
353 response = flask.make_response(render_repo(copr, mock_chroot, url))
354 response.mimetype='text/plain'
355 response.headers['Content-Disposition'] = 'filename=%s.repo' % reponame
356 return response
357
358 @coprs_ns.route('/<username>/<coprname>/monitor/')
359 -def copr_build_monitor(username, coprname):
360 query = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname, with_mock_chroots=True)
361 form = forms.CoprLegalFlagForm()
362 try:
363 copr = query.one()
364 except sqlalchemy.orm.exc.NoResultFound:
365 return page_not_found('Copr with name {0} does not exist.'.format(coprname))
366
367 builds_query = builds_logic.BuildsLogic.get_multiple(flask.g.user, copr=copr)
368 builds = builds_query.order_by('-id').all()
369
370
371
372
373
374
375
376
377
378
379 out = {}
380 build = None
381 chroots = set([chroot.name for chroot in copr.active_chroots])
382 latest_build = None
383
384 if builds:
385 latest_build = builds[0]
386 chroots.union([chroot.name for chroot in latest_build.build_chroots])
387
388 chroots = sorted(chroots)
389
390 for build in builds:
391 chroot_results = {chroot.name: chroot.state
392 for chroot in build.build_chroots}
393
394 build_results = []
395 for chroot_name in chroots:
396 if chroot_name in chroot_results:
397 build_results.append((build.id, chroot_results[chroot_name]))
398 else:
399 build_results.append((build.id, None))
400
401 for pkg_url in build.pkgs.split():
402 pkg = os.path.basename(pkg_url)
403 pkg_name = parse_package_name(pkg)
404
405 if pkg_name in out:
406 continue
407
408 out[pkg_name] = build_results
409
410 return flask.render_template('coprs/detail/monitor.html',
411 copr=copr,
412 build=latest_build,
413 chroots=chroots,
414 packages=sorted(out.iteritems()),
415 form=form)
416