def resource_delete(context, data_dict): ''' Nearly plain copying of resource_delete: CKAN calls local package_delete, thus passing our local version of it. :param context: context :param data_dict: data_dict :return: dict with success and optional msg ''' model = context['model'] user = context.get('user') resource = logic_auth.get_resource_object(context, data_dict) # check authentication against package pkg = model.Package.get(resource.package_id) if not pkg: raise NotFound(_('No package found for this resource, cannot check auth.')) pkg_dict = {'id': pkg.id} authorized = package_delete(context, pkg_dict).get('success') if not authorized: return {'success': False, 'msg': _('User %s not authorized to delete resource %s') % (user, resource.id)} else: return {'success': True}
def resource_show(context, data_dict): # This function is needed since CKAN resource_show function uses the default package_show # function instead of the one defined in the plugin. # A bug is openend in order to be able to remove this function # https://github.com/ckan/ckan/issues/1818 # It's fixed now, so this function can be deleted when the new version is released. _model = context['model'] user = context.get('user') resource = logic_auth.get_resource_object(context, data_dict) # check authentication against package query = _model.Session.query(_model.Package)\ .join(_model.ResourceGroup)\ .join(_model.Resource)\ .filter(_model.ResourceGroup.id == resource.resource_group_id) pkg = query.first() if not pkg: raise tk.ObjectNotFound(_('No package found for this resource, cannot check auth.')) pkg_dict = {'id': pkg.id} authorized = package_show(context, pkg_dict).get('success') if not authorized: return {'success': False, 'msg': _('User %s not authorized to read resource %s') % (user, resource.id)} else: return {'success': True}
def resource_create(context, data_dict): model = context['model'] user = context.get('user') package_id = data_dict.get('package_id') if not package_id and data_dict.get('id'): # This can happen when auth is deferred, eg from `resource_view_create` resource = logic_auth.get_resource_object(context, data_dict) package_id = resource.package_id if not package_id: raise logic.NotFound( _('No dataset id provided, cannot check auth.') ) # check authentication against package pkg = model.Package.get(package_id) if not pkg: raise logic.NotFound( _('No package found for this resource, cannot check auth.') ) pkg_dict = {'id': pkg.id} authorized = authz.is_authorized('package_update', context, pkg_dict).get('success') if not authorized: return {'success': False, 'msg': _('User %s not authorized to create resources on dataset %s') % (str(user), package_id)} else: return {'success': True}
def resource_update(context, data_dict): model = context['model'] user = context.get('user') resource = logic_auth.get_resource_object(context, data_dict) # check authentication against package query = model.Session.query(model.Package)\ .join(model.ResourceGroup)\ .join(model.Resource)\ .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.') ) pkg_dict = {'id': pkg.id} 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)} else: return {'success': True}
def resource_view_delete(fb, context, data_dict): user = context['auth_user_obj'] resource_view = get_resource_view_object(context, data_dict) resource = get_resource_object(context, {'id': resource_view.resource_id}) if user_owns_package_as_member(user, resource.resource_group.package): return {'success': True} elif user_is_member_of_package_org(user, resource.resource_group.package): return {'success': False} return fb(context, data_dict)
def resource_update(fb, context, data_dict): user = context['auth_user_obj'] resource = get_resource_object(context, data_dict) package = resource.resource_group.package if user_owns_package_as_member(user, package): return {'success': True} elif user_is_member_of_package_org(user, package): return {'success': False} return fb(context, data_dict)
def resource_view_update(context, data_dict): user = context['auth_user_obj'] resource_view = get_resource_view_object(context, data_dict) resource = get_resource_object(context, {'id': resource_view.resource_id}) if user_owns_package_as_member(user, resource.resource_group.package): return {'success': True} elif user_is_member_of_package_org(user, resource.resource_group.package): return {'success': False} fallback = get_default_auth('update', 'resource_view_update') return fallback(context, data_dict)
def resource_delete(context, data_dict): user = context['auth_user_obj'] resource = get_resource_object(context, data_dict) package = resource.resource_group.package if user_owns_package_as_member(user, package): return {'success': True} elif user_is_member_of_package_org(user, package): return {'success': False} fallback = get_default_auth('delete', 'resource_delete') return fallback(context, data_dict)
def resource_show(context, data_dict): """ Resource show permission checks the user group if the package state is deleted """ model = context['model'] user = context.get('user') resource = get_resource_object(context, data_dict) package = resource.resource_group.package if package.state == 'deleted': userobj = model.User.get( user ) if not userobj: return {'success': False, 'msg': _('User %s not authorized to read resource %s') % (str(user),package.id)} if not _groups_intersect( userobj.get_groups('organization'), package.get_groups('organization') ): return {'success': False, 'msg': _('User %s not authorized to read package %s') % (str(user),package.id)} pkg_dict = {'id': package.id} return package_show(context, pkg_dict)
def test_get_resource_object_with_id(self): user_name = helpers.call_action('get_site_user')['name'] dataset = helpers.call_action('package_create', context={'user': user_name}, name='test_dataset') resource = helpers.call_action('resource_create', context={'user': user_name}, package_id=dataset['id'], url='http://foo') context = {'model': core_model} obj = logic_auth.get_resource_object(context, {'id': resource['id']}) assert obj.id == resource['id'] assert context['resource'] == obj
def resource_delete(context, data_dict): model = context['model'] user = context.get('user') resource = get_resource_object(context, data_dict) # check authentication against package pkg = model.Package.get(resource.package_id) if not pkg: raise logic.NotFound(_('No package found for this resource, cannot check auth.')) pkg_dict = {'id': pkg.id} authorized = authz.is_authorized('package_delete', context, pkg_dict).get('success') if not authorized: return {'success': False, 'msg': _('User %s not authorized to delete resource %s') % (user, resource.id)} else: return {'success': True}
def edit_resource(context, data_dict): ''' Check if a user is allowed edit a resource. :param context: context :param data_dict: data dictionary :rype: dictionary ''' auth_dict = update.resource_update(context, data_dict) resource = logic_auth.get_resource_object(context, data_dict) if resource.resource_type == settings.RESOURCE_TYPE_DATASET: return {'success': False, 'msg': _('Resource %s not editable') % (data_dict['id'])} else: return auth_dict
def resource_show(context, data_dict): model = context["model"] user = context.get("user") resource = get_resource_object(context, data_dict) # check authentication against package pkg = model.Package.get(resource.package_id) if not pkg: raise logic.NotFound(_("No package found for this resource, cannot check auth.")) pkg_dict = {"id": pkg.id} authorized = authz.is_authorized("package_show", context, pkg_dict).get("success") if not authorized: return {"success": False, "msg": _("User %s not authorized to read resource %s") % (user, resource.id)} else: return {"success": True}
def resource_show(context, data_dict): model = context['model'] user = context.get('user') resource = get_resource_object(context, data_dict) # check authentication against package pkg = model.Package.get(resource.package_id) if not pkg: raise logic.NotFound(_('No package found for this resource, cannot check auth.')) pkg_dict = {'id': pkg.id} authorized = authz.is_authorized('package_show', context, pkg_dict).get('success') if not authorized: return {'success': False, 'msg': _('User %s not authorized to read resource %s') % (user, resource.id)} else: return {'success': True}
def resource_update(context, data_dict): """ Update resource permission checks the user is in a group that the resource's package is also a member of. """ model = context['model'] user = context.get('user') resource = get_resource_object(context, data_dict) userobj = model.User.get( user ) if not userobj: return {'success': False, 'msg': _('User %s not authorized to edit resources in this package') % str(user)} if not _groups_intersect( userobj.get_groups('publisher'), resource.resource_group.package.get_groups('publisher') ): return {'success': False, 'msg': _('User %s not authorized to edit resources in this package') % str(user)} return {'success': True}
def resource_show_ext(context, data_dict): model = context['model'] user = context.get('user') userobj = context.get('auth_user_obj') resource = get_resource_object(context, data_dict) # check authentication against package pkg = model.Package.get(resource.package_id) if not pkg: raise logic.NotFound( _('No package found for this resource, cannot check auth.')) pkg_dict = {'id': pkg.id} authorized = authz.is_authorized('package_show', context, pkg_dict).get('success') if not authorized: return { 'success': False, 'msg': _('User %s not authorized to read resource %s') % (user, resource.id) } if 'res_access' in data_dict: res_access = data_dict['res_access'] else: res_access = True if userobj == None: mydataset = False else: mydataset = (userobj.id == pkg.creator_user_id) if not (mydataset or res_access): return { 'success': False, 'msg': _('User %s not authorized to read resource (access not public) %s') % (user, resource.id) } return {'success': True}
def test_get_resource_object_with_id(self): user_name = helpers.call_action("get_site_user")["name"] dataset = helpers.call_action("package_create", context={"user": user_name}, name="test_dataset") resource = helpers.call_action( "resource_create", context={"user": user_name}, package_id=dataset["id"], url="http://foo", ) context = {"model": core_model} obj = logic_auth.get_resource_object(context, {"id": resource["id"]}) assert obj.id == resource["id"] assert context["resource"] == obj
def resource_show(context, data_dict): user = context.get('user') user_obj = context.get('auth_user_obj') resource = logic_auth.get_resource_object(context, data_dict) # check authentication against package package_dict = {'id': resource.package_id} package = logic_auth.get_package_object(context, package_dict) if not package: raise tk.ObjectNotFound(_('No package found for this resource, cannot check auth.')) if package and user_obj and package.creator_user_id == user_obj.id: return {'success': True} # active packages can only be seen by its owners if package.state == 'active': # anyone can see a public package if not package.private: return {'success': True} # if the user has rights to read in the organization or in the group if package.owner_org: authorized = authz.has_user_permission_for_group_or_org( package.owner_org, user, 'read') else: authorized = False if not authorized: # Init the model db.init_db(context['model']) # Branch not executed if the database return an empty list if db.AllowedUser.get(package_id=package.id, user_name=user): authorized = True if not authorized: return {'success': False, 'msg': _('User %s not authorized to read resource %s') % (user, resource.id)} else: return {'success': True} else: return {'success': False, 'msg': _('User %s not authorized to read resource %s') % (user, resource.id)}
def resource_view_create(context, data_dict): user = context['auth_user_obj'] # data_dict provides 'resource_id', while get_resource_object expects 'id'. This is not consistent with the rest of # the API - so future proof it by catering for both cases in case the API is made consistent (one way or the other) # later. if data_dict and 'resource_id' in data_dict: dc = {'id': data_dict['resource_id'], 'resource_id': data_dict['resource_id']} elif data_dict and 'id' in data_dict: dc = {'id': data_dict['id'], 'resource_id': data_dict['id']} else: dc = data_dict resource = get_resource_object(context, dc) if user_owns_package_as_member(user, resource.resource_group.package): return {'success': True} elif user_is_member_of_package_org(user, resource.resource_group.package): return {'success': False} fallback = get_default_auth('create', 'resource_view_create') return fallback(context, data_dict)
def resource_view_create(context, data_dict): user = context['auth_user_obj'] # data_dict provides 'resource_id', while get_resource_object expects 'id'. This is not consistent with the rest of # the API - so future proof it by catering for both cases in case the API is made consistent (one way or the other) # later. if data_dict and 'resource_id' in data_dict: dc = {'id': data_dict['resource_id'], 'resource_id': data_dict['resource_id']} elif data_dict and 'id' in data_dict: dc = {'id': data_dict['id'], 'resource_id': data_dict['id']} else: dc = data_dict resource = get_resource_object(context, dc) if user_owns_package_as_member(user, resource.package): return {'success': True} elif user_is_member_of_package_org(user, resource.package): return {'success': False} fallback = get_default_auth('create', 'resource_view_create') return fallback(context, data_dict)
def edit_resource(context, data_dict): ''' Check if a user is allowed edit a resource. :param context: context :param data_dict: data dictionary :rype: dictionary ''' auth_dict = update.resource_update(context, data_dict) resource = logic_auth.get_resource_object(context, data_dict) if resource.resource_type == settings.RESOURCE_TYPE_DATASET: return { 'success': False, 'msg': _('Resource %s not editable') % (data_dict['id']) } else: return auth_dict
def resource_delete(next_auth, context, data_dict): ''' :param next_auth: :param context: :param data_dict: ''' user = context['auth_user_obj'] resource = get_resource_object(context, data_dict) package = resource.package if user_owns_package_as_member(user, package): return { 'success': True } elif user_is_member_of_package_org(user, package): return { 'success': False } return next_auth(context, data_dict)
def resource_update(context, data_dict): model = context['model'] user = context.get('user') resource = get_resource_object(context, data_dict) # check authentication against package query = model.Session.query(model.Package)\ .join(model.ResourceGroup)\ .join(model.Resource)\ .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.')) pkg_dict = {'id': pkg.id} 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)} else: return {'success': True}
def resource_show(context, data_dict): '''Override ckan's auth function ''' resource_id = data_dict.get('id') user = context.get('user') if has_user_record_for_resource(resource_id, user): if has_user_permission_for_resource(resource_id, user, 'read'): return {'success': True} return {'success': False} resourceObj = get_resource_object(context, data_dict) packageObj = get_package_object(context, {'id': resourceObj.package_id}) if packageObj.private: userobj = model.User.get(user) if userobj: org_ids = userobj.get_group_ids('organization') if packageObj.owner_org in org_ids: return {'success': True} return {'success': False} return ckan_package_show(context, {'id': resourceObj.package_id})
def restricted_resource_show(context, data_dict=None): # Ensure user who can edit the package can see the resource resource = data_dict.get('resource', context.get('resource', {})) if not resource: resource = logic_auth.get_resource_object(context, data_dict) if type(resource) is not dict: resource = resource.as_dict() if authz.is_authorized('package_update', context, { 'id': resource.get('package_id') }).get('success'): return ({'success': True}) user_name = logic.restricted_get_username_from_context(context) package = data_dict.get('package', {}) if not package: model = context['model'] package = model.Package.get(resource.get('package_id')) package = package.as_dict() return (logic.restricted_check_user_resource_access( user_name, resource, package))
def initiatives_resource_show(context, data_dict=None): resource = data_dict.get("resource", context.get("resource", {})) if not resource: resource = logic_auth.get_resource_object(context, data_dict) if type(resource) is not dict: resource = resource.as_dict() # Ensure user who can edit the package can see the resource if authz.is_authorized("package_update", context, { "id": resource.get("package_id") }).get("success"): return {"success": True} user_name = logic.initiatives_get_username_from_context(context) package = data_dict.get("package", {}) if not package: model = context["model"] package = model.Package.get(resource.get("package_id")) package = package.as_dict() return logic.initiatives_check_user_resource_access( user_name, resource, package)
def resource_show(context, data_dict): model = context["model"] user = context.get("user") resource = get_resource_object(context, data_dict) # check authentication against package query = ( model.Session.query(model.Package) .join(model.ResourceGroup) .join(model.Resource) .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.")) pkg_dict = {"id": pkg.id} authorized = package_show(context, pkg_dict).get("success") if not authorized: return {"success": False, "msg": _("User %s not authorized to read resource %s") % (user, resource.id)} else: return {"success": True}
def resource_create(context, data_dict): model = context['model'] user = context.get('user') package_id = data_dict.get('package_id') if not package_id and data_dict.get('id'): # This can happen when auth is deferred, eg from `resource_view_create` resource = logic_auth.get_resource_object(context, data_dict) package_id = resource.package_id if not package_id: raise logic.NotFound(_('No dataset id provided, cannot check auth.')) # check authentication against package pkg = model.Package.get(package_id) if not pkg: raise logic.NotFound( _('No package found for this resource, cannot check auth.')) pkg_dict = {'id': pkg.id} authorized = authz.is_authorized('package_update', context, pkg_dict).get('success') if not authorized: return { 'success': False, 'msg': _('User %s not authorized to create resources on dataset %s') % (str(user), package_id) } else: if authz.config.get('ckan.gov_theme.is_back'): return {'success': True} else: return {'success': False}
def resource_view_show(context, data_dict): resourceObj = get_resource_object(context, data_dict) return resource_show(context, {'id': resourceObj.id})
def resource_tracker_create(context, data_dict): '''Authorization check for creating a log for a resource ''' resource_id = data_dict.get('el') resourceObj = get_resource_object(context, {'id': resource_id}) return auth.resource_show(context, {'id': resourceObj.id})
def resource_download(context, data_dict): ''' This is a new auth function that specifically controls access to the download of a resource file, as opposed to seeing the metadata of a resource (handled by `resource_show` If this resource is marked as public or private in the custom visibility field, the authorization check is deferred to `resource_show` as the standard logic applies (we assume that the necessary validators are applied to keep `visibility` and `private` fields in sync). If this resource is marked as `restricted` then only users belonging to the dataset organization can download the file. ''' # Prepare all the parts context['model'] = context.get('model') or model user = context.get('user') resource = get_resource_object(context, data_dict) dataset = toolkit.get_action('package_show')({ 'ignore_auth': True }, { 'id': resource.package_id }) visibility = resource.extras.get('visibility') # Use default check user_id = getattr(context.get('auth_user_obj'), 'id', None) is_deposit = dataset.get('type') == 'deposited-dataset' if is_deposit: is_depositor = dataset.get('creator_user_id') == user_id curators = [u['id'] for u in helpers.get_data_curation_users(dataset)] is_curator = user_id in curators else: is_depositor = False is_curator = False if not user or is_depositor or is_curator or not visibility or visibility != 'restricted': try: toolkit.check_access('resource_show', context, data_dict) return {'success': True} except toolkit.NotAuthorized: return {'success': False} # Restricted visibility (public metadata but private downloads) if dataset.get('owner_org'): user_orgs = toolkit.get_action('organization_list_for_user')( { 'ignore_auth': True }, { 'id': user }) user_in_owner_org = any(org['id'] == dataset['owner_org'] for org in user_orgs) if user_in_owner_org: return {'success': True} # Check if the user is a dataset collaborator action = toolkit.get_action('package_collaborator_list_for_user') if user and action: datasets = action(context, {'id': user}) return { 'success': resource.package_id in [d['package_id'] for d in datasets] } return {'success': False}