From 21d79c3ea5120a868b6c66ba85c4c2af092ee555 Mon Sep 17 00:00:00 2001 From: Alice Butcher Date: Thu, 4 Oct 2018 20:33:54 +0100 Subject: [PATCH] added a test for chaining core auth functions also fixed a related bug: error message for unauthenticated users would break for chained auth functions because partials don't have `__name__` attributes --- ckan/authz.py | 3 ++- .../tests/test_chained_auth_functions.py | 27 +++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/ckan/authz.py b/ckan/authz.py index 694d05d8841..a405fefddea 100644 --- a/ckan/authz.py +++ b/ckan/authz.py @@ -205,7 +205,8 @@ def is_authorized(action, context, data_dict=None): return { 'success': False, 'msg': 'Action {0} requires an authenticated user'.format( - auth_function.__name__) + (auth_function if not isinstance(auth_function, functools.partial) + else auth_function.func).__name__) } return auth_function(context, data_dict) diff --git a/ckanext/datastore/tests/test_chained_auth_functions.py b/ckanext/datastore/tests/test_chained_auth_functions.py index 513659c2916..d5b9764f989 100644 --- a/ckanext/datastore/tests/test_chained_auth_functions.py +++ b/ckanext/datastore/tests/test_chained_auth_functions.py @@ -1,17 +1,22 @@ # -*- coding: utf-8 -*- import nose import ckan.plugins as p -from ckan.logic import check_access +from ckan.logic import check_access, NotAuthorized +from ckan.logic.auth.get import user_list as core_user_list import ckan.lib.create_test_data as ctd import ckan.tests.helpers as helpers +import ckan.tests.factories as factories +from ckan import model from ckanext.datastore.tests.helpers import DatastoreFunctionalTestBase assert_equals = nose.tools.assert_equals assert_raises = nose.tools.assert_raises +assert_is_instance = nose.tools.assert_is_instance auth_message = u'No search for you' +user_list_message = u'Nothing to see here' class TestAuthException(Exception): @@ -27,11 +32,19 @@ def datastore_search_sql_auth(up_func, context, data_dict): raise TestAuthException(auth_message) +@p.toolkit.chained_auth_function +def user_list(next_auth, context, data_dict): + # check it's received the core function as the first arg + assert_equals(next_auth, core_user_list) + raise TestAuthException(user_list_message) + + class ExampleDataStoreSearchSQLPlugin(p.SingletonPlugin): p.implements(p.IAuthFunctions) def get_auth_functions(self): - return {u'datastore_search_sql': datastore_search_sql_auth} + return {u'datastore_search_sql': datastore_search_sql_auth, + u'user_list': user_list} class TestChainedAuth(DatastoreFunctionalTestBase): @@ -48,3 +61,13 @@ def test_datastore_search_sql_auth(self): u'user': u'annafan', u'table_names': []}, {}) # check that exception returned has the message from our auth function assert_equals(raise_context.exception.message, auth_message) + + def test_chain_core_auth_functions(self): + user = factories.User() + context = {u'user': user[u'name']} + with assert_raises(TestAuthException) as raise_context: + check_access(u'user_list', context, {}) + assert_equals(raise_context.exception.message, user_list_message) + # check that the 'auth failed' msg doesn't fail because it's a partial + assert_raises(NotAuthorized, + lambda: check_access(u'user_list', {}, {}))