[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