Skip to content

Commit b86f3dc

Browse files
authored
add --password option to profile create and profile update commands (#113)
* add --password option to `profile create` and `profile update` commands * remove unused `_reset_pw()` * remove unused `_reset_pw()` * clarify reset-pw help * fix bad merge and test
1 parent c7a7f61 commit b86f3dc

4 files changed

Lines changed: 60 additions & 44 deletions

File tree

src/code42cli/cmds/profile.py

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,18 @@ def profile():
2222
"-n",
2323
"--name",
2424
required=True,
25-
type=str,
2625
help="The name of the Code42 CLI profile to use when executing this command.",
2726
)
2827
server_option = click.option(
29-
"-s", "--server", required=True, type=str, help="The url and port of the Code42 server."
28+
"-s", "--server", required=True, help="The url and port of the Code42 server."
3029
)
3130
username_option = click.option(
32-
"-u", "--username", required=True, type=str, help="The username of the Code42 API user."
31+
"-u", "--username", required=True, help="The username of the Code42 API user."
32+
)
33+
password_option = click.option(
34+
"--password",
35+
help="The password for the Code42 API user. If this option is omitted, interactive prompts "
36+
"will be used to obtain the password.",
3337
)
3438
disable_ssl_option = click.option(
3539
"--disable-ssl-errors",
@@ -58,32 +62,44 @@ def show(profile_name):
5862
@name_option
5963
@server_option
6064
@username_option
65+
@password_option
6166
@disable_ssl_option
62-
def create(name, server, username, disable_ssl_errors=False):
67+
def create(name, server, username, password, disable_ssl_errors):
6368
"""Create profile settings. The first profile created will be the default."""
6469
cliprofile.create_profile(name, server, username, disable_ssl_errors)
65-
_prompt_for_allow_password_set(name)
70+
if password:
71+
_set_pw(name, password)
72+
else:
73+
_prompt_for_allow_password_set(name)
6674
echo("Successfully created profile '{}'.".format(name))
6775

6876

6977
@profile.command()
7078
@name_option
7179
@server_option
7280
@username_option
81+
@password_option
7382
@disable_ssl_option
74-
def update(name=None, server=None, username=None, disable_ssl_errors=None):
83+
def update(name, server, username, password, disable_ssl_errors):
7584
"""Update an existing profile."""
7685
c42profile = cliprofile.get_profile(name)
7786
cliprofile.update_profile(c42profile.name, server, username, disable_ssl_errors)
78-
_prompt_for_allow_password_set(c42profile.name)
87+
if password:
88+
_set_pw(name, password)
89+
else:
90+
_prompt_for_allow_password_set(c42profile.name)
7991
echo("Profile '{}' has been updated.".format(c42profile.name))
8092

8193

8294
@profile.command()
8395
@profile_name_arg
84-
def reset_pw(profile_name=None):
85-
"""Change the stored password for a profile."""
86-
_reset_pw(profile_name)
96+
def reset_pw(profile_name):
97+
"""\b
98+
Change the stored password for a profile. Only affects what's stored in the local profile,
99+
does not make any changes to the Code42 user account."""
100+
password = getpass()
101+
_set_pw(profile_name, password)
102+
echo("Password updated for profile '{}'".format(profile_name))
87103

88104

89105
@profile.command("list")
@@ -101,6 +117,7 @@ def _list():
101117
def use(profile_name):
102118
"""Set a profile as the default."""
103119
cliprofile.switch_default_profile(profile_name)
120+
echo("{} has been set as the default profile.".format(profile_name))
104121

105122

106123
@profile.command()
@@ -136,15 +153,15 @@ def delete_all():
136153

137154
def _prompt_for_allow_password_set(profile_name):
138155
if does_user_agree("Would you like to set a password? (y/n): "):
139-
_reset_pw(profile_name)
156+
password = getpass()
157+
_set_pw(profile_name, password)
140158

141159

142-
def _reset_pw(profile_name):
160+
def _set_pw(profile_name, password):
143161
c42profile = cliprofile.get_profile(profile_name)
144-
new_password = getpass()
145162
try:
146-
validate_connection(c42profile.authority_url, c42profile.username, new_password)
163+
validate_connection(c42profile.authority_url, c42profile.username, password)
147164
except Exception:
148165
secho("Password not stored!", bold=True)
149166
raise
150-
cliprofile.set_password(new_password, c42profile.name)
167+
cliprofile.set_password(password, c42profile.name)

src/code42cli/config.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ def switch_default_profile(self, new_default_name):
8383
raise NoConfigProfileError(new_default_name)
8484
self._internal[self.DEFAULT_PROFILE] = new_default_name
8585
self._save()
86-
echo("{} has been set as the default profile.".format(new_default_name))
8786

8887
def delete_profile(self, name):
8988
"""Deletes a profile."""
@@ -149,7 +148,6 @@ def _try_complete_setup(self, profile):
149148
return
150149

151150
self._save()
152-
echo("Successfully saved profile '{}'.".format(profile.name))
153151

154152
default_profile = self._internal.get(self.DEFAULT_PROFILE)
155153
if default_profile is None or default_profile == self.DEFAULT_VALUE:

tests/cmds/test_profile.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,24 +103,45 @@ def test_create_profile_if_user_does_not_agree_does_not_save_password(
103103
def test_create_profile_if_credentials_invalid_password_not_saved(
104104
runner, user_agreement, invalid_connection, mock_cliprofile_namespace
105105
):
106+
mock_cliprofile_namespace.profile_exists.return_value = False
107+
result = runner.invoke(cli, ["profile", "create", "-n", "foo", "-s", "bar", "-u", "baz"],)
108+
assert "Password not stored!" in result.output
109+
assert not mock_cliprofile_namespace.set_password.call_count
110+
111+
112+
def test_create_profile_with_password_option_if_credentials_invalid_password_not_saved(
113+
runner, invalid_connection, mock_cliprofile_namespace
114+
):
115+
password = "test_pass"
106116
mock_cliprofile_namespace.profile_exists.return_value = False
107117
result = runner.invoke(
108-
cli, ["profile", "create", "-n", "foo", "-s", "bar", "-u", "baz", "--disable-ssl-errors"],
118+
cli, ["profile", "create", "-n", "foo", "-s", "bar", "-u", "baz", "--password", password],
109119
)
110120
assert "Password not stored!" in result.output
111121
assert not mock_cliprofile_namespace.set_password.call_count
122+
assert "Would you like to set a password?" not in result.output
112123

113124

114125
def test_create_profile_if_credentials_valid_password_saved(
115126
runner, mocker, user_agreement, valid_connection, mock_cliprofile_namespace
116127
):
117128
mock_cliprofile_namespace.profile_exists.return_value = False
118-
runner.invoke(
119-
cli, ["profile", "create", "-n", "foo", "-s", "bar", "-u", "baz", "--disable-ssl-errors"]
120-
)
129+
runner.invoke(cli, ["profile", "create", "-n", "foo", "-s", "bar", "-u", "baz"])
121130
mock_cliprofile_namespace.set_password.assert_called_once_with("newpassword", mocker.ANY)
122131

123132

133+
def test_create_profile_with_password_option_if_credentials_valid_password_saved(
134+
runner, mocker, valid_connection, mock_cliprofile_namespace
135+
):
136+
password = "test_pass"
137+
mock_cliprofile_namespace.profile_exists.return_value = False
138+
result = runner.invoke(
139+
cli, ["profile", "create", "-n", "foo", "-s", "bar", "-u", "baz", "--password", password],
140+
)
141+
mock_cliprofile_namespace.set_password.assert_called_once_with(password, mocker.ANY)
142+
assert "Would you like to set a password?" not in result.output
143+
144+
124145
def test_create_profile_outputs_confirmation(
125146
runner, user_agreement, valid_connection, mock_cliprofile_namespace
126147
):
@@ -280,5 +301,6 @@ def test_list_profiles_when_no_profiles_outputs_no_profiles_message(
280301

281302

282303
def test_use_profile(runner, mock_cliprofile_namespace, profile):
283-
runner.invoke(cli, ["profile", "use", profile.name])
304+
result = runner.invoke(cli, ["profile", "use", profile.name])
284305
mock_cliprofile_namespace.switch_default_profile.assert_called_once_with(profile.name)
306+
assert "{} has been set as the default profile.".format(profile.name) in result.output

tests/test_config.py

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
from __future__ import with_statement
1+
from configparser import ConfigParser
22

33
import pytest
4-
from configparser import ConfigParser
5-
import logging
64

7-
from code42cli import PRODUCT_NAME
85
from code42cli.config import ConfigAccessor, NoConfigProfileError
96
from .conftest import MockSection
107

@@ -143,14 +140,6 @@ def test_switch_default_profile_saves(self, config_parser_for_multiple_profiles,
143140
accessor.switch_default_profile(_TEST_SECOND_PROFILE_NAME)
144141
assert mock_saver.call_count
145142

146-
def test_switch_default_profile_outputs_confirmation(
147-
self, capsys, config_parser_for_multiple_profiles, mock_saver
148-
):
149-
accessor = ConfigAccessor(config_parser_for_multiple_profiles)
150-
accessor.switch_default_profile(_TEST_SECOND_PROFILE_NAME)
151-
output = capsys.readouterr()
152-
assert "set as the default profile" in output.out
153-
154143
def test_create_profile_when_given_default_name_does_not_create(self, config_parser_for_create):
155144
accessor = ConfigAccessor(config_parser_for_create)
156145
with pytest.raises(Exception):
@@ -189,16 +178,6 @@ def test_create_profile_when_not_existing_saves(self, config_parser_for_create,
189178
accessor.create_profile(_TEST_PROFILE_NAME, "example.com", "bar", False)
190179
assert mock_saver.call_count
191180

192-
def test_create_profile_when_not_existing_outputs_confirmation(
193-
self, capsys, config_parser_for_create, mock_saver
194-
):
195-
mock_internal = create_internal_object(False)
196-
setup_parser_one_profile(mock_internal, mock_internal, config_parser_for_create)
197-
accessor = ConfigAccessor(config_parser_for_create)
198-
accessor.create_profile(_TEST_PROFILE_NAME, "example.com", "bar", False)
199-
output = capsys.readouterr()
200-
assert "Successfully saved" in output.out
201-
202181
def test_update_profile_when_no_profile_exists_raises_exception(
203182
self, config_parser_for_multiple_profiles
204183
):

0 commit comments

Comments
 (0)