diff --git a/ckan/lib/dictization/model_dictize.py b/ckan/lib/dictization/model_dictize.py index 825a993349b..d9574bfd1e2 100644 --- a/ckan/lib/dictization/model_dictize.py +++ b/ckan/lib/dictization/model_dictize.py @@ -359,7 +359,8 @@ def user_dictize(user, context): requester = context['user'] if not (ckan.authz.Authorizer().is_sysadmin(unicode(requester)) or - requester == user.name): + requester == user.name or + context.get('keep_sensitive_data', False)): # If not sysadmin or the same user, strip sensible info result_dict.pop('apikey', None) result_dict.pop('reset_key', None) diff --git a/ckan/logic/action/create.py b/ckan/logic/action/create.py index 5a8fdf58947..c117dee8a97 100644 --- a/ckan/logic/action/create.py +++ b/ckan/logic/action/create.py @@ -384,13 +384,18 @@ def user_create(context, data_dict): if not context.get('defer_commit'): model.repo.commit() - # Construct the user dict before changing the context. + # A new context is required for dictizing the newly constructed user in + # order that all the new user's data is returned, in particular, the + # api_key. # - # TODO: I don't know what the need for changing the context is, probably - # caching of the domain object. But it doesn't seem right given that - # usually context['user'] contains the user who made the request. - user_dict = model_dictize.user_dictize(user, context) - + # The context is copied so as not to clobber the caller's context dict. + user_dictize_context = context.copy() + user_dictize_context['keep_sensitive_data'] = True + user_dict = model_dictize.user_dictize(user, user_dictize_context) + + # TODO: I don't know what the need for changing the context is here, + # probably caching of the domain object. But it doesn't seem right given + # that usually context['user'] contains the user who made the request. context['user'] = user context['id'] = user.id log.debug('Created user %s' % str(user.name)) diff --git a/ckan/tests/functional/api/test_user.py b/ckan/tests/functional/api/test_user.py index 13ce706f2f4..06dd35dd7fc 100644 --- a/ckan/tests/functional/api/test_user.py +++ b/ckan/tests/functional/api/test_user.py @@ -1,5 +1,6 @@ from nose.tools import assert_equal +import ckan.logic as logic from ckan import model from ckan.lib.create_test_data import CreateTestData from ckan.tests import TestController as ControllerTestCase @@ -50,3 +51,52 @@ def test_autocomplete_limit(self): print response.json assert_equal(len(response.json), 1) +class TestUserActions(object): + + @classmethod + def setup_class(cls): + CreateTestData.create() + + @classmethod + def teardown_class(cls): + model.repo.rebuild_db() + + def test_user_create_simple(self): + '''Simple creation of a new user by a non-sysadmin user.''' + context = { + 'model': model, + 'session': model.Session, + 'user': 'tester' + } + data_dict = { + 'name': 'a-new-user', + 'email': 'a.person@example.com', + 'password': 'supersecret', + } + + user_dict = logic.get_action('user_create')(context, data_dict) + + assert_equal(user_dict['name'], 'a-new-user') + assert 'email' in user_dict + assert 'apikey' in user_dict + assert 'password' not in user_dict + + def test_user_update_simple(self): + '''Simple update of a user by themselves.''' + context = { + 'model': model, + 'session': model.Session, + 'user': 'annafan', + } + + data_dict = { + 'id': 'annafan', + 'email': 'anna@example.com', + } + + user_dict = logic.get_action('user_update')(context, data_dict) + + assert_equal(user_dict['email'], 'anna@example.com') + assert 'apikey' in user_dict + assert 'password' not in user_dict +