Repository: Kinto/kinto

Issue:
`kinto create-user` doesn't override the password if the user already exists.



Discussion:
I did some more tests, and I suspect that "create-user" doesn't create the user at all. For example, I run,

```
$ sudo docker run --rm --net host \
    --env-file /etc/dockerflow/buildhub.txt \
    -v /etc/kinto.ini:/etc/kinto.ini \
    --log-driver=syslog hub.prod.mozaws.net/pipelines/buildhub:4.2.0 \
kinto create-user -u user1 -p password --ini /etc/kinto.ini

/usr/local/lib/python3.5/site-packages/kinto/core/storage/postgresql/client.py:91: UserWarning: Reuse existing PostgreSQL connection. Parameters permission_* will be ignored.
  warnings.warn(msg)
INFO   Running kinto 7.4.1.
Creating user 'user1'
```

And afterwards I ran ```curl -s -u user1:password https://buildhub.stage.mozaws.net/v1/```, which doesn't return the user property.

```
$ curl -s -u user1:password https://buildhub.stage.mozaws.net/v1/ | jq .
{
  "http_api_version": "1.17",
  "project_name": "kinto",
  "project_version": "7.4.1",
  "settings": {
    "batch_max_requests": 25,
    "readonly": false
  },
  "project_docs": "https://kinto.readthedocs.io/",
  "url": "https://buildhub.stage.mozaws.net/v1/",
  "capabilities": {
    "elasticsearch": {
      "description": "Index and search records using ElasticSearch.",
      "version": "0.3.0",
      "url": "https://github.com/Kinto/kinto-elasticsearch"
    },
    "accounts": {
      "description": "Manage user accounts.",
      "url": "https://kinto.readthedocs.io/en/latest/api/1.x/accounts.html"
    }
  }
}
```

Further more the user_principals table doesn't contain the ```user1``` user either.

```
buildhub=> select * from user_principals where user_id like '%user1%';
 user_id | principal
---------+-----------
(0 rows)
```
One possible flaw is that the command does not run `current_transaction.commit()` (see https://github.com/Kinto/kinto/blob/master/kinto/core/scripts.py#L89) and maybe it was only tested on the memory backend ?
> Maybe it was only tested on the memory backend?

It was also tested with the redis backend but you could really well be right about the postgresql backend error.

Resolving patch:
diff --git a/kinto/plugins/accounts/scripts.py b/kinto/plugins/accounts/scripts.py
--- a/kinto/plugins/accounts/scripts.py
+++ b/kinto/plugins/accounts/scripts.py
@@ -50,10 +50,10 @@ def create_user(env, username=None, password=None):
 
     print("Creating user '{}'".format(username))
     record = {'id': username, 'password': hash_password(password)}
-    registry.storage.create(collection_id='account',
+    registry.storage.update(collection_id='account',
                             parent_id=username,
-                            record=record,
-                            ignore_conflict=True)
+                            object_id=username,
+                            record=record)
     registry.permission.add_principal_to_ace('/accounts/{}'.format(username),
                                              'write',
                                              'account:{}'.format(username))


Test patch:
diff --git a/tests/plugins/test_accounts.py b/tests/plugins/test_accounts.py
--- a/tests/plugins/test_accounts.py
+++ b/tests/plugins/test_accounts.py
@@ -351,7 +351,7 @@ def test_create_user_with_an_invalid_username_and_password_confirmation_recovers
             with mock.patch('kinto.plugins.accounts.scripts.getpass.getpass', side_effect=[
                     "password", "p4ssw0rd", "password", "password"]):
                 code = scripts.create_user({'registry': self.registry}, None, None)
-                self.registry.storage.create.assert_called_once()
+                self.registry.storage.update.assert_called_once()
                 self.registry.permission.add_principal_to_ace.assert_called_with(
                     "/accounts/username", "write", "account:username")
                 assert code == 0
@@ -361,14 +361,14 @@ def test_create_user_with_a_valid_username_and_password_confirmation(self):
             with mock.patch('kinto.plugins.accounts.scripts.getpass.getpass',
                             return_value="password"):
                 code = scripts.create_user({'registry': self.registry})
-                self.registry.storage.create.assert_called_once()
+                self.registry.storage.update.assert_called_once()
                 self.registry.permission.add_principal_to_ace.assert_called_with(
                     "/accounts/username", "write", "account:username")
                 assert code == 0
 
     def test_create_user_with_valid_username_and_password_parameters(self):
         code = scripts.create_user({'registry': self.registry}, "username", "password")
-        self.registry.storage.create.assert_called_once()
+        self.registry.storage.update.assert_called_once()
         self.registry.permission.add_principal_to_ace.assert_called_with(
             "/accounts/username", "write", "account:username")
         assert code == 0