Skip to content

Commit 34064d6

Browse files
authored
[MPT-14082] Added user set password endpoint (#83)
Added user set password endpoint https://softwareone.atlassian.net/browse/MPT-14082
2 parents 46245bd + 1c63ab3 commit 34064d6

File tree

3 files changed

+87
-6
lines changed

3 files changed

+87
-6
lines changed

mpt_api_client/resources/accounts/users.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@ def sso_check(self, resource_id: str, resource_data: ResourceData | None = None)
5252
"""
5353
return self._resource_action(resource_id, "POST", "sso-check", json=resource_data)
5454

55+
def set_password(self, resource_id: str, password: str) -> User:
56+
"""Set password for a user.
57+
58+
Args:
59+
resource_id: Resource ID
60+
password: New password
61+
"""
62+
resource_data = {"password": password}
63+
64+
return self._resource_action(resource_id, "POST", "set-password", json=resource_data)
65+
5566

5667
class AsyncUsersService(
5768
AsyncUpdateMixin[User],
@@ -79,3 +90,14 @@ async def sso_check(self, resource_id: str, resource_data: ResourceData | None =
7990
resource_data: Resource data will be updated
8091
"""
8192
return await self._resource_action(resource_id, "POST", "sso-check", json=resource_data)
93+
94+
async def set_password(self, resource_id: str, password: str) -> User:
95+
"""Set password for a user.
96+
97+
Args:
98+
resource_id: Resource ID
99+
password: New password
100+
"""
101+
resource_data = {"password": password}
102+
103+
return await self._resource_action(resource_id, "POST", "set-password", json=resource_data)

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ per-file-ignores =
4545
tests/http/test_mixins.py: WPS204 WPS202
4646
tests/resources/catalog/test_products.py: WPS202 WPS210
4747
tests/resources/*/test_mixins.py: WPS118 WPS202 WPS204 WPS235
48+
tests/resources/accounts/test_users.py: WPS204 WPS202 WPS210
4849
tests/test_mpt_client.py: WPS235
4950

5051
tests/*:

tests/resources/accounts/test_users.py

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ def async_users_service(async_http_client):
1616

1717

1818
@pytest.mark.parametrize(
19-
"method", ["get", "update", "delete", "block", "unblock", "sso", "sso_check"]
19+
"method", ["get", "update", "delete", "block", "unblock", "sso", "sso_check", "set_password"]
2020
)
2121
def test_mixins_present(users_service, method):
2222
assert hasattr(users_service, method)
2323

2424

2525
@pytest.mark.parametrize(
26-
"method", ["get", "update", "delete", "block", "unblock", "sso", "sso_check"]
26+
"method", ["get", "update", "delete", "block", "unblock", "sso", "sso_check", "set_password"]
2727
)
2828
def test_async_mixins_present(async_users_service, method):
2929
assert hasattr(async_users_service, method)
@@ -36,7 +36,7 @@ def test_async_mixins_present(async_users_service, method):
3636
("sso_check", {"id": "OBJ-0000-0001", "status": "update"}),
3737
],
3838
)
39-
def test_sso_resource_actions(users_service, action, input_status):
39+
def test_resource_actions(users_service, action, input_status):
4040
request_expected_content = b'{"id":"OBJ-0000-0001","status":"update"}'
4141
response_expected_data = {"id": "OBJ-0000-0001", "status": "new_status"}
4242
with respx.mock:
@@ -65,7 +65,7 @@ def test_sso_resource_actions(users_service, action, input_status):
6565
("sso_check", None),
6666
],
6767
)
68-
def test_sso_resource_actions_no_data(users_service, action, input_status):
68+
def test_resource_actions_no_data(users_service, action, input_status):
6969
request_expected_content = b""
7070
response_expected_data = {"id": "OBJ-0000-0001", "status": "new_status"}
7171
with respx.mock:
@@ -94,7 +94,7 @@ def test_sso_resource_actions_no_data(users_service, action, input_status):
9494
("sso_check", {"id": "OBJ-0000-0001", "status": "update"}),
9595
],
9696
)
97-
async def test_async_sso_resource_actions(async_users_service, action, input_status):
97+
async def test_async_resource_actions(async_users_service, action, input_status):
9898
request_expected_content = b'{"id":"OBJ-0000-0001","status":"update"}'
9999
response_expected_data = {"id": "OBJ-0000-0001", "status": "new_status"}
100100
with respx.mock:
@@ -123,7 +123,7 @@ async def test_async_sso_resource_actions(async_users_service, action, input_sta
123123
("sso_check", None),
124124
],
125125
)
126-
async def test_async_sso_resource_actions_no_data(async_users_service, action, input_status):
126+
async def test_async_resource_actions_no_data(async_users_service, action, input_status):
127127
request_expected_content = b""
128128
response_expected_data = {"id": "OBJ-0000-0001", "status": "new_status"}
129129
with respx.mock:
@@ -143,3 +143,61 @@ async def test_async_sso_resource_actions_no_data(async_users_service, action, i
143143
assert request.content == request_expected_content
144144
assert blockable_obj.to_dict() == response_expected_data
145145
assert isinstance(blockable_obj, User)
146+
147+
148+
@pytest.mark.parametrize(
149+
("action", "input_password"),
150+
[
151+
("set_password", "new-password-123"),
152+
],
153+
)
154+
def test_set_password_action(users_service, action, input_password):
155+
request_expected_content_str = f'{{"password":"{input_password}"}}'
156+
request_expected_content = request_expected_content_str.encode()
157+
response_expected_data = {"password": input_password}
158+
with respx.mock:
159+
mock_route = respx.post(
160+
"https://api.example.com/public/v1/"
161+
f"accounts/users/OBJ-0000-0001/{action.replace('_', '-')}"
162+
).mock(
163+
return_value=httpx.Response(
164+
status_code=httpx.codes.OK,
165+
json=response_expected_data,
166+
)
167+
)
168+
blockable_obj = getattr(users_service, action)("OBJ-0000-0001", input_password)
169+
170+
request = mock_route.calls[0].request
171+
172+
assert request.content == request_expected_content
173+
assert blockable_obj.to_dict() == response_expected_data
174+
assert isinstance(blockable_obj, User)
175+
176+
177+
@pytest.mark.parametrize(
178+
("action", "input_password"),
179+
[
180+
("set_password", "new-password-123"),
181+
],
182+
)
183+
async def test_async_set_password_action(async_users_service, action, input_password):
184+
request_expected_content_str = f'{{"password":"{input_password}"}}'
185+
request_expected_content = request_expected_content_str.encode()
186+
response_expected_data = {"password": input_password}
187+
with respx.mock:
188+
mock_route = respx.post(
189+
"https://api.example.com/public/v1/"
190+
f"accounts/users/OBJ-0000-0001/{action.replace('_', '-')}"
191+
).mock(
192+
return_value=httpx.Response(
193+
status_code=httpx.codes.OK,
194+
json=response_expected_data,
195+
)
196+
)
197+
blockable_obj = await getattr(async_users_service, action)("OBJ-0000-0001", input_password)
198+
199+
request = mock_route.calls[0].request
200+
201+
assert request.content == request_expected_content
202+
assert blockable_obj.to_dict() == response_expected_data
203+
assert isinstance(blockable_obj, User)

0 commit comments

Comments
 (0)