Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master
---------------------------------------------------------------
commit 010246d4e7351c9113cf1c3b4cee7aa20ae26af5
Author: Bohuslav Kabrda <bkabrda(a)redhat.com>
Date: Wed Mar 27 14:46:33 2013 +0100
Allow deleting coprs
---------------------------------------------------------------
coprs_frontend/coprs/forms.py | 3 +
coprs_frontend/coprs/logic/coprs_logic.py | 17 ++++++++
.../coprs/templates/coprs/_coprs_forms.html | 17 ++++++++
coprs_frontend/coprs/templates/coprs/detail.html | 5 ++
.../coprs/templates/coprs/detail/delete.html | 14 +++++++
.../coprs/views/coprs_ns/coprs_general.py | 24 +++++++++++
coprs_frontend/coprs/whoosheers.py | 4 ++
.../tests/test_views/test_coprs_ns/test_general.py | 41 ++++++++++++++++++++
8 files changed, 125 insertions(+), 0 deletions(-)
diff --git a/coprs_frontend/coprs/forms.py b/coprs_frontend/coprs/forms.py
index 5c80c33..7c7cf35 100644
--- a/coprs_frontend/coprs/forms.py
+++ b/coprs_frontend/coprs/forms.py
@@ -123,6 +123,9 @@ class CoprFormFactory(object):
return F
+class CoprDeleteForm(wtf.Form):
+ verify = wtf.TextField('Confirm deleting by typing "yes"',
+ validators=[wtf.Required(), wtf.Regexp(r'^yes$',
message='Type "yes" - without the quotes, lowercase.')])
class BuildForm(wtf.Form):
pkgs = wtf.TextAreaField('Pkgs',
diff --git a/coprs_frontend/coprs/logic/coprs_logic.py
b/coprs_frontend/coprs/logic/coprs_logic.py
index 29aa6b0..1a83147 100644
--- a/coprs_frontend/coprs/logic/coprs_logic.py
+++ b/coprs_frontend/coprs/logic/coprs_logic.py
@@ -112,6 +112,23 @@ class CoprsLogic(object):
db.session.add(copr)
@classmethod
+ def delete(cls, user, copr, check_for_duplicates=True):
+ # for the time being, we authorize user to do this in view...
+ # TODO: do we want to dump the information somewhere, so that we can search it in
future?
+ cls.raise_if_unfinished_action(user, copr)
+ action = models.Action(action_type=helpers.ActionTypeEnum('delete'),
+ object_type='copr',
+ object_id=copr.id,
+ old_value='{0}/{1}'.format(copr.owner.name,
copr.name),
+ new_value='',
+ created_on=int(time.time()))
+
+ db.session.add(action)
+ db.session.delete(copr)
+
+ return copr
+
+ @classmethod
def exists_for_user(cls, user, coprname):
existing = models.Copr.query.filter(models.Copr.name==coprname).\
filter(models.Copr.owner_id==user.id)
diff --git a/coprs_frontend/coprs/templates/coprs/_coprs_forms.html
b/coprs_frontend/coprs/templates/coprs/_coprs_forms.html
index b3f6742..a0f55e3 100644
--- a/coprs_frontend/coprs/templates/coprs/_coprs_forms.html
+++ b/coprs_frontend/coprs/templates/coprs/_coprs_forms.html
@@ -31,6 +31,23 @@
</form>
{% endmacro %}
+{% macro copr_delete_form(form, copr) %}
+ <form action="{{ url_for('coprs_ns.copr_delete',
username=copr.owner.name, coprname=copr.name) }}" method="post">
+ <dl>
+ {{ form.csrf_token }}
+ <dd>
+ {% if form.verify.errors %}
+ {% for error in form.verify.errors %}
+ <p class="form-error">{{ error }}</p>
+ {% endfor %}
+ {% endif %}
+ </dd>
+ {{ form.verify }}
+ <dt><input type="submit"
value="Delete"></dt>
+ </dl>
+ </form>
+{% endmacro %}
+
{% macro copr_permissions_form(form, copr, permissions) %}
{% if permissions %}
<form action="{{ url_for('coprs_ns.copr_update_permissions',
username=copr.owner.name, coprname=copr.name) }}" method=post>
diff --git a/coprs_frontend/coprs/templates/coprs/detail.html
b/coprs_frontend/coprs/templates/coprs/detail.html
index ef0f097..749ffb6 100644
--- a/coprs_frontend/coprs/templates/coprs/detail.html
+++ b/coprs_frontend/coprs/templates/coprs/detail.html
@@ -27,6 +27,11 @@
<a href="{{ url_for('coprs_ns.copr_edit', username =
copr.owner.name, coprname = copr.name) }}">Edit</a>
</li>
{% endif %}
+ {% if g.user and g.user == copr.owner %}
+ <li class="{% block delete_selected %}unselected{% endblock %}">
+ <a href="{{ url_for('coprs_ns.copr_delete',
username=copr.owner.name, coprname=copr.name) }}">Delete</a>
+ </li>
+ {% endif %}
</ul>
</div>
{% block detail_body %}{% endblock %}
diff --git a/coprs_frontend/coprs/templates/coprs/detail/delete.html
b/coprs_frontend/coprs/templates/coprs/detail/delete.html
new file mode 100644
index 0000000..0e65de0
--- /dev/null
+++ b/coprs_frontend/coprs/templates/coprs/detail/delete.html
@@ -0,0 +1,14 @@
+{% extends "coprs/detail.html" %}
+{% block title %}Delete {{ copr.owner.name }}/{{ copr.name }}?{% endblock %}
+{% block delete_selected %}selected{% endblock %}
+{% from "coprs/_coprs_forms.html" import copr_delete_form %}
+
+{% block detail_body %}
+ <p>If you really want to delete this Copr, you'll have to answer this
riddle:</p>
+ <p>{{ range(5)|random }}.{{ range(10)|random }} hens lay {{ range(5)|random }}.{{
range(10)|random }} eggs in
+ {{ range(5)|random }}.{{ range(10)|random }} days. How many eggs do {{ range(5)|random
}}.{{ range(10)|random }}
+ hens lay in {{ range(5)|random }}.{{ range(10)|random }} days?</p>
+ <p>Ok, kidding, just type "<strong>yes</strong>" into the
below box.</p>
+ {{ copr_delete_form(form, copr) }}
+
+{% endblock %}
diff --git a/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
b/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
index fc1a0ad..6da142e 100644
--- a/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
+++ b/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
@@ -236,3 +236,27 @@ def copr_update_permissions(username, coprname):
flask.flash('Copr permissions were updated successfully.')
return flask.redirect(flask.url_for('coprs_ns.copr_detail', username =
copr.owner.name, coprname = copr.name))
+
+@coprs_ns.route('/detail/<username>/<coprname>/delete/',
methods=['GET', 'POST'])
+@login_required
+def copr_delete(username, coprname):
+ form = forms.CoprDeleteForm()
+ copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first()
+ # only owner can delete a copr
+ if flask.g.user != copr.owner:
+ flask.flash('Only owners may delete their Coprs.')
+ return flask.redirect(flask.url_for('coprs_ns.copr_detail',
username=username, coprname=coprname))
+
+ if form.validate_on_submit():
+ try:
+ coprs_logic.CoprsLogic.delete(flask.g.user, copr)
+ except exceptions.ActionInProgressException as e:
+ db.session.rollback()
+ flask.flash('Can\'t manipulate this Copr, there is another operation
in progress: {0}'.format(e.action))
+ return flask.redirect(flask.url_for('coprs_ns.copr_detail',
username=username, coprname=coprname))
+ else:
+ db.session.commit()
+ flask.flash('Copr was deleted successfully.')
+ return flask.redirect(flask.url_for('coprs_ns.coprs_by_owner',
username=username))
+ else:
+ return flask.render_template('coprs/detail/delete.html', form=form,
copr=copr)
diff --git a/coprs_frontend/coprs/whoosheers.py b/coprs_frontend/coprs/whoosheers.py
index 45b5ab6..cefae0f 100644
--- a/coprs_frontend/coprs/whoosheers.py
+++ b/coprs_frontend/coprs/whoosheers.py
@@ -53,3 +53,7 @@ class CoprUserWhoosheer(AbstractWhoosheer):
coprname=copr.name,
description=copr.description,
instructions=copr.instructions)
+
+ @classmethod
+ def delete_copr(cls, writer, copr):
+ writer.delete_by_term('copr_id', copr.id)
diff --git a/coprs_frontend/tests/test_views/test_coprs_ns/test_general.py
b/coprs_frontend/tests/test_views/test_coprs_ns/test_general.py
index 691276f..63f3a06 100644
--- a/coprs_frontend/tests/test_views/test_coprs_ns/test_general.py
+++ b/coprs_frontend/tests/test_views/test_coprs_ns/test_general.py
@@ -370,3 +370,44 @@ class TestCoprUpdatePermissions(CoprsTestCase):
data = {'copr_builder_1': '2',
'copr_admin_3': '2'},
follow_redirects = True)
assert 'Copr permissions were updated' in r.data
+
+class TestCoprDelete(CoprsTestCase):
+ def test_delete(self, f_users, f_coprs, f_db):
+ with self.tc as c:
+ with c.session_transaction() as s:
+ s['openid'] = self.u1.openid_name
+
+ self.db.session.add_all([self.u1, self.c1])
+ r = c.post('/coprs/detail/{0}/{1}/delete/'.format(self.u1.name,
self.c1.name),
+ data = {'verify': 'yes'},
+ follow_redirects = True)
+ assert 'Copr was deleted successfully' in r.data
+ assert self.models.Action.query.first().id == self.c1.id
+ assert not
self.models.Copr.query.filter(self.models.Copr.id==self.c1.id).first()
+
+ def test_copr_delete_does_not_delete_if_verify_filled_wrongly(self, f_users, f_coprs,
f_db):
+ with self.tc as c:
+ with c.session_transaction() as s:
+ s['openid'] = self.u1.openid_name
+
+ self.db.session.add_all([self.u1, self.c1])
+ r = c.post('/coprs/detail/{0}/{1}/delete/'.format(self.u1.name,
self.c1.name),
+ data = {'verify': 'no'},
+ follow_redirects = True)
+ assert 'Copr was deleted successfully' not in r.data
+ assert not self.models.Action.query.first()
+ assert
self.models.Copr.query.filter(self.models.Copr.id==self.c1.id).first()
+
+ def test_non_owner_cant_delete(self, f_users, f_coprs, f_db):
+ with self.tc as c:
+ with c.session_transaction() as s:
+ s['openid'] = self.u2.openid_name
+
+ self.db.session.add_all([self.u1, self.u2, self.c1])
+ r = c.post('/coprs/detail/{0}/{1}/delete/'.format(self.u1.name,
self.c1.name),
+ data = {'verify': 'yes'},
+ follow_redirects = True)
+ self.db.session.add_all([self.c1])
+ assert 'Copr was deleted successfully' not in r.data
+ assert not self.models.Action.query.first()
+ assert
self.models.Copr.query.filter(self.models.Copr.id==self.c1.id).first()