diff --git a/ckan/controllers/group.py b/ckan/controllers/group.py index 033748193c5..2915b1b997c 100644 --- a/ckan/controllers/group.py +++ b/ckan/controllers/group.py @@ -192,7 +192,10 @@ def _read(self, id, limit): q = c.q = request.params.get('q', '') # Search within group - q += ' groups: "%s"' % c.group_dict.get('name') + if c.group_dict.get('is_organization'): + q += ' owner_org: "%s"' % c.group_dict.get('id') + else: + q += ' groups: "%s"' % c.group_dict.get('name') try: description_formatted = ckan.misc.MarkdownFormat().to_html( diff --git a/ckan/lib/app_globals.py b/ckan/lib/app_globals.py index 6b108d42a04..e98f975ca7d 100644 --- a/ckan/lib/app_globals.py +++ b/ckan/lib/app_globals.py @@ -109,9 +109,15 @@ def get_config_value(key, default=''): value = model.get_system_info(key) else: value = None + config_value = config.get(key) + # sort encodeings if needed + if isinstance(config_value, str): + try: + config_value = config_value.decode('utf-8') + except UnicodeDecodeError: + config_value = config_value.decode('latin-1') # we want to store the config the first time we get here so we can # reset them if needed - config_value = config.get(key) if key not in _CONFIG_CACHE: _CONFIG_CACHE[key] = config_value if value is not None: diff --git a/ckan/lib/dictization/model_dictize.py b/ckan/lib/dictization/model_dictize.py index ae1ed848f2c..70f9023f478 100644 --- a/ckan/lib/dictization/model_dictize.py +++ b/ckan/lib/dictization/model_dictize.py @@ -23,7 +23,7 @@ def group_list_dictize(obj_list, context, query = search.PackageSearchQuery() q = {'q': '+capacity:public' if not with_private else '*:*', - 'fl': 'groups', 'facet.field': ['groups'], + 'fl': 'groups', 'facet.field': ['groups', 'owner_org'], 'facet.limit': -1, 'rows': 1} query.run(q) @@ -42,7 +42,10 @@ def group_list_dictize(obj_list, context, group_dict['display_name'] = obj.display_name - group_dict['packages'] = query.facets['groups'].get(obj.name, 0) + if obj.is_organization: + group_dict['packages'] = query.facets['owner_org'].get(obj.id, 0) + else: + group_dict['packages'] = query.facets['groups'].get(obj.name, 0) if context.get('for_view'): if group_dict['is_organization']: @@ -336,7 +339,10 @@ def group_dictize(group, context): context) query = search.PackageSearchQuery() - q = {'q': 'groups:"%s" +capacity:public' % group.name, 'rows': 1} + if group.is_organization: + q = {'q': 'owner_org:"%s" +capacity:public' % group.id, 'rows': 1} + else: + q = {'q': 'groups:"%s" +capacity:public' % group.name, 'rows': 1} result_dict['package_count'] = query.run(q)['count'] result_dict['tags'] = tag_list_dictize( diff --git a/ckan/lib/search/index.py b/ckan/lib/search/index.py index f608f14e9d3..d77d7cbfa12 100644 --- a/ckan/lib/search/index.py +++ b/ckan/lib/search/index.py @@ -157,8 +157,10 @@ def index_package(self, pkg_dict, defer_commit=False): # if there is an owner_org we want to add this to groups for index # purposes - if pkg_dict.get('organization'): - pkg_dict['groups'].append(pkg_dict['organization']['name']) + if pkg_dict['owner_org'] and pkg_dict.get('organization'): + pkg_dict['organization'] = pkg_dict['organization']['name'] + else: + pkg_dict['organization'] = None # tracking diff --git a/ckan/logic/action/get.py b/ckan/logic/action/get.py index c7a9e78669e..19c18aad479 100644 --- a/ckan/logic/action/get.py +++ b/ckan/logic/action/get.py @@ -1323,7 +1323,7 @@ def package_search(context, data_dict): for key_, value_ in value.items(): new_facet_dict = {} new_facet_dict['name'] = key_ - if key == 'groups': + if key in ('groups', 'organization'): group = model.Group.get(key_) if group: new_facet_dict['display_name'] = group.display_name diff --git a/ckan/logic/auth/create.py b/ckan/logic/auth/create.py index f791b078a17..64d5cc3e150 100644 --- a/ckan/logic/auth/create.py +++ b/ckan/logic/auth/create.py @@ -106,6 +106,8 @@ def user_create(context, data_dict=None): def _check_group_auth(context, data_dict): + # FIXME This code is shared amoung other logic.auth files and should be + # somewhere better if not data_dict: return True diff --git a/ckan/logic/auth/update.py b/ckan/logic/auth/update.py index 896c6e33991..0a17ad43822 100644 --- a/ckan/logic/auth/update.py +++ b/ckan/logic/auth/update.py @@ -1,23 +1,26 @@ import ckan.logic as logic import ckan.new_authz as new_authz -from ckan.logic.auth import (get_package_object, get_resource_object, - get_group_object, get_user_object, - get_resource_object, get_related_object) -from ckan.logic.auth.create import _check_group_auth, package_relationship_create -from ckan.lib.base import _ -import ckan.new_authz +import ckan.logic.auth as logic_auth +from ckan.common import _ + +# FIXME this import is evil and should be refactored +from ckan.logic.auth.create import _check_group_auth + def make_latest_pending_package_active(context, data_dict): - return package_update(context, data_dict) + return new_authz.is_authorized('package_update', context, data_dict) + def package_update(context, data_dict): user = context.get('user') - package = get_package_object(context, data_dict) + package = logic_auth.get_package_object(context, data_dict) if package.owner_org: # if there is an owner org then we must have update_dataset # premission for that organization - check1 = new_authz.has_user_permission_for_group_or_org(package.owner_org, user, 'update_dataset') + check1 = new_authz.has_user_permission_for_group_or_org( + package.owner_org, user, 'update_dataset' + ) else: # If dataset is not owned then we can edit if config permissions allow if new_authz.auth_is_registered_user(): @@ -26,18 +29,23 @@ def package_update(context, data_dict): else: check1 = new_authz.check_config_permission('anon_create_dataset') if not check1: - return {'success': False, 'msg': _('User %s not authorized to edit package %s') % (str(user), package.id)} + return {'success': False, + 'msg': _('User %s not authorized to edit package %s') % + (str(user), package.id)} else: - check2 = _check_group_auth(context,data_dict) + check2 = _check_group_auth(context, data_dict) if not check2: - return {'success': False, 'msg': _('User %s not authorized to edit these groups') % str(user)} + return {'success': False, + 'msg': _('User %s not authorized to edit these groups') % + (str(user))} return {'success': True} + def resource_update(context, data_dict): model = context['model'] user = context.get('user') - resource = get_resource_object(context, data_dict) + resource = logic_auth.get_resource_object(context, data_dict) # check authentication against package query = model.Session.query(model.Package)\ @@ -46,60 +54,84 @@ def resource_update(context, data_dict): .filter(model.ResourceGroup.id == resource.resource_group_id) pkg = query.first() if not pkg: - raise logic.NotFound(_('No package found for this resource, cannot check auth.')) + raise logic.NotFound( + _('No package found for this resource, cannot check auth.') + ) pkg_dict = {'id': pkg.id} - authorized = package_update(context, pkg_dict).get('success') + authorized = new_authz.is_authorized('package_update', context, pkg_dict).get('success') if not authorized: - return {'success': False, 'msg': _('User %s not authorized to edit resource %s') % (str(user), resource.id)} + return {'success': False, + 'msg': _('User %s not authorized to edit resource %s') % + (str(user), resource.id)} else: return {'success': True} + def package_relationship_update(context, data_dict): - return package_relationship_create(context, data_dict) + return new_authz.is_authorized('package_relationship_create', + context, + data_dict) + def package_change_state(context, data_dict): user = context['user'] - package = get_package_object(context, data_dict) + package = logic_auth.get_package_object(context, data_dict) # use the logic for package_update - authorized = new_authz.is_authorized_boolean('package_update', context, data_dict) + authorized = new_authz.is_authorized_boolean('package_update', + context, + data_dict) if not authorized: - return {'success': False, 'msg': _('User %s not authorized to change state of package %s') % (str(user),package.id)} + return { + 'success': False, + 'msg': _('User %s not authorized to change state of package %s') % + (str(user), package.id) + } else: return {'success': True} + def group_update(context, data_dict): - group = get_group_object(context, data_dict) + group = logic_auth.get_group_object(context, data_dict) user = context['user'] - authorized = new_authz.has_user_permission_for_group_or_org( - group.id, user, 'update') + authorized = new_authz.has_user_permission_for_group_or_org(group.id, + user, + 'update') if not authorized: - return {'success': False, 'msg': _('User %s not authorized to edit group %s') % (str(user),group.id)} + return {'success': False, + 'msg': _('User %s not authorized to edit group %s') % + (str(user), group.id)} else: return {'success': True} + def organization_update(context, data_dict): - group = get_group_object(context, data_dict) + group = logic_auth.get_group_object(context, data_dict) user = context['user'] authorized = new_authz.has_user_permission_for_group_or_org( group.id, user, 'update') if not authorized: - return {'success': False, 'msg': _('User %s not authorized to edit organization %s') % (user, group.id)} + return {'success': False, + 'msg': _('User %s not authorized to edit organization %s') % + (user, group.id)} else: return {'success': True} + def related_update(context, data_dict): model = context['model'] user = context['user'] if not user: - return {'success': False, 'msg': _('Only the owner can update a related item')} + return {'success': False, + 'msg': _('Only the owner can update a related item')} - related = get_related_object(context, data_dict) - userobj = model.User.get( user ) + related = logic_auth.get_related_object(context, data_dict) + userobj = model.User.get(user) if not userobj or userobj.id != related.owner_id: - return {'success': False, 'msg': _('Only the owner can update a related item')} + return {'success': False, + 'msg': _('Only the owner can update a related item')} # Only sysadmins can change the featured field. if ('featured' in data_dict and data_dict['featured'] != related.featured): @@ -112,62 +144,88 @@ def related_update(context, data_dict): def group_change_state(context, data_dict): user = context['user'] - group = get_group_object(context, data_dict) + group = logic_auth.get_group_object(context, data_dict) # use logic for group_update - authorized = new_authz.is_authorized_boolean('group_update', context, data_dict) + authorized = new_authz.is_authorized_boolean('group_update', + context, + data_dict) if not authorized: - return {'success': False, 'msg': _('User %s not authorized to change state of group %s') % (str(user),group.id)} + return { + 'success': False, + 'msg': _('User %s not authorized to change state of group %s') % + (str(user), group.id) + } else: return {'success': True} + def group_edit_permissions(context, data_dict): user = context['user'] - group = get_group_object(context, data_dict) + group = logic_auth.get_group_object(context, data_dict) + + authorized = new_authz.has_user_permission_for_group_or_org(group.id, + user, + 'update') - if not new_authz.has_user_permission_for_group_or_org(group.id, user, 'update'): - return {'success': False, 'msg': _('User %s not authorized to edit permissions of group %s') % (str(user),group.id)} + if not authorized: + return {'success': False, + 'msg': _('User %s not authorized to edit permissions of group %s') % + (str(user), group.id)} else: return {'success': True} - def user_update(context, data_dict): user = context['user'] - user_obj = get_user_object(context, data_dict) + user_obj = logic_auth.get_user_object(context, data_dict) + user_reset = ('reset_key' in data_dict and + data_dict['reset_key'] == user_obj.reset_key) - if not (user == user_obj.name) and \ - not ('reset_key' in data_dict and data_dict['reset_key'] == user_obj.reset_key): - return {'success': False, 'msg': _('User %s not authorized to edit user %s') % (str(user), user_obj.id)} + if not (user == user_obj.name) and not user_reset: + return {'success': False, + 'msg': _('User %s not authorized to edit user %s') % + (str(user), user_obj.id)} return {'success': True} + def revision_change_state(context, data_dict): # FIXME currently only sysadmins can change state user = context['user'] + return { + 'success': False, + 'msg': _('User %s not authorized to change state of revision') % user + } - return {'success': False, 'msg': _('User %s not authorized to change state of revision' ) % user} def task_status_update(context, data_dict): # sysadmins only user = context['user'] - return {'success': False, 'msg': _('User %s not authorized to update task_status table') % user} + return { + 'success': False, + 'msg': _('User %s not authorized to update task_status table') % user + } + def vocabulary_update(context, data_dict): # sysadmins only return {'success': False} + def term_translation_update(context, data_dict): # sysadmins only user = context['user'] - return {'success': False, 'msg': _('User %s not authorized to update term_translation table') % user} + return { + 'success': False, + 'msg': _('User %s not authorized to update term_translation table') % user + } def dashboard_mark_activities_old(context, data_dict): - # FIXME: This should go through check_access() not call is_authorized() - # directly, but wait until 2939-orgs is merged before fixing this. - return ckan.new_authz.is_authorized('dashboard_activity_list', - context, data_dict) + return new_authz.is_authorized('dashboard_activity_list', + context, + data_dict) def send_email_notifications(context, data_dict): @@ -181,18 +239,22 @@ def package_update_rest(context, data_dict): model = context['model'] user = context['user'] if user in (model.PSEUDO_USER__VISITOR, ''): - return {'success': False, 'msg': _('Valid API key needed to edit a package')} + return {'success': False, + 'msg': _('Valid API key needed to edit a package')} + + return new_authz.is_authorized('package_update', context, data_dict) - return package_update(context, data_dict) def group_update_rest(context, data_dict): model = context['model'] user = context['user'] if user in (model.PSEUDO_USER__VISITOR, ''): - return {'success': False, 'msg': _('Valid API key needed to edit a group')} + return {'success': False, + 'msg': _('Valid API key needed to edit a group')} return group_update(context, data_dict) + def package_owner_org_update(context, data_dict): # sysadmins only return {'success': False} diff --git a/ckan/public/base/less/module.less b/ckan/public/base/less/module.less index fe8b5cf7598..1f2f791da4c 100644 --- a/ckan/public/base/less/module.less +++ b/ckan/public/base/less/module.less @@ -3,6 +3,7 @@ } .module-heading { + .clearfix; margin: 0; padding: 7px @gutterX; font-size: 14px; diff --git a/ckan/templates/organization/bulk_process.html b/ckan/templates/organization/bulk_process.html index 445aaf81099..7e05b0b4261 100644 --- a/ckan/templates/organization/bulk_process.html +++ b/ckan/templates/organization/bulk_process.html @@ -6,7 +6,8 @@

{{ _('Edit datasets') }}

-

+ {% link_for _('Add Dataset'), controller='package', action='new', group=c.group_dict.id, class_='btn pull-right', icon='plus-sign-alt' %} +

{%- if c.page.item_count -%} {{ c.page.item_count }} datasets{{ _(" found for \"{query}\"").format(query=c.q) if c.q }} {%- elif request.params -%} diff --git a/ckan/templates/organization/members.html b/ckan/templates/organization/members.html index c4be4fbb029..7bb5b648349 100644 --- a/ckan/templates/organization/members.html +++ b/ckan/templates/organization/members.html @@ -4,8 +4,9 @@ {% block primary_content_inner %}
-

{{ _('Members') }}

- + {% link_for _('Add Member'), controller='organization', action='member_new', id=c.group_dict.id, class_='btn pull-right', icon='plus-sign-alt' %} +

{{ _('{0} members'.format(c.members|length)) }}

+
@@ -36,8 +37,5 @@

{{ _('Members') }}

{% endfor %}
-
- {% link_for _('Add member'), controller='organization', action='member_new', id=c.group_dict.id, class_='btn btn-primary' %} -
{% endblock %}