From 4ae0974193eb8479857e4ff9f120166627220ef4 Mon Sep 17 00:00:00 2001 From: Pallab Pain Date: Mon, 31 Jul 2023 16:55:09 +0530 Subject: [PATCH] feat(organization): adds command to invite user --- Pipfile | 1 + Pipfile.lock | 55 ++++++++++++++++++++---------- riocli/organization/__init__.py | 2 ++ riocli/organization/invite_user.py | 49 ++++++++++++++++++++++++++ riocli/organization/utils.py | 5 +++ setup.py | 3 +- 6 files changed, 96 insertions(+), 19 deletions(-) create mode 100644 riocli/organization/invite_user.py diff --git a/Pipfile b/Pipfile index 3d2cffcf..0126e3c2 100644 --- a/Pipfile +++ b/Pipfile @@ -32,6 +32,7 @@ yaspin = ">=2.3.0" jsonschema = ">=4.0.0" waiting = ">=1.4.1" semver = ">=3.0.0" +email-validator = "==2.0.0.post2" [requires] python_version = "3" diff --git a/Pipfile.lock b/Pipfile.lock index 9014e58f..30e6bc8b 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "f989df10a0b0659c30e617e0f2aa66d29c4d8cc3b9fe38d112373b7d14abe665" + "sha256": "d5e4fbee6c5315b619209c22fac47556821c3c0ec70e85726051726f01b4ebce" }, "pipfile-spec": 6, "requires": { @@ -118,7 +118,7 @@ "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac", "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==3.2.0" }, "click": { @@ -192,6 +192,26 @@ "index": "pypi", "version": "==0.0.3.1" }, + "dnspython": { + "hashes": [ + "sha256:5b7488477388b8c0b70a8ce93b227c5603bc7b77f1565afe8e729c36c51447d7", + "sha256:c33971c79af5be968bb897e95c2448e11a645ee84d93b265ce0b7aabe5dfdca8" + ], + "markers": "python_version >= '3.8' and python_version < '4.0'", + "version": "==2.4.1" + }, + "email-validator": { + "hashes": [ + "sha256:1ff6e86044200c56ae23595695c54e9614f4a9551e0e393614f764860b3d7900", + "sha256:2466ba57cda361fb7309fd3d5a225723c788ca4bbad32a0ebd5373b99730285c" + ], + "index": "pypi", + "version": "==2.0.0.post2" + }, + "flake8": { + "path": ".", + "version": "==0.6.0" + }, "graphlib-backport": { "hashes": [ "sha256:24246967b9e7e6a91550bc770e6169585d35aa32790258579a8a3899a8c18fde", @@ -301,7 +321,7 @@ "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac", "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==3.0.39" }, "pyrfc3339": { @@ -414,10 +434,6 @@ "index": "pypi", "version": "==1.11.1" }, - "rapyuta-io-cli": { - "path": ".", - "version": "==0.6.0" - }, "requests": { "hashes": [ "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", @@ -426,6 +442,9 @@ "markers": "python_version >= '3.7'", "version": "==2.31.0" }, + "riocli": { + "path": "." + }, "semver": { "hashes": [ "sha256:2a23844ba1647362c7490fe3995a86e097bb590d16f0f32dfc383008f19e4cdf", @@ -542,7 +561,7 @@ "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da", "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a" ], - "markers": "python_full_version >= '3.6.0'", + "markers": "python_version >= '3.6'", "version": "==4.12.2" }, "black": { @@ -652,7 +671,7 @@ "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac", "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==3.2.0" }, "click": { @@ -791,11 +810,11 @@ }, "pathspec": { "hashes": [ - "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687", - "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293" + "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20", + "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3" ], "markers": "python_version >= '3.7'", - "version": "==0.11.1" + "version": "==0.11.2" }, "pep517": { "hashes": [ @@ -837,11 +856,11 @@ }, "platformdirs": { "hashes": [ - "sha256:1b42b450ad933e981d56e59f1b97495428c9bd60698baab9f3eb3d00d5822421", - "sha256:ad8291ae0ae5072f66c16945166cb11c63394c7a3ad1b1bc9828ca3162da8c2f" + "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d", + "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d" ], "markers": "python_version >= '3.7'", - "version": "==3.9.1" + "version": "==3.10.0" }, "plette": { "extras": [ @@ -1101,11 +1120,11 @@ }, "tomlkit": { "hashes": [ - "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171", - "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3" + "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86", + "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899" ], "markers": "python_version >= '3.7'", - "version": "==0.11.8" + "version": "==0.12.1" }, "typed-ast": { "hashes": [ diff --git a/riocli/organization/__init__.py b/riocli/organization/__init__.py index e3ccb7e9..86515780 100644 --- a/riocli/organization/__init__.py +++ b/riocli/organization/__init__.py @@ -15,6 +15,7 @@ from click_help_colors import HelpColorsGroup from riocli.constants import Colors +from riocli.organization.invite_user import invite_user from riocli.organization.list import list_organizations from riocli.organization.select import select_organization from riocli.organization.users import list_users @@ -34,5 +35,6 @@ def organization() -> None: organization.add_command(list_users) +organization.add_command(invite_user) organization.add_command(list_organizations) organization.add_command(select_organization) diff --git a/riocli/organization/invite_user.py b/riocli/organization/invite_user.py new file mode 100644 index 00000000..44925982 --- /dev/null +++ b/riocli/organization/invite_user.py @@ -0,0 +1,49 @@ +# Copyright 2023 Rapyuta Robotics +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import click +from click_help_colors import HelpColorsCommand +from email_validator import EmailNotValidError, validate_email + +from riocli.constants import Colors, Symbols +from riocli.organization.utils import invite_user_to_org +from riocli.utils.context import get_root_context + + +@click.command( + 'invite-user', + cls=HelpColorsCommand, + help_headers_color=Colors.YELLOW, + help_options_color=Colors.GREEN, +) +@click.argument('user-email', type=str) +@click.pass_context +def invite_user(ctx: click.Context, user_email: str) -> None: + """ + Invite a new user to the current organization + """ + ctx = get_root_context(ctx) + + try: + validate_email(user_email) + except EmailNotValidError as e: + click.secho('{} {} is not a valid email address'.format(Symbols.ERROR, user_email), fg=Colors.RED) + raise SystemExit(1) from e + + try: + invite_user_to_org(ctx.obj.data['organization_id'], user_email) + click.secho('{} User invited successfully.'.format(Symbols.SUCCESS), fg=Colors.GREEN) + except Exception as e: + click.secho('{} Failed to invite user: {}'.format(Symbols.ERROR, e), fg=Colors.RED) + raise SystemExit(1) from e diff --git a/riocli/organization/utils.py b/riocli/organization/utils.py index 7efa95ba..55afb9cb 100644 --- a/riocli/organization/utils.py +++ b/riocli/organization/utils.py @@ -53,3 +53,8 @@ def _api_call( def get_organization_details(organization_guid: str) -> typing.Dict: return _api_call(HttpMethod.GET, '{}/get'.format(organization_guid)) + + +def invite_user_to_org(organization_guid: str, user_email: str) -> typing.Dict: + payload = {'userEmail': user_email} + return _api_call(HttpMethod.PUT, '{}/adduser'.format(organization_guid), payload=payload) diff --git a/setup.py b/setup.py index fa3b039c..a2af8fce 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ import re -from setuptools import setup, find_packages +from setuptools import find_packages, setup version = re.search( '^__version__\s*=\s*"(.*)"', open("riocli/bootstrap.py").read(), re.M @@ -59,6 +59,7 @@ "jsonschema==4.0.0", "waiting>=1.4.1", "semver>=3.0.0", + "email-validator==2.0.0.post2", ], setup_requires=["flake8"], )