Skip to content

Commit

Permalink
[1669] Changes to auth to enable users to add datasets to their group
Browse files Browse the repository at this point in the history
  • Loading branch information
rossjones committed Jan 30, 2012
1 parent 6847303 commit c88c900
Show file tree
Hide file tree
Showing 16 changed files with 366 additions and 57 deletions.
2 changes: 1 addition & 1 deletion ckan/controllers/group.py
Expand Up @@ -301,7 +301,6 @@ def pager_url(q=None, page=None):
return render('group/read.html')

def new(self, data=None, errors=None, error_summary=None):

group_type = request.path.strip('/').split('/')[0]
if group_type == 'group':
group_type = None
Expand Down Expand Up @@ -401,6 +400,7 @@ def _save_new(self, context, group_type=None):
tuplize_dict(parse_params(request.params))))
data_dict['type'] = group_type or 'group'
context['message'] = data_dict.get('log_message', '')
data_dict['users'] = [{'name': c.user, 'capacity': 'admin'}]
group = get_action('group_create')(context, data_dict)

# Redirect to the appropriate _read route for the type of group
Expand Down
11 changes: 3 additions & 8 deletions ckan/controllers/package.py
Expand Up @@ -67,15 +67,9 @@ def register_pluggable_behaviour(map):
"""
global _default_controller_behaviour

# Check this method hasn't been invoked already.
# TODO: This method seems to be being invoked more than once during running of
# the tests. So I've disbabled this check until I figure out why.
#if _default_controller_behaviour is not None:
#raise ValueError, "Pluggable package controller behaviour is already defined "\
#"'%s'" % _default_controller_behaviour

# Create the mappings and register the fallback behaviour if one is found.
for plugin in PluginImplementations(IDatasetForm):
print 'Processing %r' % plugin
if plugin.is_fallback():
if _default_controller_behaviour is not None:
raise ValueError, "More than one fallback "\
Expand All @@ -84,7 +78,6 @@ def register_pluggable_behaviour(map):

for package_type in plugin.package_types():
# Create a connection between the newly named type and the package controller
# but first we need to make sure we are not clobbering an existing domain
map.connect('/%s/new' % (package_type,), controller='package', action='new')
map.connect('%s_read' % (package_type,), '/%s/{id}' % (package_type,), controller='package', action='read')
map.connect('%s_action' % (package_type,),
Expand Down Expand Up @@ -440,6 +433,8 @@ def new(self, data=None, errors=None, error_summary=None):
'save': 'save' in request.params,
'schema': self._form_to_db_schema(package_type=package_type)}

# Package needs to have a publisher group in the call to check_access
# and also to save it
try:
check_access('package_create',context)
except NotAuthorized:
Expand Down
9 changes: 2 additions & 7 deletions ckan/lib/create_test_data.py
Expand Up @@ -319,15 +319,10 @@ def create(cls):
* Associated tags, etc etc
'''

publisher_group = model.Group(name=u'default_publisher',
title=u'Default publisher',
description=u'The default test publisher',
type='publisher')
model.Session.add(publisher_group)

cls.pkg_names = [u'annakarenina', u'warandpeace']
pkg1 = model.Package(name=cls.pkg_names[0])
pkg1.group = publisher_group
#pkg1.group = publisher_group
model.Session.add(pkg1)
pkg1.title = u'A Novel By Tolstoy'
pkg1.version = u'0.7a'
Expand Down Expand Up @@ -381,7 +376,7 @@ def create(cls):
tag1 = model.Tag(name=u'russian')
tag2 = model.Tag(name=u'tolstoy')

pkg2.group = publisher_group
#pkg2.group = publisher_group

# Flexible tag, allows spaces, upper-case,
# and all punctuation except commas
Expand Down
17 changes: 13 additions & 4 deletions ckan/lib/dictization/model_save.py
Expand Up @@ -213,6 +213,7 @@ def package_membership_list_save(group_dicts, package, context):
member_obj = model.Member(table_id = package.id,
table_name = 'package',
group = group,
group_id=group.id,
state = 'active')
session.add(member_obj)

Expand Down Expand Up @@ -256,7 +257,8 @@ def relationship_list_save(relationship_dicts, package, attr, context):
relationship_list.append(relationship)

def package_dict_save(pkg_dict, context):

import uuid

model = context["model"]
package = context.get("package")
allow_partial_update = context.get("allow_partial_update", False)
Expand All @@ -271,6 +273,9 @@ def package_dict_save(pkg_dict, context):

pkg = table_dict_save(pkg_dict, Package, context)

if not pkg.id:
pkg.id = str(uuid.uuid4())

package_resource_list_save(pkg_dict.get("resources", []), pkg, context)
package_tag_list_save(pkg_dict.get("tags", []), pkg, context)
package_membership_list_save(pkg_dict.get("groups", []), pkg, context)
Expand Down Expand Up @@ -316,14 +321,15 @@ def group_member_save(context, group_dict, member_table_name):
session.add(entity_member[entity_id])

for entity_id in set(entities.keys()) - set(entity_member.keys()):
member = Member(group=group, table_id=entity_id[0],
member = Member(group=group, group_id=group.id, table_id=entity_id[0],
table_name=member_table_name[:-1],
capacity=entity_id[1])
session.add(member)


def group_dict_save(group_dict, context):

import uuid

model = context["model"]
session = context["session"]
group = context.get("group")
Expand All @@ -334,8 +340,11 @@ def group_dict_save(group_dict, context):
group_dict["id"] = group.id

group = table_dict_save(group_dict, Group, context)
if not group.id:
group.id = str(uuid.uuid4())

context['group'] = group
print group_dict

group_member_save(context, group_dict, 'packages')
group_member_save(context, group_dict, 'users')
group_member_save(context, group_dict, 'groups')
Expand Down
4 changes: 2 additions & 2 deletions ckan/logic/action/create.py
Expand Up @@ -172,15 +172,15 @@ def group_create(context, data_dict):
rev.message = _(u'REST API: Create object %s') % data.get("name")

group = group_dict_save(data, context)

# TODO: Refactor to use new member for admin

if user:
admins = [model.User.by_name(user.decode('utf8'))]
else:
admins = []
model.setup_default_user_roles(group, admins)
# Needed to let extensions know the group id
model.Session.flush()

for item in PluginImplementations(IGroupController):
item.create(group)
if not context.get('defer_commit'):
Expand Down
13 changes: 1 addition & 12 deletions ckan/logic/auth/publisher/create.py
@@ -1,7 +1,7 @@
from ckan.logic.auth import get_package_object, get_group_object, get_authorization_group_object, \
get_user_object, get_resource_object
from ckan.logic.auth.publisher import _groups_intersect
from ckan.logic import check_access_old, NotFound
from ckan.logic import NotFound
from ckan.authz import Authorizer
from ckan.lib.base import _

Expand All @@ -10,17 +10,6 @@ def package_create(context, data_dict=None):
model = context['model']
user = context['user']

# We need the publisher group passed in as part of this request
try:
group = get_group_object( context )
except NotFound:
return {'success': False,
'msg': _('User %s not authorized to create a package without a group specified') % str(user)}

userobj = model.User.get( user )
if not _groups_intersect( userobj.get_groups('publisher'), group.get_groups('publisher') ):
return {'success': False, 'msg': _('User %s not authorized to create a package here') % str(user)}

return {'success': True}

def resource_create(context, data_dict):
Expand Down
17 changes: 9 additions & 8 deletions ckan/logic/auth/publisher/update.py
Expand Up @@ -12,12 +12,13 @@ def package_update(context, data_dict):
model = context['model']
user = context.get('user')
package = get_package_object(context, data_dict)

userobj = model.User.get( user )
if not userobj or \
not _groups_intersect( userobj.get_groups('publisher'), package.get_groups('publisher') ):
return {'success': False,
'msg': _('User %s not authorized to edit packages in these groups') % str(user)}
# group = get_group_object( context, data_dict )

# userobj = model.User.get( user )
# if not userobj or \
# not _groups_intersect( userobj.get_groups('publisher'), [group] ):
# return {'success': False,
# 'msg': _('User %s not authorized to edit packages in these groups') % str(user)}

return {'success': True}

Expand Down Expand Up @@ -46,10 +47,10 @@ def group_update(context, data_dict):
model = context['model']
user = context['user']
group = get_group_object(context, data_dict)

# Only allow package update if the user and package groups intersect
userobj = model.User.get( user )
if not _groups_intersect( userobj.get_groups('publisher', 'admin'), group.get_groups('publisher') ):
if not _groups_intersect( userobj.get_groups('publisher', 'admin'), [group] ):
return {'success': False, 'msg': _('User %s not authorized to edit this group') % str(user)}

return {'success': True}
Expand Down
1 change: 0 additions & 1 deletion ckan/model/group.py
Expand Up @@ -130,7 +130,6 @@ def as_dict(self, ref_package_by='name'):
return _dict

def add_package_by_name(self, package_name):
from pdb import set_trace; set_trace()
if not package_name:
return
package = Package.by_name(package_name)
Expand Down
5 changes: 2 additions & 3 deletions ckan/templates/group/layout.html
Expand Up @@ -26,7 +26,6 @@
<li py:attrs="{'class':'current-tab'} if c.action=='edit' else {}" py:if="h.check_access('group_update',{'id':c.group.id})">
<!-- TODO: We need to be able to change the URL below based on the type of the group -->
${h.subnav_named_route( c,h.icon('group_edit') + _('Edit'), c.group.type + '_action', action='edit', id=c.group.name )}
${h.subnav_link(c, h.icon('group_edit') + _('Edit'), controller='group', action='edit', id=c.group.name)}
</li>
<li py:attrs="{'class':'current-tab'} if c.action=='authz' else {}" py:if="h.check_access('group_edit_permissions',{'id':c.group.id})">
${h.subnav_named_route(c, h.icon('lock') + _('Authorization'), c.group.type + '_action', controller='group', action='authz', id=c.group.name)}
Expand All @@ -42,8 +41,8 @@
${h.subnav_link(c, h.icon('group') + _('List Groups'), controller='group', action='index')}
</li>
<li py:attrs="{'class':'current-tab'} if c.action=='new' else {}">
<span class="ckan-logged-in" style="display: none;">${ h.subnav_link(c, h.icon('group_add') + _('Add a Group'), controller='group', action='new')}</span>
<span class="ckan-logged-out">${h.subnav_link(c, h.icon('group_add') + _('Login to Add a Group'), controller='group', action='new')}</span>
<span class="ckan-logged-in" style="display: none;">${ h.subnav_link(c, h.icon('group_add') + _('Add a Publisher'), controller='group', action='new')}</span>
<span class="ckan-logged-out">${h.subnav_link(c, h.icon('group_add') + _('Login to Add a Publisher'), controller='group', action='new')}</span>
</li>
</ul>
</py:match>
Expand Down
2 changes: 1 addition & 1 deletion ckan/tests/functional/api/__init__.py
Expand Up @@ -31,5 +31,5 @@ def assert_dicts_equal_ignoring_ordering(dict1, dict2):
dicts = [copy.deepcopy(dict1), copy.deepcopy(dict2)]
for d in dicts:
d = change_lists_to_sets(d)
from nose.tools import set_trace; set_trace()
#from nose.tools import set_trace; set_trace()
assert_equal(dicts[0], dicts[1])
6 changes: 3 additions & 3 deletions ckan/tests/functional/api/model/test_relationships.py
Expand Up @@ -255,9 +255,9 @@ def test_update_relationship_incorrectly(self):
res = self.app.put(offset, params=postparams, status=[200],
extra_environ=self.extra_environ)
print res.body
assert '123' not in res.body
assert '456' not in res.body
assert '789' in res.body
assert '123' not in res.body, res.body
assert '456' not in res.body, res.body
assert '789' in res.body, res.body

def delete_annakarenina_parent_of_war_and_peace(self):
offset = self.relationship_offset('annakarenina', 'parent_of', 'warandpeace')
Expand Down
10 changes: 4 additions & 6 deletions ckan/tests/functional/api/test_action.py
Expand Up @@ -252,7 +252,7 @@ def test_05_user_show_edits(self):
assert 'timestamp' in edit
assert_equal(edit['state'], 'active')
assert_equal(edit['approved_timestamp'], None)
assert_equal(set(edit['groups']), set(('default_publisher', 'roger', 'david')))
assert_equal(set(edit['groups']), set(( 'roger', 'david')))
assert_equal(edit['state'], 'active')
assert edit['message'].startswith('Creating test data.')
assert_equal(set(edit['packages']), set(('warandpeace', 'annakarenina')))
Expand Down Expand Up @@ -547,7 +547,6 @@ def test_13_group_list(self):
'result': [
'david',
'roger',
'default_publisher'
],
'help': 'Returns a list of groups',
'success': True
Expand All @@ -562,8 +561,8 @@ def test_13_group_list(self):
assert res_obj['result'][0]['name'] == 'david'
assert res_obj['result'][0]['display_name'] == 'Dave\'s books'
assert res_obj['result'][0]['packages'] == 2
assert res_obj['result'][2]['name'] == 'roger', res_obj['result'][1]
assert res_obj['result'][2]['packages'] == 1
assert res_obj['result'][1]['name'] == 'roger', res_obj['result'][1]
assert res_obj['result'][1]['packages'] == 1
assert 'id' in res_obj['result'][0]
assert 'revision_id' in res_obj['result'][0]
assert 'state' in res_obj['result'][0]
Expand All @@ -573,8 +572,7 @@ def test_13_group_list_by_size(self):
res = self.app.post('/api/action/group_list',
params=postparams)
res_obj = json.loads(res.body)
assert_equal(sorted(res_obj['result']), ['david',
'roger'])
assert_equal(sorted(res_obj['result']), ['david','roger'])

def test_13_group_list_by_size_all_fields(self):
postparams = '%s=1' % json.dumps({'order_by': 'packages',
Expand Down
3 changes: 2 additions & 1 deletion ckan/tests/misc/test_auth_profiles.py
Expand Up @@ -46,5 +46,6 @@ def test_authorizer_count(self):
if not key.startswith('_'):
modules[module_root] = modules[module_root] + 1

assert modules['ckan.logic.auth'] == modules['ckan.logic.auth.publisher']
# Differs based on auth imports
assert modules['ckan.logic.auth'] == modules['ckan.logic.auth.publisher'] - 3, modules

0 comments on commit c88c900

Please sign in to comment.