From 660fc8194233a2b746c239a7b731218d66cf53ec Mon Sep 17 00:00:00 2001 From: kindly Date: Sun, 29 Sep 2013 17:56:01 +0100 Subject: [PATCH 01/10] basic group add remove done with out any styling --- ckan/config/routing.py | 3 ++ ckan/controllers/package.py | 59 +++++++++++++++++++++++ ckan/logic/action/create.py | 3 +- ckan/logic/action/delete.py | 3 +- ckan/logic/action/get.py | 3 +- ckan/logic/auth/create.py | 21 ++++++++ ckan/new_authz.py | 4 +- ckan/templates/package/group_list.html | 32 ++++++++++++ ckan/templates/package/read_base.html | 1 + ckan/templates/snippets/package_list.html | 2 +- 10 files changed, 123 insertions(+), 8 deletions(-) create mode 100644 ckan/templates/package/group_list.html diff --git a/ckan/config/routing.py b/ckan/config/routing.py index 0fbb02bb886..8bb15623082 100644 --- a/ckan/config/routing.py +++ b/ckan/config/routing.py @@ -230,6 +230,7 @@ def make_map(): 'history_ajax', 'follow', 'activity', + 'groups', 'unfollow', 'delete', 'api_data', @@ -239,6 +240,8 @@ def make_map(): m.connect('dataset_activity', '/dataset/activity/{id}', action='activity', ckan_icon='time') m.connect('/dataset/activity/{id}/{offset}', action='activity') + m.connect('dataset_groups', '/dataset/groups/{id}', + action='groups', ckan_icon='group') m.connect('/dataset/{id}.{format}', action='read') m.connect('dataset_read', '/dataset/{id}', action='read', ckan_icon='sitemap') diff --git a/ckan/controllers/package.py b/ckan/controllers/package.py index d1852cd95b7..7feab9c2f95 100644 --- a/ckan/controllers/package.py +++ b/ckan/controllers/package.py @@ -1246,6 +1246,65 @@ def followers(self, id=None): return render('package/followers.html') + def groups(self, id): + context = {'model': model, 'session': model.Session, + 'user': c.user or c.author, 'for_view': True, + 'auth_user_obj': c.userobj} + data_dict = {'id': id} + try: + c.pkg_dict = get_action('package_show')(context, data_dict) + except NotFound: + abort(404, _('Dataset not found')) + except NotAuthorized: + abort(401, _('Unauthorized to read dataset %s') % id) + + if request.method == 'POST': + new_group = request.POST.get('group_added') + if new_group: + data_dict = {"id": new_group, + "object": id, + "object_type": 'package', + "capacity": 'public'} + try: + get_action('member_create')(context, data_dict) + except NotFound: + abort(404, _('Group not found')) + + removed_group = request.POST.get('group_removed') + if removed_group: + data_dict = {"id": removed_group, + "object": id, + "object_type": 'package'} + + try: + get_action('member_delete')(context, data_dict) + except NotFound: + abort(404, _('Group not found')) + redirect(h.url_for(controller='package', + action='groups', id=id)) + + + + context['is_member'] = True + users_groups = get_action('group_list_authz')(context, data_dict) + + pkg_group_ids = set(group['id'] for group + in c.pkg_dict.get('groups', [])) + user_group_ids = set(group['id'] for group + in users_groups) + + c.group_dropdown = [[group['id'], group['display_name']] + for group in users_groups if + group['id'] not in pkg_group_ids] + + for group in c.pkg_dict.get('groups', []): + ## this could be pushed back to package dictize + group['display_name'] = group.get('titile') or group.get('name') + group['user_member'] = (group['id'] in user_group_ids) + + + return render('package/group_list.html') + def activity(self, id): '''Render this package's public activity stream page.''' diff --git a/ckan/logic/action/create.py b/ckan/logic/action/create.py index baac5a2154c..d868aac62b4 100644 --- a/ckan/logic/action/create.py +++ b/ckan/logic/action/create.py @@ -446,8 +446,7 @@ def member_create(context, data_dict=None): if not obj: raise NotFound('%s was not found.' % obj_type.title()) - # User must be able to update the group to add a member to it - _check_access('group_update', context, data_dict) + _check_access('member_create', context, data_dict) # Look up existing, in case it exists member = model.Session.query(model.Member).\ diff --git a/ckan/logic/action/delete.py b/ckan/logic/action/delete.py index 60ea1a5bed8..1d3b5fe879c 100644 --- a/ckan/logic/action/delete.py +++ b/ckan/logic/action/delete.py @@ -203,8 +203,7 @@ def member_delete(context, data_dict=None): if not obj: raise NotFound('%s was not found.' % obj_type.title()) - # User must be able to update the group to remove a member from it - _check_access('group_update', context, data_dict) + _check_access('member_create', context, data_dict) member = model.Session.query(model.Member).\ filter(model.Member.table_name == obj_type).\ diff --git a/ckan/logic/action/get.py b/ckan/logic/action/get.py index 4f4b2fb57ee..89f2ad97c55 100644 --- a/ckan/logic/action/get.py +++ b/ckan/logic/action/get.py @@ -331,6 +331,7 @@ def translated_capacity(capacity): def _group_or_org_list(context, data_dict, is_org=False): model = context['model'] + user = context['user'] api = context.get('api_version') groups = data_dict.get('groups') ref_group_by = 'id' if api == 2 else 'name' @@ -460,7 +461,7 @@ def group_list_authz(context, data_dict): _check_access('group_list_authz',context, data_dict) sysadmin = new_authz.is_sysadmin(user) - roles = ckan.new_authz.get_roles_with_permission('edit_group') + roles = ckan.new_authz.get_roles_with_permission('manage_group') if not roles: return [] user_id = new_authz.get_user_id_for_username(user, allow_none=True) diff --git a/ckan/logic/auth/create.py b/ckan/logic/auth/create.py index a18485c2c57..c6dd89527d8 100644 --- a/ckan/logic/auth/create.py +++ b/ckan/logic/auth/create.py @@ -1,5 +1,6 @@ import ckan.logic as logic import ckan.new_authz as new_authz +import ckan.logic.auth as logic_auth from ckan.common import _ @@ -197,3 +198,23 @@ def organization_member_create(context, data_dict): def group_member_create(context, data_dict): return _group_or_org_member_create(context, data_dict) + +def member_create(context, data_dict): + group = logic_auth.get_group_object(context, data_dict) + user = context['user'] + + # User must be able to update the group to add a member to it + permission = 'update' + # However if the user is member of group then they can add/remove datasets + if not group.is_organization and data_dict.get('object_type') == 'package': + permission = 'manage_group' + + authorized = new_authz.has_user_permission_for_group_or_org(group.id, + user, + permission) + if not authorized: + return {'success': False, + 'msg': _('User %s not authorized to edit group %s') % + (str(user), group.id)} + else: + return {'success': True} diff --git a/ckan/new_authz.py b/ckan/new_authz.py index abeb8f9b57a..af224ee67b7 100644 --- a/ckan/new_authz.py +++ b/ckan/new_authz.py @@ -183,8 +183,8 @@ def is_authorized(action, context, data_dict=None): # these are the permissions that roles have ROLE_PERMISSIONS = OrderedDict([ ('admin', ['admin']), - ('editor', ['read', 'delete_dataset', 'create_dataset', 'update_dataset']), - ('member', ['read']), + ('editor', ['read', 'delete_dataset', 'create_dataset', 'update_dataset', 'manage_group']), + ('member', ['read', 'manage_group']), ]) diff --git a/ckan/templates/package/group_list.html b/ckan/templates/package/group_list.html new file mode 100644 index 00000000000..63440bfacb7 --- /dev/null +++ b/ckan/templates/package/group_list.html @@ -0,0 +1,32 @@ +{% import 'macros/form.html' as form %} +{% extends "package/read_base.html" %} + +{% block primary_content_inner %} +

{% block page_heading %}{{ _('Groups {dataset} belongs to.').format(dataset=h.dataset_display_name(c.pkg)) }}{% endblock %}

+ + {% if c.group_dropdown %} +
+ + +
+ {% endif %} + + + + +{% endblock %} diff --git a/ckan/templates/package/read_base.html b/ckan/templates/package/read_base.html index 9cf73a5c5a1..0e4b3775f43 100644 --- a/ckan/templates/package/read_base.html +++ b/ckan/templates/package/read_base.html @@ -22,6 +22,7 @@ {% block content_primary_nav %} {{ h.build_nav_icon('dataset_read', _('Dataset'), id=pkg.name) }} + {{ h.build_nav_icon('dataset_groups', _('Groups'), id=pkg.name) }} {{ h.build_nav_icon('dataset_activity', _('Activity Stream'), id=pkg.name) }} {{ h.build_nav_icon('related_list', _('Related'), id=pkg.name) }} {% endblock %} diff --git a/ckan/templates/snippets/package_list.html b/ckan/templates/snippets/package_list.html index 99aed748242..75213d535a3 100644 --- a/ckan/templates/snippets/package_list.html +++ b/ckan/templates/snippets/package_list.html @@ -15,7 +15,7 @@ #} {% if packages %} -