[ckan-changes] commit/ckan: 3 new changesets
Bitbucket
commits-noreply at bitbucket.org
Sat May 14 12:14:10 UTC 2011
3 new changesets in ckan:
http://bitbucket.org/okfn/ckan/changeset/00a5e3b5ba98/
changeset: r3080:00a5e3b5ba98
branch: feature-1074-authz-wui
user: John Lawrence Aspden
date: 2011-05-12 17:18:07
summary: [authz][s]: change package authz form by cut and paste from ckanext-admin. Untested but seems to work ok.
affected #: 2 files (5.8 KB)
--- a/ckan/controllers/package.py Tue May 10 21:07:00 2011 +0100
+++ b/ckan/controllers/package.py Thu May 12 16:18:07 2011 +0100
@@ -425,77 +425,220 @@
if not c.authz_editable:
abort(401, gettext('User %r not authorized to edit %s authorizations') % (c.user, id))
- if 'save' in request.params: # form posted
- # A dict needed for the params because request.params is a nested
- # multidict, which is read only.
- params = dict(request.params)
- c.fs = ckan.forms.get_authz_fieldset('package_authz_fs').bind(pkg.roles, data=params or None)
- try:
- self._update_authz(c.fs)
- except ValidationException, error:
- # TODO: sort this out
- # fs = error.args
- # return render('package/authz.html')
- raise
- # now do new roles
- newrole_user_id = request.params.get('PackageRole--user_id')
- newrole_authzgroup_id = request.params.get('PackageRole--authorized_group_id')
- if newrole_user_id != '__null_value__' and newrole_authzgroup_id != '__null_value__':
- c.message = _(u'Please select either a user or an authorization group, not both.')
- elif newrole_user_id != '__null_value__':
- user = model.Session.query(model.User).get(newrole_user_id)
- # TODO: chech user is not None (should go in validation ...)
- role = request.params.get('PackageRole--role')
- newpkgrole = model.PackageRole(user=user, package=pkg,
- role=role)
- # With FA no way to get new PackageRole back to set package attribute
- # new_roles = ckan.forms.new_roles_fs.bind(model.PackageRole, data=params or None)
- # new_roles.sync()
- for item in self.extensions:
- item.authz_add_role(newpkgrole)
- model.repo.commit_and_remove()
- c.message = _(u'Added role \'%s\' for user \'%s\'') % (
- newpkgrole.role,
- newpkgrole.user.display_name)
- elif newrole_authzgroup_id != '__null_value__':
- authzgroup = model.Session.query(model.AuthorizationGroup).get(newrole_authzgroup_id)
- # TODO: chech user is not None (should go in validation ...)
- role = request.params.get('PackageRole--role')
- newpkgrole = model.PackageRole(authorized_group=authzgroup,
- package=pkg, role=role)
- # With FA no way to get new GroupRole back to set group attribute
- # new_roles = ckan.forms.new_roles_fs.bind(model.GroupRole, data=params or None)
- # new_roles.sync()
- for item in self.extensions:
- item.authz_add_role(newpkgrole)
- model.Session.commit()
- model.Session.remove()
- c.message = _(u'Added role \'%s\' for authorization group \'%s\'') % (
- newpkgrole.role,
- newpkgrole.authorized_group.name)
- elif 'role_to_delete' in request.params:
- pkgrole_id = request.params['role_to_delete']
- pkgrole = model.Session.query(model.PackageRole).get(pkgrole_id)
- if pkgrole is None:
- c.error = _(u'Error: No role found with that id')
+#=========================================
+# Cut and paste from admin extension here
+
+
+ def action_save_form(users_or_authz_groups):
+ # The permissions grid has been saved
+ # which is a grid of checkboxes named user$role
+ rpi = request.params.items()
+
+ # The grid passes us a list of the users/roles that were displayed
+ submitted = [ a for (a,b) in rpi if (b == u'submitted')]
+ # and also those which were checked
+ checked = [ a for (a,b) in rpi if (b == u'on')]
+
+ # from which we can deduce true/false for each user/role combination
+ # that was displayed in the form
+ table_dict={}
+ for a in submitted:
+ table_dict[a]=False
+ for a in checked:
+ table_dict[a]=True
+
+ # now we'll split up the user$role strings to make a dictionary from
+ # (user,role) to True/False, which tells us what we need to do.
+ new_user_role_dict={}
+ for (ur,val) in table_dict.items():
+ u,r = ur.split('$')
+ new_user_role_dict[(u,r)] = val
+
+ # we get the current user/role assignments
+ # and make a dictionary of them
+ #current_uors = model.Session.query(model.SystemRole).all()
+
+ current_uors = [uor for uor in model.Session.query(model.PackageRole).all() if uor.package==pkg]
+
+
+ if users_or_authz_groups=='users':
+ current_users_roles = [( uor.user.name, uor.role) for uor in current_uors if uor.user]
+ elif users_or_authz_groups=='authz_groups':
+ current_users_roles = [( uor.authorized_group.name, uor.role) for uor in current_uors if uor.authorized_group]
else:
- for item in self.extensions:
- item.authz_remove_role(pkgrole)
- if pkgrole.user:
- c.message = _(u'Deleted role \'%s\' for user \'%s\'') % \
- (pkgrole.role, pkgrole.user.display_name)
- elif pkgrole.authorized_group:
- c.message = _(u'Deleted role \'%s\' for authorization group \'%s\'') % \
- (pkgrole.role, pkgrole.authorized_group.name)
- pkgrole.purge()
- model.repo.commit_and_remove()
+ assert False, "shouldn't be here"
- # retrieve pkg again ...
- c.pkg = model.Package.get(id)
- fs = ckan.forms.get_authz_fieldset('package_authz_fs').bind(c.pkg.roles)
- c.form = fs.render()
- c.new_roles_form = \
- ckan.forms.get_authz_fieldset('new_package_roles_fs').render()
+ current_user_role_dict={}
+ for (u,r) in current_users_roles:
+ current_user_role_dict[(u,r)]=True
+
+ # and now we can loop through our dictionary of desired states
+ # checking whether a change needs to be made, and if so making it
+
+ # WORRY: Here it seems that we have to check whether someone is already assigned
+ # a role, in order to avoid assigning it twice, or attempting to delete it when
+ # it doesn't exist. Otherwise problems occur. However this doesn't affect the
+ # index page, which would seem to be prone to suffer the same effect.
+ # Why the difference?
+
+
+ if users_or_authz_groups=='users':
+ for ((u,r), val) in new_user_role_dict.items():
+ if val:
+ if not ((u,r) in current_user_role_dict):
+ model.add_user_to_role(model.User.by_name(u),r,pkg)
+ else:
+ if ((u,r) in current_user_role_dict):
+ model.remove_user_from_role(model.User.by_name(u),r,pkg)
+ elif users_or_authz_groups=='authz_groups':
+ for ((u,r), val) in new_user_role_dict.items():
+ if val:
+ if not ((u,r) in current_user_role_dict):
+ model.add_authorization_group_to_role(model.AuthorizationGroup.by_name(u),r,pkg)
+ else:
+ if ((u,r) in current_user_role_dict):
+ model.remove_authorization_group_from_role(model.AuthorizationGroup.by_name(u),r,pkg)
+ else:
+ assert False, "shouldn't be here"
+
+
+ # finally commit the change to the database
+ model.repo.commit_and_remove()
+ h.flash_success("Changes Saved")
+
+ if ('save' in request.POST):
+ action_save_form('users')
+
+ if ('authz_save' in request.POST):
+ action_save_form('authz_groups')
+
+
+
+
+ def action_add_form(users_or_authz_groups):
+ # The user is attempting to set new roles for a named user
+ new_user = request.params.get('new_user_name')
+ # this is the list of roles whose boxes were ticked
+ checked_roles = [ a for (a,b) in request.params.items() if (b == u'on')]
+ # this is the list of all the roles that were in the submitted form
+ submitted_roles = [ a for (a,b) in request.params.items() if (b == u'submitted')]
+
+ # from this we can make a dictionary of the desired states
+ # i.e. true for the ticked boxes, false for the unticked
+ desired_roles = {}
+ for r in submitted_roles:
+ desired_roles[r]=False
+ for r in checked_roles:
+ desired_roles[r]=True
+
+ # again, in order to avoid either creating a role twice or deleting one which is
+ # non-existent, we need to get the users' current roles (if any)
+
+ current_uors = [uor for uor in model.Session.query(model.PackageRole).all() if uor.package==pkg]
+
+ if users_or_authz_groups=='users':
+ current_roles = [uor.role for uor in current_uors if ( uor.user and uor.user.name == new_user )]
+ user_object = model.User.by_name(new_user)
+ if user_object==None:
+ # The submitted user does not exist. Bail with flash message
+ h.flash_error('unknown user:' + str (new_user))
+ else:
+ # Whenever our desired state is different from our current state, change it.
+ for (r,val) in desired_roles.items():
+ if val:
+ if (r not in current_roles):
+ model.add_user_to_role(user_object, r, pkg)
+ else:
+ if (r in current_roles):
+ model.remove_user_from_role(user_object, r, pkg)
+ h.flash_success("User Added")
+
+ elif users_or_authz_groups=='authz_groups':
+ current_roles = [uor.role for uor in current_uors if ( uor.authorized_group and uor.authorized_group.name == new_user )]
+ user_object = model.AuthorizationGroup.by_name(new_user)
+ if user_object==None:
+ # The submitted user does not exist. Bail with flash message
+ h.flash_error('unknown authorization group:' + str (new_user))
+ else:
+ # Whenever our desired state is different from our current state, change it.
+ for (r,val) in desired_roles.items():
+ if val:
+ if (r not in current_roles):
+ model.add_authorization_group_to_role(user_object, r, pkg)
+ else:
+ if (r in current_roles):
+ model.remove_authorization_group_from_role(user_object, r, pkg)
+ h.flash_success("Authorization Group Added")
+
+ else:
+ assert False, "shouldn't be here"
+
+ # and finally commit all these changes to the database
+ model.repo.commit_and_remove()
+
+ if 'add' in request.POST:
+ action_add_form('users')
+ if 'authz_add' in request.POST:
+ action_add_form('authz_groups')
+
+
+ # =================
+ # Display the page
+
+ # Find out all the possible roles. For the system object that's just all of them.
+ possible_roles = model.Role.get_all()
+
+
+
+
+ # get the list of users who have roles on the System, with their roles
+
+ # I haven't the faintest idea why, but you have to reevaluate this here, or the remainder
+ # of the thing fails:
+ pkg = model.Package.get(id)
+
+ uors = [uor for uor in model.Session.query(model.PackageRole).all() if uor.package==pkg]
+ # uniquify and sort
+ users = sorted(list(set([uor.user.name for uor in uors if uor.user])))
+ authz_groups = sorted(list(set([uor.authorized_group.name for uor in uors if uor.authorized_group])))
+
+ # make a dictionary from (user, role) to True, False
+ users_roles = [( uor.user.name, uor.role) for uor in uors if uor.user]
+ user_role_dict={}
+ for u in users:
+ for r in possible_roles:
+ if (u,r) in users_roles:
+ user_role_dict[(u,r)]=True
+ else:
+ user_role_dict[(u,r)]=False
+
+
+ # and similarly make a dictionary from (authz_group, role) to True, False
+ authz_groups_roles = [( uor.authorized_group.name, uor.role) for uor in uors if uor.authorized_group]
+ authz_groups_role_dict={}
+ for u in authz_groups:
+ for r in possible_roles:
+ if (u,r) in authz_groups_roles:
+ authz_groups_role_dict[(u,r)]=True
+ else:
+ authz_groups_role_dict[(u,r)]=False
+
+
+
+ # pass these variables to the template for rendering
+ c.roles = possible_roles
+
+ c.users = users
+ c.user_role_dict = user_role_dict
+
+ c.authz_groups = authz_groups
+ c.authz_groups_role_dict = authz_groups_role_dict
+
+
+#=========================================
+
+
+
return render('package/authz.html')
def rate(self, id):
--- a/ckan/templates/package/authz.html Tue May 10 21:07:00 2011 +0100
+++ b/ckan/templates/package/authz.html Thu May 12 16:18:07 2011 +0100
@@ -9,21 +9,40 @@
Authorization for Data Package: ${c.pkgname}
</h2>
- <p py:if="c.message">${c.message}</p>
+ <h2>Update Existing Roles</h2>
- <form id="package-authz" action="" method="post">
- <h3>Update Existing Roles</h3>
- <table>
- ${h.literal(c.form)}
- </table>
+ <form id="theform" method="POST">
+ ${authz_form_table('theform', c.roles, c.users, c.user_role_dict)}
+ <button type="submit" name="save">
+ Save
+ </button>
+ </form>
- <h3>Create New User Roles</h3>
- ${h.literal(c.new_roles_form)}
-
- <br/>
+ <h2>Add Roles for Any User</h2>
- ${h.submit('save', _('Save'))}
+ <form id="addform" method="POST">
+ ${authz_add_table(c.roles)}
+ <button type="submit" name="add"> Add </button></form>
+
+ <hr/>
+
+ <h2>Existing Roles for Authorization Groups</h2>
+
+ <form id="authzgroup_form" method="POST">
+ ${authz_form_group_table('authzgroup_form', c.roles, c.authz_groups, c.authz_groups_role_dict)}
+ <button type="submit" name="authz_save">
+ Save
+ </button>
+ </form>
+
+ <h2>Add Roles for Any Authorization Group</h2>
+
+ <form id="authzgroup_addform" method="POST">
+ ${authz_add_group_table(c.roles)}
+ <button type="submit" name="authz_add"> Add </button>
+ </form>
+
</div><xi:include href="layout.html" />
http://bitbucket.org/okfn/ckan/changeset/98fa52ff1dba/
changeset: r3081:98fa52ff1dba
branch: feature-1074-authz-wui
user: John Lawrence Aspden
date: 2011-05-13 11:40:48
summary: [authz][s]: added a couple of suggestions from dread and rgrp for database queries. tidied code. all tested by hand and seems to work.
affected #: 1 file (710 bytes)
--- a/ckan/controllers/package.py Thu May 12 16:18:07 2011 +0100
+++ b/ckan/controllers/package.py Fri May 13 10:40:48 2011 +0100
@@ -425,9 +425,25 @@
if not c.authz_editable:
abort(401, gettext('User %r not authorized to edit %s authorizations') % (c.user, id))
-#=========================================
-# Cut and paste from admin extension here
+ # Three different ways of getting the list of userobjectroles for this package
+ # particular package They all take a frighteningly long time to retrieve
+ # the data, but I can't tell how they'll scale. On a large dataset it might
+ # be worth working out which is quickest, so I've made a function for
+ # ease of changing the query.
+ def get_userobjectroles():
+ # we already have a pkg variable in scope, but I found while testing
+ # that it occasionally mysteriously loses its value! The Lord alone
+ # knows why. Redefine it here and hope it doesn't forget before the
+ # next statement.
+ pkg = model.Package.get(id)
+ # my original query, get them all and filter in python:
+ # uors = [uor for uor in model.Session.query(model.PackageRole).all() if uor.package==pkg]
+ # dread's suggestion:
+ uors = model.Session.query(model.PackageRole).join('package').filter_by(name=pkg.name).all()
+ # rgrp's version:
+ # uors = model.Session.query(model.PackageRole).filter_by(package=pkg)
+ return uors
def action_save_form(users_or_authz_groups):
# The permissions grid has been saved
@@ -458,8 +474,7 @@
# and make a dictionary of them
#current_uors = model.Session.query(model.SystemRole).all()
- current_uors = [uor for uor in model.Session.query(model.PackageRole).all() if uor.package==pkg]
-
+ current_uors = get_userobjectroles()
if users_or_authz_groups=='users':
current_users_roles = [( uor.user.name, uor.role) for uor in current_uors if uor.user]
@@ -506,13 +521,6 @@
model.repo.commit_and_remove()
h.flash_success("Changes Saved")
- if ('save' in request.POST):
- action_save_form('users')
-
- if ('authz_save' in request.POST):
- action_save_form('authz_groups')
-
-
def action_add_form(users_or_authz_groups):
@@ -534,7 +542,7 @@
# again, in order to avoid either creating a role twice or deleting one which is
# non-existent, we need to get the users' current roles (if any)
- current_uors = [uor for uor in model.Session.query(model.PackageRole).all() if uor.package==pkg]
+ current_uors = get_userobjectroles()
if users_or_authz_groups=='users':
current_roles = [uor.role for uor in current_uors if ( uor.user and uor.user.name == new_user )]
@@ -576,28 +584,28 @@
# and finally commit all these changes to the database
model.repo.commit_and_remove()
+
+ # =================
+ # Display the page
+
if 'add' in request.POST:
action_add_form('users')
if 'authz_add' in request.POST:
action_add_form('authz_groups')
+ if ('save' in request.POST):
+ action_save_form('users')
- # =================
- # Display the page
+ if ('authz_save' in request.POST):
+ action_save_form('authz_groups')
- # Find out all the possible roles. For the system object that's just all of them.
+ # Find out all the possible roles. At the moment, any role can be
+ # associated with any object, so that's easy:
possible_roles = model.Role.get_all()
+ # get the list of users who have roles on this object, with their roles
+ uors = get_userobjectroles()
-
-
- # get the list of users who have roles on the System, with their roles
-
- # I haven't the faintest idea why, but you have to reevaluate this here, or the remainder
- # of the thing fails:
- pkg = model.Package.get(id)
-
- uors = [uor for uor in model.Session.query(model.PackageRole).all() if uor.package==pkg]
# uniquify and sort
users = sorted(list(set([uor.user.name for uor in uors if uor.user])))
authz_groups = sorted(list(set([uor.authorized_group.name for uor in uors if uor.authorized_group])))
@@ -612,7 +620,6 @@
else:
user_role_dict[(u,r)]=False
-
# and similarly make a dictionary from (authz_group, role) to True, False
authz_groups_roles = [( uor.authorized_group.name, uor.role) for uor in uors if uor.authorized_group]
authz_groups_role_dict={}
@@ -623,8 +630,6 @@
else:
authz_groups_role_dict[(u,r)]=False
-
-
# pass these variables to the template for rendering
c.roles = possible_roles
@@ -634,13 +639,11 @@
c.authz_groups = authz_groups
c.authz_groups_role_dict = authz_groups_role_dict
+ return render('package/authz.html')
-#=========================================
- return render('package/authz.html')
-
def rate(self, id):
package_name = id
package = model.Package.get(package_name)
http://bitbucket.org/okfn/ckan/changeset/c41864c9e290/
changeset: r3082:c41864c9e290
branch: feature-1074-authz-wui
user: John Lawrence Aspden
date: 2011-05-14 14:12:41
summary: [authz][s]: fix broken test
affected #: 1 file (1.6 KB)
--- a/ckan/tests/functional/test_package_edit_authz.py Fri May 13 10:40:48 2011 +0100
+++ b/ckan/tests/functional/test_package_edit_authz.py Sat May 14 13:12:41 2011 +0100
@@ -3,9 +3,38 @@
from ckan.lib.base import *
import ckan.authz as authz
+
+def check_and_set_checkbox(theform, user, role, should_be, set_to):
+ '''Given an authz form, find the checkbox associated with the strings user and role,
+ assert that it's in the state 'should_be', and set it to 'set_to' '''
+ user_role_string = '%s$%s' % (user, role)
+ checkboxes = [x for x in theform.fields[user_role_string] \
+ if x.__class__.__name__ == 'Checkbox']
+
+ assert(len(checkboxes)==1), \
+ "there should only be one checkbox for %s/%s" % (user, role)
+ checkbox = checkboxes[0]
+
+ #checkbox should be unticked
+ assert checkbox.checked==should_be, \
+ "%s/%s checkbox in unexpected state" % (user, role)
+
+ #tick or untick the box and return the form
+ checkbox.checked=set_to
+ return theform
+
+def package_roles(pkgname):
+ pkg = model.Package.by_name(pkgname)
+ return [ (r.user.name, r.role) for r in pkg.roles ]
+
+
+
class TestPackageEditAuthz(TestController):
@classmethod
def setup_class(self):
+ # for the authorization editing tests we set up test data so:
+ # three users, madeup-sysadmin , madeup-administrator, and madeup-another
+ # two packages test6 and test6a, m-a is admin on both
model.repo.init_db()
model.repo.new_revision()
@@ -77,6 +106,11 @@
href = '%s' % pr.id
assert href in res, res
+
+#################################################################
+#################################################################
+
+
def _prs(self, pkgname):
pkg = model.Package.by_name(pkgname)
return dict([ (getattr(r.user, 'name', 'USER NAME IS NONE'), r) for r in pkg.roles ])
@@ -88,38 +122,44 @@
self.admin})
assert self.pkgname in res
- def _r(r):
- return 'PackageRole-%s-role' % r.id
- def _u(r):
- return 'PackageRole-%s-user_id' % r.id
+ prs=package_roles(self.pkgname)
+ assert len(prs) == 3
+ assert ('madeup-administrator', 'admin') in prs
+ assert ('visitor', 'editor') in prs
+ assert ('logged_in', 'editor') in prs
- prs = self._prs(self.pkgname)
- assert prs['visitor'].role == model.Role.EDITOR
- assert prs['logged_in'].role == model.Role.EDITOR
- form = res.forms['package-authz']
-
- # change role assignments
- form.select(_r(prs['visitor']), model.Role.READER)
- form.select(_r(prs['logged_in']), model.Role.ADMIN)
+ #admin makes visitor a reader and logged in an admin
+ form = res.forms['theform']
+ check_and_set_checkbox(form, u'visitor', u'reader', False, True)
+ check_and_set_checkbox(form, u'logged_in', u'admin', False, True)
+ check_and_set_checkbox(form, u'visitor', u'editor', True, True)
+ check_and_set_checkbox(form, u'logged_in', u'editor', True, False)
+
res = form.submit('save', extra_environ={'REMOTE_USER': self.admin})
- model.repo.commit_and_remove()
# ensure db was changed
- prs = self._prs(self.pkgname)
- assert len(prs) == 3, prs
- assert prs['visitor'].role == model.Role.READER
- assert prs['logged_in'].role == model.Role.ADMIN
+ prs=package_roles(self.pkgname)
+ assert len(prs) == 4
+ assert ('madeup-administrator', 'admin') in prs
+ assert ('visitor', 'reader') in prs
+ assert ('visitor', 'editor') in prs
+ assert ('logged_in', 'admin') in prs
# ensure rerender of form is changed
offset = url_for(controller='package', action='authz', id=self.pkgname)
res = self.app.get(offset, extra_environ={'REMOTE_USER':
self.admin})
assert self.pkgname in res
- fv = res.forms['package-authz']
- visitor_options = fv[_r(prs['visitor'])].options
- assert ('reader', True) in visitor_options, visitor_options
- logged_in_options = fv[_r(prs['logged_in'])].options
- assert ('admin', True) in logged_in_options, logged_in_options
+
+ # check that the checkbox states are what we think they should be
+ # and put things back how they were.
+ form = res.forms['theform']
+ check_and_set_checkbox(form, u'visitor', u'reader', True, False)
+ check_and_set_checkbox(form, u'logged_in', u'admin', True, False)
+ check_and_set_checkbox(form, u'visitor', u'editor', True, True)
+ check_and_set_checkbox(form, u'logged_in', u'editor', False, True)
+ res = form.submit('save', extra_environ={'REMOTE_USER': self.admin})
+
def test_3_sysadmin_changes_role(self):
# load authz page
Repository URL: https://bitbucket.org/okfn/ckan/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
More information about the ckan-changes
mailing list