def user_roles_get(context, data_dict): '''Get user roles parameter. :param user_id: id of the user you want to get roles for. :type user_id: string ''' l.check_access('user_roles', context, data_dict) data, errors = df.validate(data_dict, user_roles_delete_schema(), context) if errors: raise t.ValidationError(errors) m = context.get('model') user_obj = m.User.get(data.get('user_id')) if user_obj is None: raise l.NotFound("No such user") user_id = user_obj.id user_role = UserRoles.get(user_id) if user_role is None: return user_role if not user_role: raise l.NotFound("User has no roles") out = table_dictize(user_role, context) return out
def member_request(context, data_dict): logic.check_access('member_request_show', context, data_dict) mrequest_id = data_dict.get('mrequest_id', None) membership = model.Session.query(model.Member).get(mrequest_id) if not membership: raise logic.NotFound("Member request not found") # Return most current instance from memberrequest table member_request = model.Session.query(MemberRequest).filter( MemberRequest.membership_id == mrequest_id).order_by( desc(MemberRequest.request_date)).limit(1).first() if not member_request: raise logic.NotFound( "Member request associated with membership not found") member_dict = {} member_dict['id'] = mrequest_id member_dict['organization_name'] = membership.group.name member_dict['group_id'] = membership.group_id member_dict['role'] = member_request.role member_dict['state'] = member_request.status member_dict['request_date'] = member_request.request_date.strftime( "%d - %b - %Y") member_dict['user_id'] = membership.table_id return member_dict
def member_request(context, data_dict): """ :param context: context object :param data_dict: data dictionary :type context: dict :type data_dict: dict """ logic.check_access('member_request_show', context, data_dict) mrequest_id = data_dict.get('mrequest_id', None) membership = model.Session.query(model.Member).get(mrequest_id) if not membership or membership.state != 'pending': raise logic.NotFound("Member request not found") # Return most current instance from memberrequest table member_request_obj = model.Session.query(MemberRequest).filter( MemberRequest.membership_id == mrequest_id).order_by( 'request_date desc').limit(1).first() if not member_request_obj or member_request_obj.status != 'pending': raise logic.NotFound( "Member request associated with membership not found") member_dict = { 'id': mrequest_id, 'organization_name': membership.group.name, 'group_id': membership.group_id, 'role': member_request_obj.role, 'state': 'pending', 'request_date': member_request_obj.request_date.strftime("%d - %b - %Y"), 'user_id': membership.table_id } return member_dict
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 taxonomy_delete(context, data_dict): """ Delete the specific taxonomy, and as a result, all of the terms within it. :returns: The newly deleted taxonomy :rtype: A dictionary """ _check_access('taxonomy_delete', context, data_dict) model = context['model'] name = logic.get_or_bust(data_dict, 'id') taxonomy = Taxonomy.get(name) if not taxonomy: raise logic.NotFound() terms = model.Session.query(TaxonomyTerm)\ .filter(TaxonomyTerm.taxonomy == taxonomy) map(model.Session.delete, terms.all()) model.Session.delete(taxonomy) model.Session.commit() return taxonomy.as_dict()
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 inventory_resource_show(context, data_dict): model = context['model'] user = User.by_name(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.')) if user is None: if pkg.private: return {'success': False} else: return {'success': True} else: 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 taxonomy_update(context, data_dict): """ Updates an existing taxonomy. title, name and uri are required :returns: The newly updated taxonomy :rtype: A dictionary """ _check_access('taxonomy_update', context, data_dict) model = context['model'] id = logic.get_or_bust(data_dict, 'id') name = logic.get_or_bust(data_dict, 'name') title = logic.get_or_bust(data_dict, 'title') uri = logic.get_or_bust(data_dict, 'uri') tax = Taxonomy.get(id) if not tax: raise logic.NotFound() tax.name = name tax.title = title tax.uri = uri model.Session.add(tax) model.Session.commit() return tax.as_dict()
def taxonomy_show(context, data_dict): """ Shows a single taxonomy. :param id: The name of id of the taxonomy :returns: A single taxonomy :rtype: A dictionary """ _check_access('taxonomy_show', context, data_dict) model = context['model'] id = data_dict.get('id') uri = data_dict.get('uri') name = data_dict.get('name') if not id and not uri and not name: raise logic.ValidationError("Neither id, name or uri were provided") item = Taxonomy.get(id or name) if not item and uri: item = Taxonomy.by_uri(uri) if not item: raise logic.NotFound() return item.as_dict(with_terms=True)
def taxonomy_term_update(context, data_dict): """ Allows a taxonomy term to be updated. :returns: The newly updated term :rtype: A dictionary """ _check_access('taxonomy_term_update', context, data_dict) model = context['model'] id = logic.get_or_bust(data_dict, 'id') term = TaxonomyTerm.get(id) if not term: raise logic.NotFound() term.label = data_dict.get('label', term.label) term.parent_id = data_dict.get('parent_id', term.parent_id) term.uri = logic.get_or_bust(data_dict, 'uri') term.description = data_dict.get('description', '') term.extras = data_dict.get('extras', '') model.Session.add(term) model.Session.commit() return term.as_dict()
def delete(cls, filter): obj = Session.query(cls).filter_by(**filter).first() if obj: Session.delete(obj) Session.commit() else: raise logic.NotFound(_(u'Theme'))
def like_delete(context, data_dict): '''Deletes a like from a given object for the current user. This action is only available for an authenticated user. :param ref: `str`, the ID of the object (for example news feed post ID). ''' check_access('like_delete', context, data_dict) if 'ref' not in data_dict: raise ValidationError({'ref': [_('Missing value')]}) ref = data_dict['ref'] user = context.get('auth_user_obj') try: model.Session.begin(subtransactions=True) like_ref = LikesRef.get(user.id, ref) if not like_ref: raise logic.NotFound(_('Not found')) like_ref.delete() count = LikesCount.get(ref) if count and count.count: count.count -= 1 count.save() model.Session.commit() except Exception as e: log.error('Failed to delete a like. Error: %s', str(e)) log.exception(e) model.Session.rollback()
def taxonomy_term_show_all(context, data_dict): """ Shows a single taxonomy term and its children, the taxonomy id is not required, just a term_id. :returns: A single taxonomy term :rtype: A dictionary """ _check_access('taxonomy_term_show', context, data_dict) label = data_dict.get('label') taxonomy_id = data_dict.get('taxonomy_id') if not label: raise logic.ValidationError("Either id, uri or label is required") if (taxonomy_id): term = TaxonomyTerm.get_from_taxonomy(label, taxonomy_id) else: term = TaxonomyTerm.get_all(label) if not term: raise logic.NotFound() return [u.as_dict() for u in term]
def taxonomy_update(context, data_dict): """ Updates an existing taxonomy. title, name and uri are required :returns: The newly updated taxonomy :rtype: A dictionary """ _check_access('taxonomy_update', context, data_dict) model = context['model'] id = logic.get_or_bust(data_dict, 'id') tax = Taxonomy.get(id) if not tax: raise logic.NotFound() tax.name = data_dict.get('name', tax.name) tax.title = data_dict.get('title', tax.title) tax.uri = data_dict.get('name', tax.uri) last_modified = data_dict.get('last_modified', tax.last_modified) if tax.last_modified != last_modified: tax.last_modified = isodate(last_modified, context) model.Session.add(tax) model.Session.commit() return tax.as_dict()
def resource_delete(context, data_dict): """Auth function override of ckan.logic.auth.delete.resource_delete function Re-implement the resource_delete auth function so that we check the protected status of a function before allowing deletion. :param context: dict :param data_dict: dict :return: success_dict: dict """ model = context['model'] resource = get_resource_object(context, data_dict).as_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} # if you can update a package then you can delete it can_update = tk.check_access('package_update', context, pkg_dict) if can_update: if helpers.resource_has_protected_status(resource['id']): return { 'success': False, 'msg': 'Contact a system administrator to delete this resource' } else: return {'success': False, 'msg': 'Resource delete is not allowed'} return {'success': True}
def user_roles_create(context, data_dict): l.check_access('user_roles', context, data_dict) data, errors = df.validate(data_dict, user_roles_schema(), context) if errors: raise t.ValidationError(errors) m = context.get('model') user_obj = m.User.get(data.get('user_id')) if user_obj is None: raise l.NotFound("No such user") user_id = user_obj.id role = data.get('role') user_roles = UserRoles.get(user_id) if user_roles: user_roles.role = role user_roles.save() else: user_roles = UserRoles(user_id=user_id, role=role) user_roles.save() out = table_dictize(user_roles, context) return out
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_show(context, data_dict): model = context['model'] user = context.get('user') log.info('user resource show: %s', 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.')) user_roles = user_custom_roles(context, data_dict) if Roles.MOD_R_DATA in user_roles: return {'success': True} 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: #check resource status, if private just org members may see it if not toolkit.get_action('is_resource_public')(context, resource.extras): authorized_read = package_update(context, pkg_dict).get('success') if not authorized_read: return {'success': False, 'msg': _('User %s not authorized to read resource %s') % (user, resource.id)} return {'success': True}
def _update_harvest_source_object(context, data_dict): ''' Updates an actual HarvestSource object with the data dict of the harvest_source dataset. All validation and authorization checks should be used by now, so this function is not to be used directly to update harvest sources. :param data_dict: A standard package data_dict :returns: The created HarvestSource object :rtype: HarvestSource object ''' source_id = data_dict.get('id') log.info('Harvest source %s update: %r', source_id, data_dict) source = HarvestSource.get(source_id) if not source: log.error('Harvest source %s does not exist', source_id) raise logic.NotFound('Harvest source %s does not exist' % source_id) fields = [ 'url', 'title', 'description', 'user_id', 'publisher_id', 'frequency', 'time' ] for f in fields: if f in data_dict and data_dict[f] is not None: if f == 'url': data_dict[f] = data_dict[f].strip() source.__setattr__(f, data_dict[f]) # Avoids clashes with the dataset type if 'source_type' in data_dict: source.type = data_dict['source_type'] if 'config' in data_dict: source.config = data_dict['config'] # Don't change state unless explicitly set in the dict if 'state' in data_dict: source.active = data_dict.get('state') == 'active' # Don't commit yet, let package_create do it source.add() # Abort any pending jobs if not source.active: jobs = HarvestJob.filter(source=source, status=u'New') log.info( 'Harvest source %s not active, so aborting %i outstanding jobs', source_id, jobs.count()) if jobs: for job in jobs: job.status = u'Aborted' job.add() return source
def saml2_user_delete(context, data_dict): if not data_dict.get('id') and data_dict.get('nameid'): saml2_user_id = saml2_get_userid_by_name_id(data_dict['nameid']) if saml2_user_id is not None: data_dict['id'] = saml2_user_id else: raise logic.NotFound( 'NameID "{id}" was not found.'.format(id=data_dict['nameid'])) ckan_user_delete(context, data_dict)
def resource_view_delete(context: Context, data_dict: DataDict) -> AuthResult: model = context['model'] resource_view = model.ResourceView.get(data_dict['id']) if not resource_view: raise logic.NotFound(_('Resource view not found, cannot check auth.')) resource_id = resource_view.resource_id return authz.is_authorized('resource_delete', context, {'id': resource_id})
def _request_token(user_id): if toolkit.c.user: # Don't offer the reset form if already logged in log.warning("User already logged in {}".format(toolkit.c.user)) raise toolkit.NotAuthorized('user already logged in, logout first') context = {'user': toolkit.c.user} data_dict = {'id': user_id} user_obj = None try: user_dict = toolkit.get_action('user_show')(context, data_dict) user_obj = context['user_obj'] except logic.NotFound: # Try searching the user del data_dict['id'] data_dict['q'] = user_id if user_id and len(user_id) > 2: user_list = toolkit.get_action('user_list')(context, data_dict) if len(user_list) == 1: # This is ugly, but we need the user object for the mailer, # and user_list does not return them del data_dict['q'] data_dict['id'] = user_list[0]['id'] user_dict = toolkit.get_action('user_show')(context, data_dict) user_obj = context['user_obj'] elif len(user_list) > 1: raise logic.NotFound('"%s" matched several users' % user_id) else: raise logic.NotFound('No such user: %s' % user_id) else: raise logic.NotFound('No such user: %s' % user_id) if user_obj: try: passwordless_send_reset_link(user_obj) except mailer.MailerException as e: log.error('Could not send token link: %s' % str(e)) raise mailer.MailerException( 'could not send token link by mail: %s' % str(e)) return
def resource_view_show(context, data_dict): model = context['model'] resource_view = model.ResourceView.get(data_dict['id']) if not resource_view: raise logic.NotFound(_('Resource view not found, cannot check auth.')) resource = model.Resource.get(resource_view.resource_id) return authz.is_authorized('resource_show', context, {'id': resource.id})
def purge_revision_history(context, data_dict): ''' Purge a given publisher's unused revision history. :param group: the name or id of the publisher :type group: string :returns: number of resources and revisions purged. :rtype: dictionary ''' logic.check_access('purge_revision_history', context, data_dict) model = context['model'] engine = model.meta.engine group_id = logic.get_or_bust(data_dict, 'group') group = model.Group.get(group_id) if not group: raise logic.NotFound('Publisher {0} not found'.format(group_id)) RESOURCE_IDS_SQL = ''' SELECT resource.id FROM resource JOIN resource_group ON resource.resource_group_id = resource_group.id JOIN member ON member.table_id = resource_group.package_id JOIN "group" ON "group".id = member.group_id WHERE "group".name = %s AND "group".type = 'organization' AND member.table_name = 'package' AND resource.state = 'deleted' ''' DELETE_REVISIONS_SQL = ''' DELETE FROM resource_revision WHERE id IN ({sql}) '''.format(sql=RESOURCE_IDS_SQL) # Not necessary to use a sub-select, but it allows re-use of sql statement # and this isn't performance critical code. DELETE_RESOURCES_SQL = ''' DELETE FROM resource WHERE id IN ({sql}) '''.format(sql=RESOURCE_IDS_SQL) try: number_revisions_deleted = engine.execute( DELETE_REVISIONS_SQL, group.name ).rowcount number_resources_deleted = engine.execute( DELETE_RESOURCES_SQL, group.name ).rowcount except Exception, e: raise logic.ActionError('Error executing sql: %s' % e)
def _check_group_auth(context, data_dict): '''Has this user got update permission for all of the given groups? If there is a package in the context then ignore that package's groups. (owner_org is checked elsewhere.) :returns: False if not allowed to update one (or more) of the given groups. True otherwise. i.e. True is the default. A blank data_dict mentions no groups, so it returns True. ''' # FIXME This code is shared amoung other logic.auth files and should be # somewhere better if not data_dict: return True model = context['model'] user = context['user'] pkg = context.get("package") api_version = context.get('api_version') or '1' group_blobs = data_dict.get('groups', []) groups = set() for group_blob in group_blobs: # group_blob might be a dict or a group_ref if isinstance(group_blob, dict): if api_version == '1': id = group_blob.get('name') else: id = group_blob.get('id') if not id: continue else: id = group_blob grp = model.Group.get(id) if grp is None: raise logic.NotFound(_('Group was not found.')) groups.add(grp) if pkg: pkg_groups = pkg.get_groups() groups = groups - set(pkg_groups) for group in groups: if not authz.has_user_permission_for_group_or_org( group.id, user, 'update'): return False return True
def resource_view_delete(context, data_dict): if context.get('resource'): return authz.is_authorized('resource_delete', context, {}) if context.get('resource_view'): return authz.is_authorized('resource_delete', context, {'id': context['resource_view'].resource_id}) resource_id = data_dict.get('resource_id') if not resource_id: resource_view = context['model'].ResourceView.get(data_dict['id']) if not resource_view: raise logic.NotFound(_('Resource view not found, cannot check auth.')) resource_id = resource_view.resource_id return authz.is_authorized('resource_delete', context, {'id': resource_id})
def all_tags(vocab_id_or_name=None): if vocab_id_or_name: vocab = vocabulary.Vocabulary.get(vocab_id_or_name) if vocab is None: # The user specified an invalid vocab. raise logic.NotFound("could not find vocabulary '%s'" % vocab_id_or_name) query = meta.Session.query(Tag).join(CeonTagExtra).filter( Tag.vocabulary_id == vocab.id).order_by(CeonTagExtra.position) else: query = meta.Session.query(Tag).join(CeonTagExtra).filter( Tag.vocabulary_id == None) query = query.distinct().join(PackageTag) query = query.filter_by(state='active') query = query.order_by(CeonTagExtra.position) return query
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 resource_view_delete(context, data_dict): if context.get('resource'): return resource_delete(context, {}) if context.get('resource_view'): return resource_delete(context, {'id': context['resource_view'].resource_id}) resource_id = data_dict.get('resource_id') if not resource_id: resource_view = context['model'].ResourceView.get(data_dict['id']) if not resource_view: raise logic.NotFound(_('Resource view not found, cannot check auth.')) resource_id = resource_view.resource_id if authz.config.get('ckan.gov_theme.is_back'): return resource_delete(context, {'id': resource_id}) else: return {'success': False}
def unfollow_search(context, data_dict): '''Stop following a search. You must provide your API key in the Authorization header. :param id: the id of the saved search :type id: string ''' if 'user' not in context: raise logic.NotAuthorized( _("You must be logged in to follow a search.")) if not paste.deploy.converters.asbool( config.get('ckan.follow_searches_enabled', 'false')): raise logic.NotFound(_("Following searches not supported")) model = context['model'] session = context['session'] userobj = model.User.get(context['user']) if not userobj: raise logic.NotAuthorized( _("You must be logged in to unfollow a search.")) follower = userobj.id if not data_dict.get('id'): errors = {"id": [_("Not provided and search_string not found")]} raise ValidationError(errors) id = data_dict['id'] obj = session.query(model.SavedSearch).get(id) if obj.user_id != follower: raise NotFound(_('You are not following this search')) obj.delete() model.repo.commit()