From a35eb75440e577e418628cbe4e710fb85686f977 Mon Sep 17 00:00:00 2001 From: amercader Date: Thu, 1 Mar 2012 12:02:16 +0000 Subject: [PATCH] [logic,auth] Add auth logic layer The first version of the auth layer is based on the current policy, i.e. you need to be sysadmin to perform any action. TODO: the CLI is still not working. --- ckanext/harvest/commands/harvester.py | 9 ++-- ckanext/harvest/controllers/view.py | 65 ++++++++++++++++--------- ckanext/harvest/logic/action/create.py | 11 ++++- ckanext/harvest/logic/action/delete.py | 4 +- ckanext/harvest/logic/action/get.py | 33 ++++++++++--- ckanext/harvest/logic/action/update.py | 19 ++++++-- ckanext/harvest/logic/auth/__init__.py | 7 +++ ckanext/harvest/logic/auth/create.py | 30 ++++++++++++ ckanext/harvest/logic/auth/delete.py | 13 +++++ ckanext/harvest/logic/auth/get.py | 67 ++++++++++++++++++++++++++ ckanext/harvest/logic/auth/update.py | 30 ++++++++++++ ckanext/harvest/plugin.py | 50 ++++++++++++++++--- 12 files changed, 289 insertions(+), 49 deletions(-) create mode 100644 ckanext/harvest/logic/auth/__init__.py create mode 100644 ckanext/harvest/logic/auth/create.py create mode 100644 ckanext/harvest/logic/auth/delete.py create mode 100644 ckanext/harvest/logic/auth/get.py create mode 100644 ckanext/harvest/logic/auth/update.py diff --git a/ckanext/harvest/commands/harvester.py b/ckanext/harvest/commands/harvester.py index 338bb99..9f69978 100644 --- a/ckanext/harvest/commands/harvester.py +++ b/ckanext/harvest/commands/harvester.py @@ -152,12 +152,11 @@ class Harvester(CkanCommand): 'user_id':user_id, 'publisher_id':publisher_id} - context = {'model':model} + context = {'model':model, 'session':model.Session} source = get_action('harvest_source_create')(context,data_dict) print 'Created new harvest source:' self.print_harvest_source(source) - context = {'model': model} sources = get_action('harvest_source_list')(context,{}) self.print_there_are('harvest source', sources) @@ -189,7 +188,7 @@ class Harvester(CkanCommand): data_dict = {'only_active':True} what = 'active harvest source' - context = {'model': model} + context = {'model': model,'session':model.Session} sources = get_action('harvest_source_list')(context,data_dict) self.print_harvest_sources(sources) self.print_there_are(what=what, sequence=sources) @@ -204,7 +203,7 @@ class Harvester(CkanCommand): job = create_harvest_job(source_id) self.print_harvest_job(job) - context = {'model': model} + context = {'model': model,'session':model.Session} jobs = get_action('harvest_job_list')(context,{'status':u'New'}) self.print_there_are('harvest jobs', jobs, condition=status) @@ -226,7 +225,7 @@ class Harvester(CkanCommand): source_id = unicode(self.args[1]) else: source_id = None - context = {'model': model} + context = {'model': model, 'session':model.Session} objs = get_action('harvest_objects_import')(context,{'source_id':source_id}) print '%s objects reimported' % len(objs) diff --git a/ckanext/harvest/controllers/view.py b/ckanext/harvest/controllers/view.py index 4c560ae..899358a 100644 --- a/ckanext/harvest/controllers/view.py +++ b/ckanext/harvest/controllers/view.py @@ -9,7 +9,7 @@ from ckan.lib.base import BaseController, c, g, request, \ response, session, render, config, abort, redirect from ckan.lib.navl.dictization_functions import DataError -from ckan.logic import NotFound, ValidationError, get_action +from ckan.logic import NotFound, ValidationError, get_action, NotAuthorized from ckanext.harvest.logic.schema import harvest_source_form_schema from ckan.lib.helpers import Page import logging @@ -17,19 +17,15 @@ log = logging.getLogger(__name__) class ViewController(BaseController): - def __before__(self, action, **env): - super(ViewController, self).__before__(action, **env) - # All calls to this controller must be with a sysadmin key - if not self.authorizer.is_sysadmin(c.user): - response_msg = _('Not authorized to see this page') - status = 401 - abort(status, response_msg) + not_auth_message = _('Not authorized to see this page') def index(self): - # Request all harvest sources - context = {'model':model} - - c.sources = get_action('harvest_source_list')(context,{}) + context = {'model':model, 'user':c.user,'session':model.Session} + try: + # Request all harvest sources + c.sources = get_action('harvest_source_list')(context,{}) + except NotAuthorized,e: + abort(401,self.not_auth_message) return render('index.html') @@ -41,7 +37,13 @@ class ViewController(BaseController): data = data or {} errors = errors or {} error_summary = error_summary or {} - harvesters_info = get_action('harvesters_info_show')() + + try: + context = {'model':model, 'user':c.user} + harvesters_info = get_action('harvesters_info_show')(context,{}) + except NotAuthorized,e: + abort(401,self.not_auth_message) + vars = {'data': data, 'errors': errors, 'error_summary': error_summary, 'harvesters': harvesters_info} c.form = render('source/new_source_form.html', extra_vars=vars) @@ -51,8 +53,7 @@ class ViewController(BaseController): try: data_dict = dict(request.params) self._check_data_dict(data_dict) - - context = {'model':model} + context = {'model':model, 'user':c.user, 'session':model.Session} source = get_action('harvest_source_create')(context,data_dict) # Create a harvest job for the new source @@ -61,6 +62,8 @@ class ViewController(BaseController): h.flash_success(_('New harvest source added successfully.' 'A new harvest job for the source has also been created.')) redirect(h.url_for('harvest')) + except NotAuthorized,e: + abort(401,self.not_auth_message) except DataError,e: abort(400, 'Integrity Error') except ValidationError,e: @@ -76,17 +79,23 @@ class ViewController(BaseController): if not data: try: - context = {'model':model} + context = {'model':model, 'user':c.user} old_data = get_action('harvest_source_show')(context, {'id':id}) except NotFound: abort(404, _('Harvest Source not found')) + except NotAuthorized,e: + abort(401,self.not_auth_message) data = data or old_data errors = errors or {} error_summary = error_summary or {} + try: + context = {'model':model, 'user':c.user} + harvesters_info = get_action('harvesters_info_show')(context,{}) + except NotAuthorized,e: + abort(401,self.not_auth_message) - harvesters_info = get_action('harvesters_info_show')() vars = {'data': data, 'errors': errors, 'error_summary': error_summary, 'harvesters': harvesters_info} c.form = render('source/new_source_form.html', extra_vars=vars) @@ -97,12 +106,14 @@ class ViewController(BaseController): data_dict = dict(request.params) data_dict['id'] = id self._check_data_dict(data_dict) - context = {'model':model} + context = {'model':model, 'user':c.user, 'session':model.Session} source = get_action('harvest_source_update')(context,data_dict) h.flash_success(_('Harvest source edited successfully.')) redirect(h.url_for('harvest')) + except NotAuthorized,e: + abort(401,self.not_auth_message) except DataError,e: abort(400, _('Integrity Error')) except NotFound, e: @@ -125,7 +136,7 @@ class ViewController(BaseController): def read(self,id): try: - context = {'model':model} + context = {'model':model, 'user':c.user} c.source = get_action('harvest_source_show')(context, {'id':id}) c.page = Page( @@ -137,26 +148,33 @@ class ViewController(BaseController): return render('source/read.html') except NotFound: abort(404,_('Harvest source not found')) + except NotAuthorized,e: + abort(401,self.not_auth_message) + def delete(self,id): try: - context = {'model':model} + context = {'model':model, 'user':c.user} get_action('harvest_source_delete')(context, {'id':id}) h.flash_success(_('Harvesting source successfully inactivated')) redirect(h.url_for('harvest')) except NotFound: abort(404,_('Harvest source not found')) + except NotAuthorized,e: + abort(401,self.not_auth_message) def create_harvesting_job(self,id): try: - context = {'model':model} + context = {'model':model, 'user':c.user, 'session':model.Session} get_action('harvest_job_create')(context,{'source_id':id}) h.flash_success(_('Refresh requested, harvesting will take place within 15 minutes.')) except NotFound: abort(404,_('Harvest source not found')) + except NotAuthorized,e: + abort(401,self.not_auth_message) except Exception, e: msg = 'An error occurred: [%s]' % e.message h.flash_error(msg) @@ -164,8 +182,9 @@ class ViewController(BaseController): redirect(h.url_for('harvest')) def show_object(self,id): + try: - context = {'model':model} + context = {'model':model, 'user':c.user} obj = get_action('harvest_object_show')(context, {'id':id}) # Check content type. It will probably be either XML or JSON @@ -183,6 +202,8 @@ class ViewController(BaseController): return obj['content'] except NotFound: abort(404,_('Harvest object not found')) + except NotAuthorized,e: + abort(401,self.not_auth_message) except Exception, e: msg = 'An error occurred: [%s]' % e.message h.flash_error(msg) diff --git a/ckanext/harvest/logic/action/create.py b/ckanext/harvest/logic/action/create.py index a1a92d9..6b0907b 100644 --- a/ckanext/harvest/logic/action/create.py +++ b/ckanext/harvest/logic/action/create.py @@ -1,6 +1,6 @@ import re -from ckan.logic import NotFound, ValidationError +from ckan.logic import NotFound, ValidationError, check_access from ckan.lib.navl.dictization_functions import validate from ckanext.harvest.model import (HarvestSource, HarvestJob, HarvestObject) @@ -11,13 +11,16 @@ from ckanext.harvest.logic.action.get import harvest_source_list,harvest_job_lis def harvest_source_create(context,data_dict): + check_access('harvest_source_create',context,data_dict) + model = context['model'] + session = context['session'] schema = harvest_source_form_schema() data, errors = validate(data_dict, schema) if errors: - model.Session.rollback() + session.rollback() raise ValidationError(errors,_error_summary(errors)) source = HarvestSource() @@ -38,6 +41,8 @@ def harvest_source_create(context,data_dict): def harvest_job_create(context,data_dict): + check_access('harvest_job_create',context,data_dict) + source_id = data_dict['source_id'] # Check if source exists @@ -66,6 +71,8 @@ def harvest_job_create(context,data_dict): def harvest_job_create_all(context,data_dict): + check_access('harvest_job_create_all',context,data_dict) + data_dict.update({'only_active':True}) # Get all active sources diff --git a/ckanext/harvest/logic/action/delete.py b/ckanext/harvest/logic/action/delete.py index ecf5cbd..a69d3aa 100644 --- a/ckanext/harvest/logic/action/delete.py +++ b/ckanext/harvest/logic/action/delete.py @@ -1,10 +1,12 @@ -from ckan.logic import NotFound +from ckan.logic import NotFound, check_access from ckanext.harvest.model import (HarvestSource, HarvestJob) def harvest_source_delete(context,data_dict): + check_access('harvest_source_delete',context,data_dict) + source_id = data_dict.get('id') source = HarvestSource.get(source_id) if not source: diff --git a/ckanext/harvest/logic/action/get.py b/ckanext/harvest/logic/action/get.py index cc280ac..9654bf9 100644 --- a/ckanext/harvest/logic/action/get.py +++ b/ckanext/harvest/logic/action/get.py @@ -2,7 +2,7 @@ from ckan.plugins import PluginImplementations from ckanext.harvest.interfaces import IHarvester -from ckan.logic import NotFound +from ckan.logic import NotFound, check_access from ckanext.harvest.model import (HarvestSource, HarvestJob, HarvestObject) from ckanext.harvest.logic.dictization import (harvest_source_dictize, @@ -11,6 +11,8 @@ from ckanext.harvest.logic.dictization import (harvest_source_dictize, def harvest_source_show(context,data_dict): + check_access('harvest_source_show',context,data_dict) + id = data_dict.get('id') attr = data_dict.get('attr',None) @@ -23,17 +25,20 @@ def harvest_source_show(context,data_dict): def harvest_source_list(context, data_dict): + check_access('harvest_source_list',context,data_dict) + model = context['model'] + session = context['session'] only_active = data_dict.get('only_active',False) if only_active: - sources = model.Session.query(HarvestSource) \ + sources = session.query(HarvestSource) \ .filter(HarvestSource.active==True) \ .order_by(HarvestSource.created.desc()) \ .all() else: - sources = model.Session.query(HarvestSource) \ + sources = session.query(HarvestSource) \ .order_by(HarvestSource.created.desc()) \ .all() @@ -42,6 +47,8 @@ def harvest_source_list(context, data_dict): def harvest_job_show(context,data_dict): + check_access('harvest_job_show',context,data_dict) + id = data_dict.get('id') attr = data_dict.get('attr',None) @@ -53,12 +60,15 @@ def harvest_job_show(context,data_dict): def harvest_job_list(context,data_dict): + check_access('harvest_job_list',context,data_dict) + model = context['model'] + session = context['session'] source_id = data_dict.get('source_id',False) status = data_dict.get('status',False) - query = model.Session.query(HarvestJob) + query = session.query(HarvestJob) if source_id: query = query.filter(HarvestJob.source_id==source_id) @@ -72,9 +82,10 @@ def harvest_job_list(context,data_dict): def harvest_object_show(context,data_dict): + check_access('harvest_object_show',context,data_dict) + id = data_dict.get('id') attr = data_dict.get('attr',None) - obj = HarvestObject.get(id,attr=attr) if not obj: raise NotFound @@ -83,20 +94,26 @@ def harvest_object_show(context,data_dict): def harvest_object_list(context,data_dict): + check_access('harvest_object_list',context,data_dict) + model = context['model'] + session = context['session'] only_current = data_dict.get('only_current',True) if only_current: - objects = model.Session.query(HarvestObject) \ + objects = session.query(HarvestObject) \ .filter(HarvestObject.current==True) \ .all() else: - objects = model.Session.query(HarvestObject).all() + objects = session.query(HarvestObject).all() return [getattr(obj,'id') for obj in objects] -def harvesters_info_show(context = {},data_dict = {}): +def harvesters_info_show(context,data_dict): + + check_access('harvesters_info_show',context,data_dict) + available_harvesters = [] for harvester in PluginImplementations(IHarvester): info = harvester.info() diff --git a/ckanext/harvest/logic/action/update.py b/ckanext/harvest/logic/action/update.py index 86f73b9..0515208 100644 --- a/ckanext/harvest/logic/action/update.py +++ b/ckanext/harvest/logic/action/update.py @@ -5,7 +5,7 @@ from ckanext.harvest.interfaces import IHarvester from ckan.model import Package -from ckan.logic import NotFound, ValidationError +from ckan.logic import NotFound, ValidationError, check_access from ckan.lib.navl.dictization_functions import validate from ckanext.harvest.queue import get_gather_publisher @@ -22,7 +22,11 @@ log = logging.getLogger(__name__) def harvest_source_update(context,data_dict): + check_access('harvest_source_update',context,data_dict) + model = context['model'] + session = context['session'] + source_id = data_dict.get('id') schema = harvest_source_form_schema() @@ -33,7 +37,7 @@ def harvest_source_update(context,data_dict): data, errors = validate(data_dict, schema) if errors: - model.Session.rollback() + session.rollback() raise ValidationError(errors,_error_summary(errors)) fields = ['url','title','type','description','user_id','publisher_id'] @@ -67,7 +71,10 @@ def harvest_objects_import(context,data_dict): It will only affect the last fetched objects already present in the database. ''' + check_access('harvest_objects_import',context,data_dict) + model = context['model'] + session = context['session'] source_id = data_dict.get('source_id',None) if source_id: @@ -78,14 +85,14 @@ def harvest_objects_import(context,data_dict): if not source.active: raise Exception('This harvest source is not active') - last_objects_ids = model.Session.query(HarvestObject.id) \ + last_objects_ids = session.query(HarvestObject.id) \ .join(HarvestSource).join(Package) \ .filter(HarvestObject.source==source) \ .filter(HarvestObject.current==True) \ .filter(Package.state==u'active') \ .all() else: - last_objects_ids = model.Session.query(HarvestObject.id) \ + last_objects_ids = session.query(HarvestObject.id) \ .join(Package) \ .filter(HarvestObject.current==True) \ .filter(Package.state==u'active') \ @@ -93,7 +100,7 @@ def harvest_objects_import(context,data_dict): last_objects = [] for obj_id in last_objects_ids: - obj = model.Session.query(HarvestObject).get(obj_id) + obj = session.query(HarvestObject).get(obj_id) for harvester in PluginImplementations(IHarvester): if harvester.info()['name'] == obj.source.type: if hasattr(harvester,'force_import'): @@ -105,6 +112,8 @@ def harvest_objects_import(context,data_dict): def harvest_jobs_run(context,data_dict): + check_access('harvest_jobs_run',context,data_dict) + # Check if there are pending harvest jobs jobs = harvest_job_list(context,{'status':u'New'}) if len(jobs) == 0: diff --git a/ckanext/harvest/logic/auth/__init__.py b/ckanext/harvest/logic/auth/__init__.py new file mode 100644 index 0000000..d0ed2fc --- /dev/null +++ b/ckanext/harvest/logic/auth/__init__.py @@ -0,0 +1,7 @@ +try: + import pkg_resources + pkg_resources.declare_namespace(__name__) +except ImportError: + import pkgutil + __path__ = pkgutil.extend_path(__path__, __name__) + diff --git a/ckanext/harvest/logic/auth/create.py b/ckanext/harvest/logic/auth/create.py new file mode 100644 index 0000000..2173263 --- /dev/null +++ b/ckanext/harvest/logic/auth/create.py @@ -0,0 +1,30 @@ +from ckan.lib.base import _ +from ckan.authz import Authorizer + +def harvest_source_create(context,data_dict): + model = context['model'] + user = context.get('user') + + if not Authorizer().is_sysadmin(user): + return {'success': False, 'msg': _('User %s not authorized to create harvest sources') % str(user)} + else: + return {'success': True} + +def harvest_job_create(context,data_dict): + model = context['model'] + user = context.get('user') + + if not Authorizer().is_sysadmin(user): + return {'success': False, 'msg': _('User %s not authorized to create harvest jobs') % str(user)} + else: + return {'success': True} + +def harvest_job_create_all(context,data_dict): + model = context['model'] + user = context.get('user') + + if not Authorizer().is_sysadmin(user): + return {'success': False, 'msg': _('User %s not authorized to create harvest jobs for all sources') % str(user)} + else: + return {'success': True} + diff --git a/ckanext/harvest/logic/auth/delete.py b/ckanext/harvest/logic/auth/delete.py new file mode 100644 index 0000000..f527aea --- /dev/null +++ b/ckanext/harvest/logic/auth/delete.py @@ -0,0 +1,13 @@ +from ckan.lib.base import _ +from ckan.authz import Authorizer + +def harvest_source_delete(context,data_dict): + model = context['model'] + user = context.get('user') + + if not Authorizer().is_sysadmin(user): + return {'success': False, 'msg': _('User %s not authorized to delete harvest sources') % str(user)} + else: + return {'success': True} + + diff --git a/ckanext/harvest/logic/auth/get.py b/ckanext/harvest/logic/auth/get.py new file mode 100644 index 0000000..2581818 --- /dev/null +++ b/ckanext/harvest/logic/auth/get.py @@ -0,0 +1,67 @@ +from ckan.lib.base import _ +from ckan.authz import Authorizer + +def harvest_source_show(context,data_dict): + model = context['model'] + user = context.get('user') + + if not Authorizer().is_sysadmin(user): + return {'success': False, 'msg': _('User %s not authorized to read this harvest source') % str(user)} + else: + return {'success': True} + +def harvest_source_list(context,data_dict): + model = context['model'] + user = context.get('user') + + if not Authorizer().is_sysadmin(user): + return {'success': False, 'msg': _('User %s not authorized to see the harvest sources') % str(user)} + else: + return {'success': True} + + +def harvest_job_show(context,data_dict): + model = context['model'] + user = context.get('user') + + if not Authorizer().is_sysadmin(user): + return {'success': False, 'msg': _('User %s not authorized to read this harvest job') % str(user)} + else: + return {'success': True} + +def harvest_job_list(context,data_dict): + model = context['model'] + user = context.get('user') + + if not Authorizer().is_sysadmin(user): + return {'success': False, 'msg': _('User %s not authorized to see the harvest jobs') % str(user)} + else: + return {'success': True} + +def harvest_object_show(context,data_dict): + model = context['model'] + user = context.get('user') + + if not Authorizer().is_sysadmin(user): + return {'success': False, 'msg': _('User %s not authorized to read this harvest object') % str(user)} + else: + return {'success': True} + +def harvest_object_list(context,data_dict): + model = context['model'] + user = context.get('user') + + if not Authorizer().is_sysadmin(user): + return {'success': False, 'msg': _('User %s not authorized to see the harvest objects') % str(user)} + else: + return {'success': True} + +def harvesters_info_show(context,data_dict): + model = context['model'] + user = context.get('user') + + if not Authorizer().is_sysadmin(user): + return {'success': False, 'msg': _('User %s not authorized to see the harvesters information') % str(user)} + else: + return {'success': True} + diff --git a/ckanext/harvest/logic/auth/update.py b/ckanext/harvest/logic/auth/update.py new file mode 100644 index 0000000..efe84c7 --- /dev/null +++ b/ckanext/harvest/logic/auth/update.py @@ -0,0 +1,30 @@ +from ckan.lib.base import _ +from ckan.authz import Authorizer + +def harvest_source_update(context,data_dict): + model = context['model'] + user = context.get('user') + + if not Authorizer().is_sysadmin(user): + return {'success': False, 'msg': _('User %s not authorized to update harvest sources') % str(user)} + else: + return {'success': True} + +def harvest_objects_import(context,data_dict): + model = context['model'] + user = context.get('user') + + if not Authorizer().is_sysadmin(user): + return {'success': False, 'msg': _('User %s not authorized to reimport harvest objects') % str(user)} + else: + return {'success': True} + +def harvest_jobs_run(context,data_dict): + model = context['model'] + user = context.get('user') + + if not Authorizer().is_sysadmin(user): + return {'success': False, 'msg': _('User %s not authorized to run the pending harvest jobs') % str(user)} + else: + return {'success': True} + diff --git a/ckanext/harvest/plugin.py b/ckanext/harvest/plugin.py index 1d6decd..13fbedb 100644 --- a/ckanext/harvest/plugin.py +++ b/ckanext/harvest/plugin.py @@ -8,18 +8,18 @@ import ckan.lib.helpers as h from ckan.plugins import implements, SingletonPlugin from ckan.plugins import IRoutes, IConfigurer -from ckan.plugins import IConfigurable, IActions +from ckan.plugins import IConfigurable, IActions, IAuthFunctions from ckanext.harvest.model import setup log = getLogger(__name__) class Harvest(SingletonPlugin): - + implements(IConfigurable) implements(IRoutes, inherit=True) implements(IConfigurer, inherit=True) implements(IActions) - + implements(IAuthFunctions) def configure(self, config): setup() @@ -30,11 +30,11 @@ class Harvest(SingletonPlugin): map.connect('harvest', '/harvest',controller=controller,action='index') map.connect('/harvest/new', controller=controller, action='new') - map.connect('/harvest/edit/:id', controller=controller, action='edit') + map.connect('/harvest/edit/:id', controller=controller, action='edit') map.connect('/harvest/delete/:id',controller=controller, action='delete') map.connect('/harvest/:id', controller=controller, action='read') - map.connect('harvesting_job_create', '/harvest/refresh/:id',controller=controller, + map.connect('harvesting_job_create', '/harvest/refresh/:id',controller=controller, action='create_harvesting_job') map.connect('/harvest/object/:id', controller=controller, action='show_object') @@ -59,6 +59,8 @@ class Harvest(SingletonPlugin): harvest_source_list, harvest_job_show, harvest_job_list, + harvest_object_show, + harvest_object_list, harvesters_info_show,) from ckanext.harvest.logic.action.create import (harvest_source_create, harvest_job_create, @@ -73,12 +75,48 @@ class Harvest(SingletonPlugin): 'harvest_source_list': harvest_source_list, 'harvest_job_show': harvest_job_show, 'harvest_job_list': harvest_job_list, + 'harvest_object_show': harvest_object_show, + 'harvest_object_list': harvest_object_list, + 'harvesters_info_show': harvesters_info_show, 'harvest_source_create': harvest_source_create, 'harvest_job_create': harvest_job_create, 'harvest_job_create_all': harvest_job_create_all, 'harvest_source_update': harvest_source_update, 'harvest_source_delete': harvest_source_delete, - 'harvesters_info_show': harvesters_info_show, 'harvest_objects_import': harvest_objects_import, 'harvest_jobs_run':harvest_jobs_run } + + def get_auth_functions(self): + from ckanext.harvest.logic.auth.get import (harvest_source_show, + harvest_source_list, + harvest_job_show, + harvest_job_list, + harvest_object_show, + harvest_object_list, + harvesters_info_show,) + from ckanext.harvest.logic.auth.create import (harvest_source_create, + harvest_job_create, + harvest_job_create_all,) + from ckanext.harvest.logic.auth.update import (harvest_source_update, + harvest_objects_import, + harvest_jobs_run) + from ckanext.harvest.logic.auth.delete import (harvest_source_delete,) + + return { + 'harvest_source_show': harvest_source_show, + 'harvest_source_list': harvest_source_list, + 'harvest_job_show': harvest_job_show, + 'harvest_job_list': harvest_job_list, + 'harvest_object_show': harvest_object_show, + 'harvest_object_list': harvest_object_list, + 'harvesters_info_show': harvesters_info_show, + 'harvest_source_create': harvest_source_create, + 'harvest_job_create': harvest_job_create, + 'harvest_job_create_all': harvest_job_create_all, + 'harvest_source_update': harvest_source_update, + 'harvest_source_delete': harvest_source_delete, + 'harvest_objects_import': harvest_objects_import, + 'harvest_jobs_run':harvest_jobs_run + } +