Repository: ckan/ckan

Issue:
Allow Sysadmins to create users with the form
(Even if create_user_from_web is false).

I've come across several workflows where people wanted a centralised administrator to be the **only** person able to create accounts. This change allows that. Everything else works perfectly. I can offer more detail later on - I'm just in a rush at the moment.

Cheers,
Carl



Discussion:
This is good, but would you add a small test so that the behaviour doesn't change accidentally in the future.

Also, redirecting to the user just created would be better than rendering the logout_first page when a sysadmin finishes creating the user. 

Yep, will do. And I agree, that makes sense. Will add those changes tomorrow. Thanks for getting back to be so fast!

@CarlQLange did you ever get around to doing this? I just created a small test case that makes sure this works. I could provide it unless you already have anything?


Resolving patch:
diff --git a/ckan/controllers/user.py b/ckan/controllers/user.py
--- a/ckan/controllers/user.py
+++ b/ckan/controllers/user.py
@@ -166,7 +166,8 @@ def new(self, data=None, errors=None, error_summary=None):
         '''GET to display a form for registering a new user.
            or POST the form data to actually do the user registration.
         '''
-        context = {'model': model, 'session': model.Session,
+        context = {'model': model,
+                   'session': model.Session,
                    'user': c.user,
                    'auth_user_obj': c.userobj,
                    'schema': self._new_form_to_db_schema(),
@@ -180,7 +181,7 @@ def new(self, data=None, errors=None, error_summary=None):
         if context['save'] and not data:
             return self._save_new(context)
 
-        if c.user and not data:
+        if c.user and not data and not authz.is_sysadmin(c.user):
             # #1799 Don't offer the registration form if already logged in
             return render('user/logout_first.html')
 
@@ -264,7 +265,14 @@ def _save_new(self, context):
             h.flash_success(_('User "%s" is now registered but you are still '
                             'logged in as "%s" from before') %
                             (data_dict['name'], c.user))
-            return render('user/logout_first.html')
+            if authz.is_sysadmin(c.user):
+                # the sysadmin created a new user. We redirect him to the
+                # activity page for the newly created user
+                h.redirect_to(controller='user',
+                              action='activity',
+                              id=data_dict['name'])
+            else:
+                return render('user/logout_first.html')
 
     def edit(self, id=None, data=None, errors=None, error_summary=None):
         context = {'save': 'save' in request.params,


Test patch:
diff --git a/ckan/tests/controllers/test_user.py b/ckan/tests/controllers/test_user.py
--- a/ckan/tests/controllers/test_user.py
+++ b/ckan/tests/controllers/test_user.py
@@ -59,6 +59,37 @@ def test_register_user_bad_password(self):
         response = form.submit('save')
         assert_true('The passwords you entered do not match' in response)
 
+    def test_create_user_as_sysadmin(self):
+        admin_pass = 'pass'
+        sysadmin = factories.Sysadmin(password=admin_pass)
+        app = self._get_test_app()
+
+        # Have to do an actual login as this test relies on repoze
+        #  cookie handling.
+
+        # get the form
+        response = app.get('/user/login')
+        # ...it's the second one
+        login_form = response.forms[1]
+        # fill it in
+        login_form['login'] = sysadmin['name']
+        login_form['password'] = admin_pass
+        # submit it
+        login_form.submit('save')
+
+        response = app.get(
+            url=url_for(controller='user', action='register'),
+        )
+        assert "user-register-form" in response.forms
+        form = response.forms['user-register-form']
+        form['name'] = 'newestuser'
+        form['fullname'] = 'Newest User'
+        form['email'] = 'test@test.com'
+        form['password1'] = 'testpassword'
+        form['password2'] = 'testpassword'
+        response2 = form.submit('save')
+        assert '/user/activity' in response2.location
+
 
 class TestLoginView(helpers.FunctionalTestBase):
     def test_registered_user_login(self):