Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions qfieldcloud_sdk/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
13 changes: 6 additions & 7 deletions qfieldcloud_sdk/sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand All @@ -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
``<username>@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
Expand Down
31 changes: 31 additions & 0 deletions tests/test_cli_client.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import unittest
from unittest import mock

from click.testing import CliRunner

Expand Down Expand Up @@ -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)
Loading