diff --git a/qfieldcloud_sdk/cli.py b/qfieldcloud_sdk/cli.py index f2279e7..b37a1d7 100755 --- a/qfieldcloud_sdk/cli.py +++ b/qfieldcloud_sdk/cli.py @@ -177,6 +177,32 @@ def logout(ctx): log(payload["detail"]) +@cli.command() +@click.argument("username") +@click.argument("password") +@click.argument("email") +@click.option( + "--exist-ok/--no-exist-ok", + default=False, + help="Do not fail when the user already exists. Default: False", +) +@click.pass_context +def create_user( + ctx: Context, username: str, password: str, email: str, exist_ok: bool +) -> None: + """Create a new QFieldCloud user account.""" + + user = ctx.obj["client"].create_user(username, password, email, exist_ok=exist_ok) + + if ctx.obj["format_json"]: + print_json(user) + else: + if user is None: + log(f'User "{username}" already exists.') + else: + log(f'Created user "{user["username"]}".') + + @cli.command() @click.pass_context def status(ctx: Context): diff --git a/qfieldcloud_sdk/sdk.py b/qfieldcloud_sdk/sdk.py index c22bf16..d2a42b0 100644 --- a/qfieldcloud_sdk/sdk.py +++ b/qfieldcloud_sdk/sdk.py @@ -334,7 +334,7 @@ def create_user( self, username: str, password: str, - email: str = "", + email: str, exist_ok: bool = False, ) -> Optional[Dict[str, Any]]: """Create a new QFieldCloud user account (staff only). @@ -343,20 +343,19 @@ def create_user( Args: username: The username for the new account. Must be 3-150 characters - and contain only letters, numbers, ``-`` and ``_``. + and contain only letters, numbers, `-` and `_`. password: The password for the new account. - email: Optional email address. When omitted, QFieldCloud defaults to - ``@noreply.local``. - exist_ok: When *True*, return ``None`` silently if the username is + email: Email address. + exist_ok: When *True*, return `None` silently if the username is already taken (HTTP 409) instead of raising. Defaults to False. Returns: A dictionary with the public user info of the newly created account, - or ``None`` when *exist_ok* is True and the user already exists. + or `None` when `exist_ok` is `True` and the user already exists. Raises: QfcRequestException: On any HTTP error other than 409, or on 409 - when *exist_ok* is False. + when `exist_ok` is `False`. Example: ```python diff --git a/tests/test_cli_client.py b/tests/test_cli_client.py index 13b4a44..11193e4 100644 --- a/tests/test_cli_client.py +++ b/tests/test_cli_client.py @@ -1,4 +1,5 @@ import unittest +from unittest import mock from click.testing import CliRunner @@ -60,3 +61,33 @@ def test_list_jobs(self): catch_exceptions=False, ) self.assertEqual(result.exit_code, 0) + + def test_create_user(self): + client = mock.Mock() + client.create_user.return_value = { + "username": "field_mapper_42", + "email": "field_mapper_42@example.com", + } + + with mock.patch("qfieldcloud_sdk.cli.sdk.Client", return_value=client): + result = self.runner.invoke( + cli, + [ + "--json", + "create-user", + "field_mapper_42", + "s3cr3t", + "field_mapper_42@example.com", + "--exist-ok", + ], + catch_exceptions=False, + ) + + self.assertEqual(result.exit_code, 0) + client.create_user.assert_called_once_with( + "field_mapper_42", + "s3cr3t", + "field_mapper_42@example.com", + exist_ok=True, + ) + self.assertIn('"username": "field_mapper_42"', result.output)