Hi list,
I'd like to start yet another discussion about some functionality of copr, here it is:
One of nice use cases for copr would be building software collections [1]. These however require modified mock chroot (modified config_opts['root'] and config_opts['chroot_setup_cmd']).
I'm trying to think of a way how to do this:
- We would need to allow users to create their own chroots (or more precisely allow them to do certain modifications).
- We would need to be able to send these chroots from frontend to backend.
- We would need some mechanism for sane naming, so that we can distinguish between builds of collections for different releases and architectures. E.g. ruby193-x86_64 is not enough, we need to also store the information about os name (epel/fedora) and os version (epel 6, fedora 18, ...).
My proposal:
- Use chroot names like ruby193_fedora-18-x86_64.
- Allow users to create these chroots by modifying config_opts['chroot_setup_cmd'] (config_opts['root'] would be autogenerated from the chroot name).
- Store the modified information in the MockChroot table and create these on backend using communication channel proposed in [2] (parts of it already implemented in frontend).
- Allow selecting these on copr creation/modification as more options for mock chroots, by default hidden under some kind of fancy clickable JS dropdown.
Thoughts?
--
Regards,
Bohuslav "Slavek" Kabrda.
[1] https://fedorahosted.org/SoftwareCollections/
[2] https://fedorahosted.org/copr/ticket/8
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit 8fb8188a50af94855b0767f9bfddf63002c34efe
Author: Bohuslav Kabrda <bkabrda(a)redhat.com>
Date: Fri Mar 29 10:01:20 2013 +0100
Fix #60 - copr admin can now give up his permissions even if there are permissions for more users for the copr
- also added flexmock to requirements
>---------------------------------------------------------------
.../coprs/views/coprs_ns/coprs_general.py | 3 ++
.../test_views/test_coprs_ns/test_coprs_general.py | 25 ++++++++++++++++++++
requirements.txt | 1 +
3 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/coprs_frontend/coprs/views/coprs_ns/coprs_general.py b/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
index 1b8353b..f5d84fe 100644
--- a/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
+++ b/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
@@ -219,6 +219,9 @@ def copr_update_permissions(username, coprname):
if permissions_form.validate_on_submit():
# we don't change owner (yet)
try:
+ # if admin is changing his permissions, his must be changed last
+ # so that we don't get InsufficientRightsException
+ permissions.sort(cmp=lambda x, y: -1 if y.user_id == flask.g.user.id else 1)
for perm in permissions:
new_builder = permissions_form['copr_builder_{0}'.format(perm.user_id)].data
new_admin = permissions_form['copr_admin_{0}'.format(perm.user_id)].data
diff --git a/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_general.py b/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_general.py
index 63f3a06..6fa8e19 100644
--- a/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_general.py
+++ b/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_general.py
@@ -1,5 +1,7 @@
import flask
+from flexmock import flexmock
+
from coprs.signals import copr_created
from tests.coprs_test_case import CoprsTestCase
@@ -371,6 +373,29 @@ class TestCoprUpdatePermissions(CoprsTestCase):
follow_redirects = True)
assert 'Copr permissions were updated' in r.data
+ def test_copr_admin_can_give_up_his_permissions(self, f_users, f_coprs, f_copr_permissions, f_db):
+ # if admin is giving up his permission and there are more permissions for
+ # this copr, then if the admin is altered first, he won't be permitted
+ # to alter the other permissions and the whole update would fail
+ with self.tc as c:
+ with c.session_transaction() as s:
+ s['openid'] = self.u1.openid_name
+ self.db.session.add_all([self.u2, self.c3, self.cp2, self.cp3])
+ # mock out the order of CoprPermission objects, so that we are sure
+ # the admin is the first one and therefore this fails if
+ # the view doesn't reorder the permissions
+ flexmock(self.models.Copr, copr_permissions=[self.cp3, self.cp2])
+ r = c.post('/coprs/detail/{0}/{1}/update_permissions/'.format(self.u2.name, self.c3.name),
+ data = {'copr_admin_1': '1', 'copr_admin_3': '1'},
+ follow_redirects = True)
+ self.db.session.add_all([self.u1, self.c3])
+ perm = self.models.CoprPermission.query.filter(self.models.CoprPermission.user_id==self.u1.id).\
+ filter(self.models.CoprPermission.copr_id==self.c3.id).\
+ first()
+ assert perm.copr_admin == 1
+ 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:
diff --git a/requirements.txt b/requirements.txt
index d9b8d1f..9094607 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,4 +8,5 @@ flask-openid
flask-script
flask-whooshee
flask-wtf
+flexmock
pytest
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit 57dc4058d4c6709bde5e95ddf67716f142482632
Author: Bohuslav Kabrda <bkabrda(a)redhat.com>
Date: Thu Mar 28 15:30:52 2013 +0100
It seems that pytest does not like having files with same names...
>---------------------------------------------------------------
.../{test_general.py => test_backend_general.py} | 0
.../{test_builds.py => test_coprs_builds.py} | 0
.../{test_general.py => test_coprs_general.py} | 0
3 files changed, 0 insertions(+), 0 deletions(-)
diff --git a/coprs_frontend/tests/test_views/test_backend_ns/test_general.py b/coprs_frontend/tests/test_views/test_backend_ns/test_backend_general.py
similarity index 100%
rename from coprs_frontend/tests/test_views/test_backend_ns/test_general.py
rename to coprs_frontend/tests/test_views/test_backend_ns/test_backend_general.py
diff --git a/coprs_frontend/tests/test_views/test_coprs_ns/test_builds.py b/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_builds.py
similarity index 100%
rename from coprs_frontend/tests/test_views/test_coprs_ns/test_builds.py
rename to coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_builds.py
diff --git a/coprs_frontend/tests/test_views/test_coprs_ns/test_general.py b/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_general.py
similarity index 100%
rename from coprs_frontend/tests/test_views/test_coprs_ns/test_general.py
rename to coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_general.py
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit 971c737b620cb4851bffddf3d234b6550ce7ced9
Author: Bohuslav Kabrda <bkabrda(a)redhat.com>
Date: Thu Mar 28 12:58:59 2013 +0100
Move authorization checking for deleting coprs into logic
>---------------------------------------------------------------
coprs_frontend/coprs/logic/coprs_logic.py | 3 ++-
.../coprs/views/coprs_ns/coprs_general.py | 6 +-----
2 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/coprs_frontend/coprs/logic/coprs_logic.py b/coprs_frontend/coprs/logic/coprs_logic.py
index 6922789..663c5cd 100644
--- a/coprs_frontend/coprs/logic/coprs_logic.py
+++ b/coprs_frontend/coprs/logic/coprs_logic.py
@@ -117,7 +117,8 @@ class CoprsLogic(object):
@classmethod
def delete(cls, user, copr, check_for_duplicates=True):
- # for the time being, we authorize user to do this in view...
+ if not copr.owner == user:
+ raise exceptions.InsufficientRightsException('Only owners may delete their Coprs.')
# TODO: do we want to dump the information somewhere, so that we can search it in future?
cls.raise_if_unfinished_action(user, copr,
'Can\'t delete this Copr, another operation is in progress: {action}')
diff --git a/coprs_frontend/coprs/views/coprs_ns/coprs_general.py b/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
index 51bc7d1..1b8353b 100644
--- a/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
+++ b/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
@@ -238,15 +238,11 @@ def copr_update_permissions(username, coprname):
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:
+ except (exceptions.ActionInProgressException, exceptions.InsufficientRightsException) as e:
db.session.rollback()
flask.flash(e)
return flask.redirect(flask.url_for('coprs_ns.copr_detail', username=username, coprname=coprname))