Feature 11034:Forgot Password in OSM (osmclient)
Change-Id: I0dcc81c79a93420f4ed4f2ef7f8be4886989d005
Signed-off-by: jegan <jegan.s@tataelxsi.co.in>
diff --git a/osmclient/cli_commands/rbac.py b/osmclient/cli_commands/rbac.py
index 71fa12b..c51e229 100755
--- a/osmclient/cli_commands/rbac.py
+++ b/osmclient/cli_commands/rbac.py
@@ -290,6 +290,7 @@
confirmation_prompt=True,
help="user password",
)
+@click.option("--email", "email", default=None, help="User's email address")
@click.option(
"--projects",
# prompt="Comma separate list of projects",
@@ -308,12 +309,15 @@
)
@click.option("--domain-name", "domain_name", default=None, help="assign to a domain")
@click.pass_context
-def user_create(ctx, username, password, projects, project_role_mappings, domain_name):
+def user_create(
+ ctx, username, password, email, projects, project_role_mappings, domain_name
+):
"""Creates a new user
\b
USERNAME: name of the user
PASSWORD: password of the user
+ EMAIL: email of the user
PROJECTS: projects assigned to user (internal only)
PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
DOMAIN_NAME: optional domain name for the user when keystone authentication is used
@@ -324,6 +328,8 @@
user["password"] = password
user["projects"] = projects
user["project_role_mappings"] = project_role_mappings
+ if email:
+ user["email_id"] = email
if domain_name:
user["domain_name"] = domain_name
@@ -334,6 +340,7 @@
@click.command(name="user-update", short_help="updates user information")
@click.argument("username")
@click.option("--set-username", "set_username", default=None, help="change username")
+@click.option("--email", "email", default=None, help="Change User's email address")
@click.option(
"--set-project",
"set_project",
@@ -386,6 +393,7 @@
ctx,
username,
set_username,
+ email,
set_project,
remove_project,
add_project_role,
@@ -400,6 +408,7 @@
\b
USERNAME: name of the user
SET_USERNAME: new username
+ EMAIL: new email of the user
SET_PROJECT: creating mappings for project/role(s)
REMOVE_PROJECT: deleting mappings for project/role(s)
ADD_PROJECT_ROLE: adding mappings for project/role(s)
@@ -412,6 +421,7 @@
logger.debug("")
user = {}
user["username"] = set_username
+ user["email_id"] = email
user["set-project"] = set_project
user["remove-project"] = remove_project
user["add-project-role"] = add_project_role
@@ -507,3 +517,58 @@
table.add_row([k, json.dumps(v, indent=2)])
table.align = "l"
print(table)
+
+
+@click.command(name="user-reset-password", short_help="Resetting a user's password")
+@click.option("--email", "email", help="Email of the user")
+@click.pass_context
+def user_reset_password(ctx, email):
+ """Reset user's password using email
+
+ osm --user username user-reset-password --email
+
+ \b
+ EMAIL: Registered Email of the user
+
+ """
+ resp = ctx.obj.user.user_reset_password(email=email)
+ if isinstance(resp, dict):
+ if resp.get("email"):
+ while True:
+ otp = click.prompt(
+ "Please enter the One-Time-Password sent to your mail"
+ )
+ otp_resp = ctx.obj.user.user_reset_password(otp=otp)
+ if isinstance(otp_resp, dict):
+ if otp_resp.get("id"):
+ break
+ else:
+ print("Invalid One-Time-Password")
+ else:
+ break
+ if isinstance(otp_resp, dict):
+ if otp_resp.get("id"):
+ try:
+ correct_password = False
+ while not correct_password:
+ new_password = click.prompt(
+ "Please enter the new password",
+ hide_input=True,
+ confirmation_prompt=True,
+ )
+ otp_resp["new_password"] = new_password
+ update_user = otp_resp
+ password_resp = ctx.obj.user.forgot_password(
+ update_user=update_user
+ )
+ if isinstance(password_resp, int):
+ correct_password = True
+ print("Password has been updated")
+ else:
+ print("Password has been used before")
+ except Exception as e:
+ print(f"Error while updating the password, {e}")
+ else:
+ print("Invalid One-Time-Password. Maximum retries exceeded")
+ else:
+ print(resp)
diff --git a/osmclient/scripts/osm.py b/osmclient/scripts/osm.py
index bb69b6a..50ffac3 100755
--- a/osmclient/scripts/osm.py
+++ b/osmclient/scripts/osm.py
@@ -303,6 +303,8 @@
cli_osm.add_command(rbac.user_show)
cli_osm.add_command(rbac.user_update)
+ cli_osm.add_command(rbac.user_reset_password)
+
cli_osm.add_command(repo.repo_add)
cli_osm.add_command(repo.repo_delete)
cli_osm.add_command(repo.repo_list)
diff --git a/osmclient/sol005/client.py b/osmclient/sol005/client.py
index 0b7d309..133f04f 100644
--- a/osmclient/sol005/client.py
+++ b/osmclient/sol005/client.py
@@ -65,6 +65,7 @@
self._user = user
self._password = password
self._project = project
+ self._otp = None
self._project_domain_name = kwargs.get("project_domain_name")
self._user_domain_name = kwargs.get("user_domain_name")
self._logger = logging.getLogger("osmclient")
@@ -125,14 +126,22 @@
self.utils = utils.Utils(http_client, **kwargs)
"""
- def get_token(self, pwd_change=False):
+ def get_token(self, pwd_change=False, email=None):
self._logger.debug("")
if self._token is None:
- postfields_dict = {
- "username": self._user,
- "password": self._password,
- "project_id": self._project,
- }
+ if email:
+ postfields_dict = {
+ "username": self._user,
+ "email_id": email,
+ }
+ elif self._otp:
+ postfields_dict = {"username": self._user, "otp": self._otp}
+ else:
+ postfields_dict = {
+ "username": self._user,
+ "password": self._password,
+ "project_id": self._project,
+ }
if self._project_domain_name:
postfields_dict["project_domain_name"] = self._project_domain_name
if self._user_domain_name:
@@ -148,7 +157,7 @@
raise ClientException(
"Password Expired. Please update the password using change_password option"
)
- self._token = token["id"]
+ self._token = token.get("id")
if self._token is not None:
self._headers["Authorization"] = "Bearer {}".format(self._token)
@@ -166,3 +175,7 @@
version = resp.split()[2]
date = resp.split()[4]
return "{} {}".format(version, date)
+
+ def set_otp(self, otp):
+ self._otp = otp
+ self._emailid = None
diff --git a/osmclient/sol005/user.py b/osmclient/sol005/user.py
index 296bd55..262b904 100644
--- a/osmclient/sol005/user.py
+++ b/osmclient/sol005/user.py
@@ -100,6 +100,8 @@
if user.get("username"):
update_user["username"] = user["username"]
+ if user.get("email_id"):
+ update_user["email_id"] = user["email_id"]
if user.get("new_password"):
update_user["password"] = user["new_password"]
if pwd_change and user.get("current_password"):
@@ -267,3 +269,21 @@
if name == user["username"]:
return user
raise NotFound("User {} not found".format(name))
+
+ def user_reset_password(self, email=None, otp=None, update_user=None):
+ try:
+ if update_user:
+ user_update = dict()
+ user_update["password"] = update_user["new_password"]
+ http_code, resp = self._http.patch_cmd(
+ endpoint="{}/{}".format(self._apiBase, update_user["user_id"]),
+ postfields_dict=user_update,
+ skip_query_admin=True,
+ )
+ return http_code
+ if otp:
+ self._client.set_otp(otp)
+ resp = self._client.get_token(email=email)
+ return resp
+ except Exception as e:
+ return e