2018-01-26 17:14:00 +00:00
|
|
|
|
import copy
|
2018-11-30 17:39:39 +00:00
|
|
|
|
import uuid
|
2018-02-20 11:22:17 +00:00
|
|
|
|
|
2016-10-25 18:13:50 +01:00
|
|
|
|
import pytest
|
2018-02-20 11:22:17 +00:00
|
|
|
|
from flask import url_for
|
2018-04-25 14:12:58 +01:00
|
|
|
|
|
|
|
|
|
|
import app
|
2021-06-09 13:19:05 +01:00
|
|
|
|
from app.utils.user import is_gov_user
|
2017-08-17 10:44:36 +01:00
|
|
|
|
from tests.conftest import (
|
2020-06-08 14:39:36 +01:00
|
|
|
|
ORGANISATION_ID,
|
|
|
|
|
|
ORGANISATION_TWO_ID,
|
2017-08-17 10:44:36 +01:00
|
|
|
|
SERVICE_ONE_ID,
|
2019-02-25 16:51:37 +00:00
|
|
|
|
USER_ONE_ID,
|
2019-12-19 16:59:07 +00:00
|
|
|
|
create_active_user_empty_permissions,
|
|
|
|
|
|
create_active_user_manage_template_permissions,
|
|
|
|
|
|
create_active_user_view_permissions,
|
|
|
|
|
|
create_active_user_with_permissions,
|
2023-11-08 07:51:57 -08:00
|
|
|
|
create_platform_admin_user,
|
2018-02-20 11:22:17 +00:00
|
|
|
|
normalize_spaces,
|
2019-02-25 16:51:37 +00:00
|
|
|
|
sample_uuid,
|
2017-08-17 10:44:36 +01:00
|
|
|
|
)
|
2018-02-20 11:22:17 +00:00
|
|
|
|
|
2016-02-19 15:02:13 +00:00
|
|
|
|
|
2023-10-26 11:38:03 -07:00
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
|
|
("user", "expected_self_text", "add_details"),
|
2023-08-25 09:12:23 -07:00
|
|
|
|
[
|
2017-08-17 10:49:21 +01:00
|
|
|
|
(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
create_active_user_with_permissions(),
|
|
|
|
|
|
(
|
2023-12-18 15:38:36 -05:00
|
|
|
|
"Test User(you) "
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"Permissions "
|
|
|
|
|
|
"Can See dashboard "
|
|
|
|
|
|
"Can Send messages "
|
|
|
|
|
|
"Can Add and edit templates "
|
|
|
|
|
|
"Can Manage settings, team and usage "
|
|
|
|
|
|
"Can Manage API integration"
|
|
|
|
|
|
),
|
2023-10-26 11:38:03 -07:00
|
|
|
|
True,
|
2017-08-17 10:49:21 +01:00
|
|
|
|
),
|
2018-01-26 17:14:00 +00:00
|
|
|
|
(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
create_active_user_empty_permissions(),
|
2023-12-18 15:38:36 -05:00
|
|
|
|
("Test User With Empty Permissions(you) " "Permissions"),
|
2023-10-26 11:38:03 -07:00
|
|
|
|
False,
|
2018-08-06 11:10:37 +01:00
|
|
|
|
),
|
|
|
|
|
|
(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
create_active_user_view_permissions(),
|
2023-12-18 15:38:36 -05:00
|
|
|
|
("Test User With Permissions(you) " "Permissions " "Can See dashboard"),
|
2023-10-26 11:38:03 -07:00
|
|
|
|
False,
|
2018-08-06 11:10:37 +01:00
|
|
|
|
),
|
2017-08-17 10:49:21 +01:00
|
|
|
|
(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
create_active_user_manage_template_permissions(),
|
|
|
|
|
|
(
|
2023-12-18 15:38:36 -05:00
|
|
|
|
"Test User With Permissions(you) "
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"Permissions "
|
|
|
|
|
|
"Can See dashboard "
|
2023-11-09 12:00:31 -07:00
|
|
|
|
"Can Add and edit templates"
|
2023-08-25 09:12:23 -07:00
|
|
|
|
),
|
2023-10-26 11:38:03 -07:00
|
|
|
|
False,
|
2017-08-17 10:49:21 +01:00
|
|
|
|
),
|
2023-08-25 09:12:23 -07:00
|
|
|
|
],
|
|
|
|
|
|
)
|
2016-02-29 17:35:21 +00:00
|
|
|
|
def test_should_show_overview_page(
|
2017-08-17 10:44:36 +01:00
|
|
|
|
client_request,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
mocker,
|
|
|
|
|
|
mock_get_invites_for_service,
|
2019-05-17 13:06:26 +01:00
|
|
|
|
mock_get_template_folders,
|
2018-08-06 11:10:37 +01:00
|
|
|
|
mock_has_no_jobs,
|
2018-06-12 14:29:47 +01:00
|
|
|
|
service_one,
|
2017-08-17 10:49:21 +01:00
|
|
|
|
user,
|
2018-01-26 17:14:00 +00:00
|
|
|
|
expected_self_text,
|
|
|
|
|
|
active_user_view_permissions,
|
2023-10-26 11:38:03 -07:00
|
|
|
|
add_details,
|
2016-02-29 17:35:21 +00:00
|
|
|
|
):
|
2019-12-19 16:59:07 +00:00
|
|
|
|
current_user = user
|
2018-01-26 17:14:00 +00:00
|
|
|
|
other_user = copy.deepcopy(active_user_view_permissions)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
other_user["email_address"] = "zzzzzzz@example.gsa.gov"
|
|
|
|
|
|
other_user["name"] = "ZZZZZZZZ"
|
|
|
|
|
|
other_user["id"] = "zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz"
|
2018-01-26 17:14:00 +00:00
|
|
|
|
|
2023-01-19 17:29:21 -05:00
|
|
|
|
client_request.login(current_user)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mock_get_users = mocker.patch(
|
|
|
|
|
|
"app.models.user.Users.client_method",
|
|
|
|
|
|
return_value=[
|
|
|
|
|
|
current_user,
|
|
|
|
|
|
other_user,
|
|
|
|
|
|
],
|
|
|
|
|
|
)
|
2018-01-26 17:14:00 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
page = client_request.get("main.manage_users", service_id=SERVICE_ONE_ID)
|
2016-02-29 17:35:21 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert normalize_spaces(page.select_one("h1").text) == "Team members"
|
|
|
|
|
|
assert (
|
|
|
|
|
|
normalize_spaces(page.select(".user-list-item")[0].text) == expected_self_text
|
|
|
|
|
|
)
|
2023-10-26 11:38:03 -07:00
|
|
|
|
|
2023-11-09 12:00:31 -07:00
|
|
|
|
expected = "ZZZZZZZZ zzzzzzz@example.gsa.gov " "Permissions " "Can See dashboard"
|
2023-10-26 11:38:03 -07:00
|
|
|
|
|
|
|
|
|
|
if add_details is True:
|
|
|
|
|
|
expected = f"{expected} Change details for ZZZZZZZZ zzzzzzz@example.gsa.gov"
|
|
|
|
|
|
assert normalize_spaces(page.select(".user-list-item")[6].text) == expected
|
Make user API client return JSON, not a model
The data flow of other bits of our application looks like this:
```
API (returns JSON)
⬇
API client (returns a built in type, usually `dict`)
⬇
Model (returns an instance, eg of type `Service`)
⬇
View (returns HTML)
```
The user API client was architected weirdly, in that it returned a model
directly, like this:
```
API (returns JSON)
⬇
API client (returns a model, of type `User`, `InvitedUser`, etc)
⬇
View (returns HTML)
```
This mixing of different layers of the application is bad because it
makes it hard to write model code that doesn’t have circular
dependencies. As our application gets more complicated we will be
relying more on models to manage this complexity, so we should make it
easy, not hard to write them.
It also means that most of our mocking was of the User model, not just
the underlying JSON. So it would have been easy to introduce subtle bugs
to the user model, because it wasn’t being comprehensively tested. A lot
of the changed lines of code in this commit mean changing the tests to
mock only the JSON, which means that the model layer gets implicitly
tested.
For those reasons this commit changes the user API client to return
JSON, not an instance of `User` or other models.
2019-05-23 15:27:35 +01:00
|
|
|
|
mock_get_users.assert_called_once_with(SERVICE_ONE_ID)
|
2016-02-19 15:02:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
|
|
"state",
|
2023-09-11 16:51:30 -04:00
|
|
|
|
[
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"active",
|
|
|
|
|
|
"pending",
|
2023-09-11 16:51:30 -04:00
|
|
|
|
],
|
2023-08-25 09:12:23 -07:00
|
|
|
|
)
|
2022-05-04 16:46:00 +01:00
|
|
|
|
def test_should_show_change_details_link(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
mock_get_invites_for_service,
|
|
|
|
|
|
mock_get_template_folders,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
active_caseworking_user,
|
|
|
|
|
|
state,
|
|
|
|
|
|
):
|
|
|
|
|
|
current_user = active_user_with_permissions
|
|
|
|
|
|
|
|
|
|
|
|
other_user = active_caseworking_user
|
2023-08-25 09:12:23 -07:00
|
|
|
|
other_user["id"] = uuid.uuid4()
|
|
|
|
|
|
other_user["email_address"] = "zzzzzzz@example.gsa.gov"
|
|
|
|
|
|
other_user["state"] = state
|
2022-05-04 16:46:00 +01:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker.patch("app.user_api_client.get_user", return_value=current_user)
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.Users.client_method",
|
|
|
|
|
|
return_value=[
|
|
|
|
|
|
current_user,
|
|
|
|
|
|
other_user,
|
|
|
|
|
|
],
|
|
|
|
|
|
)
|
2022-05-04 16:46:00 +01:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
page = client_request.get("main.manage_users", service_id=SERVICE_ONE_ID)
|
|
|
|
|
|
link = page.select(".user-list-item")[-1].select_one("a")
|
2022-05-04 16:46:00 +01:00
|
|
|
|
|
|
|
|
|
|
assert normalize_spaces(link.text) == (
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"Change details for Test User zzzzzzz@example.gsa.gov"
|
2022-05-04 16:46:00 +01:00
|
|
|
|
)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert link["href"] == url_for(
|
|
|
|
|
|
".edit_user_permissions",
|
2022-05-04 16:46:00 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=other_user["id"],
|
2022-05-04 16:46:00 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
|
|
"number_of_users",
|
2023-09-11 16:51:30 -04:00
|
|
|
|
[
|
2023-08-25 09:12:23 -07:00
|
|
|
|
pytest.param(7),
|
|
|
|
|
|
pytest.param(8),
|
2023-09-11 16:51:30 -04:00
|
|
|
|
],
|
2023-08-25 09:12:23 -07:00
|
|
|
|
)
|
2021-11-04 11:28:31 +00:00
|
|
|
|
def test_should_show_live_search_if_more_than_7_users(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
mock_get_invites_for_service,
|
|
|
|
|
|
mock_get_template_folders,
|
|
|
|
|
|
mock_has_no_jobs,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
active_user_view_permissions,
|
|
|
|
|
|
number_of_users,
|
|
|
|
|
|
):
|
|
|
|
|
|
mocker.patch(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"app.user_api_client.get_user", return_value=active_user_with_permissions
|
|
|
|
|
|
)
|
|
|
|
|
|
mocker.patch("app.models.user.InvitedUsers.client_method", return_value=[])
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.Users.client_method",
|
|
|
|
|
|
return_value=[active_user_with_permissions] * number_of_users,
|
2021-11-04 11:28:31 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
page = client_request.get("main.manage_users", service_id=SERVICE_ONE_ID)
|
2021-11-04 11:28:31 +00:00
|
|
|
|
|
2023-05-26 14:52:33 -07:00
|
|
|
|
if number_of_users == 7:
|
|
|
|
|
|
with pytest.raises(expected_exception=TypeError):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert page.select_one("div[data-module=live-search]")["data-targets"] == (
|
2023-05-26 14:52:33 -07:00
|
|
|
|
".user-list-item"
|
|
|
|
|
|
)
|
|
|
|
|
|
return
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert page.select_one("div[data-module=live-search]")["data-targets"] == (
|
2021-11-04 11:28:31 +00:00
|
|
|
|
".user-list-item"
|
|
|
|
|
|
)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert len(page.select(".user-list-item")) == number_of_users
|
2021-11-04 11:28:31 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
textbox = page.select_one("[data-module=autofocus] .usa-input")
|
|
|
|
|
|
assert "value" not in textbox
|
|
|
|
|
|
assert textbox["name"] == "search"
|
2021-11-04 11:28:31 +00:00
|
|
|
|
# data-module=autofocus is set on a containing element so it
|
|
|
|
|
|
# shouldn’t also be set on the textbox itself
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert "data-module" not in textbox
|
|
|
|
|
|
assert not page.select_one("[data-force-focus]")
|
|
|
|
|
|
assert textbox["class"] == [
|
|
|
|
|
|
"usa-input",
|
2021-11-04 11:28:31 +00:00
|
|
|
|
]
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert (
|
|
|
|
|
|
normalize_spaces(page.select_one("label[for=search]").text)
|
|
|
|
|
|
== "Search by name or email address"
|
|
|
|
|
|
)
|
2021-11-04 11:28:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
2018-06-12 14:29:47 +01:00
|
|
|
|
def test_should_show_caseworker_on_overview_page(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
mock_get_invites_for_service,
|
2019-05-17 13:06:26 +01:00
|
|
|
|
mock_get_template_folders,
|
2018-06-12 14:29:47 +01:00
|
|
|
|
service_one,
|
2019-12-19 16:59:07 +00:00
|
|
|
|
active_user_view_permissions,
|
|
|
|
|
|
active_caseworking_user,
|
2018-06-12 14:29:47 +01:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["permissions"].append("caseworking")
|
2019-12-19 16:59:07 +00:00
|
|
|
|
current_user = active_user_view_permissions
|
|
|
|
|
|
|
|
|
|
|
|
other_user = active_caseworking_user
|
2023-08-25 09:12:23 -07:00
|
|
|
|
other_user["id"] = uuid.uuid4()
|
|
|
|
|
|
other_user["email_address"] = "zzzzzzz@example.gsa.gov"
|
2018-06-12 14:29:47 +01:00
|
|
|
|
|
2023-01-19 17:29:21 -05:00
|
|
|
|
client_request.login(current_user)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.Users.client_method",
|
|
|
|
|
|
return_value=[
|
|
|
|
|
|
current_user,
|
|
|
|
|
|
other_user,
|
|
|
|
|
|
],
|
2018-06-12 14:29:47 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
page = client_request.get("main.manage_users", service_id=SERVICE_ONE_ID)
|
2018-06-12 14:29:47 +01:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert normalize_spaces(page.select_one("h1").text) == "Team members"
|
|
|
|
|
|
assert normalize_spaces(page.select(".user-list-item")[0].text) == (
|
2023-12-18 15:38:36 -05:00
|
|
|
|
"Test User With Permissions(you) " "Permissions " "Can See dashboard"
|
2017-11-01 15:36:27 +00:00
|
|
|
|
)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
# [1:5] are invited users
|
|
|
|
|
|
assert normalize_spaces(page.select(".user-list-item")[6].text) == (
|
2023-11-09 12:00:31 -07:00
|
|
|
|
"Test User zzzzzzz@example.gsa.gov " "Permissions " "Can Send messages"
|
2023-08-25 09:12:23 -07:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
2023-09-11 16:51:30 -04:00
|
|
|
|
("endpoint", "extra_args", "service_has_email_auth", "auth_options_hidden"),
|
2023-08-25 09:12:23 -07:00
|
|
|
|
[
|
|
|
|
|
|
("main.edit_user_permissions", {"user_id": sample_uuid()}, True, False),
|
|
|
|
|
|
("main.edit_user_permissions", {"user_id": sample_uuid()}, False, True),
|
|
|
|
|
|
("main.invite_user", {}, True, False),
|
|
|
|
|
|
("main.invite_user", {}, False, True),
|
|
|
|
|
|
],
|
|
|
|
|
|
)
|
2017-11-01 15:36:27 +00:00
|
|
|
|
def test_service_with_no_email_auth_hides_auth_type_options(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
endpoint,
|
|
|
|
|
|
extra_args,
|
|
|
|
|
|
service_has_email_auth,
|
|
|
|
|
|
auth_options_hidden,
|
2019-02-25 16:51:37 +00:00
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_users_by_service,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mock_get_template_folders,
|
2023-10-23 14:41:31 -07:00
|
|
|
|
platform_admin_user,
|
2017-11-01 15:36:27 +00:00
|
|
|
|
):
|
|
|
|
|
|
if service_has_email_auth:
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["permissions"].append("email_auth")
|
2023-10-23 14:41:31 -07:00
|
|
|
|
client_request.login(platform_admin_user)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
page = client_request.get(endpoint, service_id=service_one["id"], **extra_args)
|
|
|
|
|
|
assert (
|
|
|
|
|
|
page.find("input", attrs={"name": "login_authentication"}) is None
|
|
|
|
|
|
) == auth_options_hidden
|
2017-11-01 15:36:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
2023-09-11 16:51:30 -04:00
|
|
|
|
@pytest.mark.parametrize("service_has_caseworking", [True, False])
|
2023-08-25 09:12:23 -07:00
|
|
|
|
@pytest.mark.parametrize(
|
2023-09-11 16:51:30 -04:00
|
|
|
|
("endpoint", "extra_args"),
|
2023-08-25 09:12:23 -07:00
|
|
|
|
[
|
|
|
|
|
|
(
|
|
|
|
|
|
"main.edit_user_permissions",
|
|
|
|
|
|
{"user_id": sample_uuid()},
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
"main.invite_user",
|
|
|
|
|
|
{},
|
|
|
|
|
|
),
|
|
|
|
|
|
],
|
|
|
|
|
|
)
|
2018-06-12 14:29:47 +01:00
|
|
|
|
def test_service_without_caseworking_doesnt_show_admin_vs_caseworker(
|
|
|
|
|
|
client_request,
|
2019-02-25 16:51:37 +00:00
|
|
|
|
mock_get_users_by_service,
|
2019-02-25 16:23:28 +00:00
|
|
|
|
mock_get_template_folders,
|
2018-06-12 14:29:47 +01:00
|
|
|
|
endpoint,
|
|
|
|
|
|
service_has_caseworking,
|
2018-08-06 11:10:37 +01:00
|
|
|
|
extra_args,
|
2023-10-23 14:41:31 -07:00
|
|
|
|
platform_admin_user,
|
2018-06-12 14:29:47 +01:00
|
|
|
|
):
|
2023-10-23 14:41:31 -07:00
|
|
|
|
client_request.login(platform_admin_user)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
page = client_request.get(endpoint, service_id=SERVICE_ONE_ID, **extra_args)
|
|
|
|
|
|
permission_checkboxes = page.select("input[type=checkbox]")
|
2020-07-31 15:06:03 +01:00
|
|
|
|
|
|
|
|
|
|
for idx in range(len(permission_checkboxes)):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert permission_checkboxes[idx]["name"] == "permissions_field"
|
|
|
|
|
|
assert permission_checkboxes[0]["value"] == "view_activity"
|
|
|
|
|
|
assert permission_checkboxes[1]["value"] == "send_messages"
|
|
|
|
|
|
assert permission_checkboxes[2]["value"] == "manage_templates"
|
|
|
|
|
|
assert permission_checkboxes[3]["value"] == "manage_service"
|
|
|
|
|
|
assert permission_checkboxes[4]["value"] == "manage_api_keys"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
2023-09-11 16:51:30 -04:00
|
|
|
|
("service_has_email_auth", "displays_auth_type"), [(True, True), (False, False)]
|
2023-08-25 09:12:23 -07:00
|
|
|
|
)
|
2017-11-01 15:36:27 +00:00
|
|
|
|
def test_manage_users_page_shows_member_auth_type_if_service_has_email_auth_activated(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_has_email_auth,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_get_invites_for_service,
|
2019-05-17 13:06:26 +01:00
|
|
|
|
mock_get_template_folders,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
displays_auth_type,
|
2017-11-01 15:36:27 +00:00
|
|
|
|
):
|
|
|
|
|
|
if service_has_email_auth:
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["permissions"].append("email_auth")
|
|
|
|
|
|
page = client_request.get("main.manage_users", service_id=service_one["id"])
|
|
|
|
|
|
assert bool(page.select_one(".tick-cross-list-hint")) == displays_auth_type
|
2017-11-01 15:36:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
@pytest.mark.parametrize(
|
2023-09-11 16:51:30 -04:00
|
|
|
|
("sms_option_disabled", "mobile_number", "expected_label"),
|
2023-08-25 09:12:23 -07:00
|
|
|
|
[
|
|
|
|
|
|
(
|
|
|
|
|
|
True,
|
|
|
|
|
|
None,
|
|
|
|
|
|
"""
|
2017-11-15 16:04:50 +00:00
|
|
|
|
Text message code
|
2019-09-13 12:49:40 +01:00
|
|
|
|
Not available because this team member has not added a
|
2017-11-15 16:04:50 +00:00
|
|
|
|
phone number to their profile
|
|
|
|
|
|
""",
|
2023-08-25 09:12:23 -07:00
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
False,
|
|
|
|
|
|
"202-867-5303",
|
|
|
|
|
|
"""
|
2017-11-15 16:04:50 +00:00
|
|
|
|
Text message code
|
|
|
|
|
|
""",
|
2023-08-25 09:12:23 -07:00
|
|
|
|
),
|
|
|
|
|
|
],
|
|
|
|
|
|
)
|
2017-11-01 15:36:27 +00:00
|
|
|
|
def test_user_with_no_mobile_number_cant_be_set_to_sms_auth(
|
|
|
|
|
|
client_request,
|
2019-02-25 16:51:37 +00:00
|
|
|
|
mock_get_users_by_service,
|
2019-02-25 16:23:28 +00:00
|
|
|
|
mock_get_template_folders,
|
2017-11-01 15:36:27 +00:00
|
|
|
|
sms_option_disabled,
|
2019-12-19 16:59:07 +00:00
|
|
|
|
mobile_number,
|
2017-11-15 16:04:50 +00:00
|
|
|
|
expected_label,
|
2017-11-01 15:36:27 +00:00
|
|
|
|
service_one,
|
2019-06-05 12:14:50 +01:00
|
|
|
|
mocker,
|
2019-12-19 16:59:07 +00:00
|
|
|
|
active_user_with_permissions,
|
2017-11-01 15:36:27 +00:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
active_user_with_permissions["mobile_number"] = mobile_number
|
2019-12-19 16:59:07 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["permissions"].append("email_auth")
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.user_api_client.get_user", return_value=active_user_with_permissions
|
|
|
|
|
|
)
|
2017-11-01 15:36:27 +00:00
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_permissions",
|
|
|
|
|
|
service_id=service_one["id"],
|
2019-02-25 16:51:37 +00:00
|
|
|
|
user_id=sample_uuid(),
|
2017-11-01 15:36:27 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
sms_auth_radio_button = page.select_one('input[value="sms_auth"]')
|
|
|
|
|
|
assert sms_auth_radio_button.has_attr("disabled") == sms_option_disabled
|
2017-11-15 16:04:50 +00:00
|
|
|
|
assert normalize_spaces(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
page.select_one("label[for=login_authentication-0]").text
|
2017-11-15 16:04:50 +00:00
|
|
|
|
) == normalize_spaces(expected_label)
|
2017-11-01 15:36:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
@pytest.mark.parametrize(
|
2023-09-11 16:51:30 -04:00
|
|
|
|
("endpoint", "extra_args", "expected_checkboxes"),
|
2023-08-25 09:12:23 -07:00
|
|
|
|
[
|
|
|
|
|
|
(
|
|
|
|
|
|
"main.edit_user_permissions",
|
|
|
|
|
|
{"user_id": sample_uuid()},
|
|
|
|
|
|
[
|
|
|
|
|
|
("view_activity", True),
|
|
|
|
|
|
("send_messages", True),
|
|
|
|
|
|
("manage_templates", True),
|
|
|
|
|
|
("manage_service", True),
|
|
|
|
|
|
("manage_api_keys", True),
|
|
|
|
|
|
],
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
"main.invite_user",
|
|
|
|
|
|
{},
|
|
|
|
|
|
[
|
|
|
|
|
|
("view_activity", False),
|
|
|
|
|
|
("send_messages", False),
|
|
|
|
|
|
("manage_templates", False),
|
|
|
|
|
|
("manage_service", False),
|
|
|
|
|
|
("manage_api_keys", False),
|
|
|
|
|
|
],
|
|
|
|
|
|
),
|
|
|
|
|
|
],
|
|
|
|
|
|
)
|
2016-02-19 15:02:13 +00:00
|
|
|
|
def test_should_show_page_for_one_user(
|
2017-08-17 10:44:36 +01:00
|
|
|
|
client_request,
|
2019-02-25 16:51:37 +00:00
|
|
|
|
mock_get_users_by_service,
|
2019-02-25 16:23:28 +00:00
|
|
|
|
mock_get_template_folders,
|
2017-08-17 10:49:21 +01:00
|
|
|
|
endpoint,
|
|
|
|
|
|
extra_args,
|
|
|
|
|
|
expected_checkboxes,
|
2023-10-23 14:41:31 -07:00
|
|
|
|
platform_admin_user,
|
2016-02-19 15:02:13 +00:00
|
|
|
|
):
|
2023-10-23 14:41:31 -07:00
|
|
|
|
client_request.login(platform_admin_user)
|
2017-08-17 10:49:21 +01:00
|
|
|
|
page = client_request.get(endpoint, service_id=SERVICE_ONE_ID, **extra_args)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
checkboxes = page.select("input[type=checkbox]")
|
2017-08-17 10:49:21 +01:00
|
|
|
|
|
2018-08-06 11:10:37 +01:00
|
|
|
|
assert len(checkboxes) == 5
|
2017-08-17 10:49:21 +01:00
|
|
|
|
|
|
|
|
|
|
for index, expected in enumerate(expected_checkboxes):
|
2020-04-23 10:57:24 +01:00
|
|
|
|
expected_input_value, expected_checked = expected
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert checkboxes[index]["name"] == "permissions_field"
|
|
|
|
|
|
assert checkboxes[index]["value"] == expected_input_value
|
|
|
|
|
|
assert checkboxes[index].has_attr("checked") == expected_checked
|
2016-02-19 15:02:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
2019-03-12 16:53:46 +00:00
|
|
|
|
def test_invite_user_allows_to_choose_auth(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_get_template_folders,
|
|
|
|
|
|
service_one,
|
2023-10-23 14:41:31 -07:00
|
|
|
|
platform_admin_user,
|
2019-03-12 16:53:46 +00:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["permissions"].append("email_auth")
|
2023-10-23 14:41:31 -07:00
|
|
|
|
client_request.login(platform_admin_user)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
page = client_request.get("main.invite_user", service_id=SERVICE_ONE_ID)
|
2019-03-12 16:53:46 +00:00
|
|
|
|
|
2021-06-30 15:29:02 +01:00
|
|
|
|
radio_buttons = page.select("input[name=login_authentication]")
|
|
|
|
|
|
values = {button["value"] for button in radio_buttons}
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert values == {"sms_auth", "email_auth"}
|
2021-06-30 15:29:02 +01:00
|
|
|
|
assert not any(button.has_attr("disabled") for button in radio_buttons)
|
2019-03-12 16:53:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
2019-07-16 09:01:21 +01:00
|
|
|
|
def test_invite_user_has_correct_email_field(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_get_template_folders,
|
2023-10-23 14:41:31 -07:00
|
|
|
|
platform_admin_user,
|
2019-07-16 09:01:21 +01:00
|
|
|
|
):
|
2023-10-23 14:41:31 -07:00
|
|
|
|
client_request.login(platform_admin_user)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
email_field = client_request.get(
|
|
|
|
|
|
"main.invite_user", service_id=SERVICE_ONE_ID
|
|
|
|
|
|
).select_one("#email_address")
|
|
|
|
|
|
assert email_field["spellcheck"] == "false"
|
|
|
|
|
|
assert "autocomplete" not in email_field
|
2019-07-16 09:01:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
2019-02-25 16:51:37 +00:00
|
|
|
|
def test_should_not_show_page_for_non_team_member(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
):
|
|
|
|
|
|
client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_permissions",
|
2019-02-25 16:51:37 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
user_id=USER_ONE_ID,
|
|
|
|
|
|
_expected_status=404,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
@pytest.mark.parametrize(
|
2023-09-11 16:51:30 -04:00
|
|
|
|
("submitted_permissions", "permissions_sent_to_api"),
|
2023-08-25 09:12:23 -07:00
|
|
|
|
[
|
|
|
|
|
|
(
|
|
|
|
|
|
{
|
|
|
|
|
|
"permissions_field": [
|
|
|
|
|
|
"view_activity",
|
|
|
|
|
|
"send_messages",
|
|
|
|
|
|
"manage_templates",
|
|
|
|
|
|
"manage_service",
|
|
|
|
|
|
"manage_api_keys",
|
|
|
|
|
|
]
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"view_activity",
|
|
|
|
|
|
"send_messages",
|
|
|
|
|
|
"manage_service",
|
|
|
|
|
|
"manage_templates",
|
|
|
|
|
|
"manage_api_keys",
|
|
|
|
|
|
},
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
{
|
|
|
|
|
|
"permissions_field": [
|
|
|
|
|
|
"view_activity",
|
|
|
|
|
|
"send_messages",
|
|
|
|
|
|
"manage_templates",
|
|
|
|
|
|
]
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"view_activity",
|
|
|
|
|
|
"send_messages",
|
|
|
|
|
|
"manage_templates",
|
|
|
|
|
|
},
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
{},
|
|
|
|
|
|
set(),
|
|
|
|
|
|
),
|
|
|
|
|
|
],
|
|
|
|
|
|
)
|
2018-08-06 11:10:37 +01:00
|
|
|
|
def test_edit_user_permissions(
|
|
|
|
|
|
client_request,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
mocker,
|
2019-02-25 16:51:37 +00:00
|
|
|
|
mock_get_users_by_service,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
mock_get_invites_for_service,
|
|
|
|
|
|
mock_set_user_permissions,
|
2019-02-25 16:23:28 +00:00
|
|
|
|
mock_get_template_folders,
|
2018-08-06 11:10:37 +01:00
|
|
|
|
fake_uuid,
|
|
|
|
|
|
submitted_permissions,
|
|
|
|
|
|
permissions_sent_to_api,
|
2016-02-19 15:02:13 +00:00
|
|
|
|
):
|
2018-08-06 11:10:37 +01:00
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_permissions",
|
2018-08-06 11:10:37 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
user_id=fake_uuid,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
_data=dict(email_address="test@example.com", **submitted_permissions),
|
2018-08-06 11:10:37 +01:00
|
|
|
|
_expected_status=302,
|
|
|
|
|
|
_expected_redirect=url_for(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.manage_users",
|
2018-08-06 11:10:37 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
),
|
2017-02-03 12:07:21 +00:00
|
|
|
|
)
|
|
|
|
|
|
mock_set_user_permissions.assert_called_with(
|
2018-08-06 11:10:37 +01:00
|
|
|
|
fake_uuid,
|
|
|
|
|
|
SERVICE_ONE_ID,
|
|
|
|
|
|
permissions=permissions_sent_to_api,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
folder_permissions=[],
|
2019-02-27 15:45:18 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_edit_user_folder_permissions(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_get_invites_for_service,
|
|
|
|
|
|
mock_set_user_permissions,
|
|
|
|
|
|
mock_get_template_folders,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
):
|
|
|
|
|
|
mock_get_template_folders.return_value = [
|
2023-08-25 09:12:23 -07:00
|
|
|
|
{
|
|
|
|
|
|
"id": "folder-id-1",
|
|
|
|
|
|
"name": "folder_one",
|
|
|
|
|
|
"parent_id": None,
|
|
|
|
|
|
"users_with_permission": [],
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "folder-id-2",
|
|
|
|
|
|
"name": "folder_one",
|
|
|
|
|
|
"parent_id": None,
|
|
|
|
|
|
"users_with_permission": [],
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "folder-id-3",
|
|
|
|
|
|
"name": "folder_one",
|
|
|
|
|
|
"parent_id": "folder-id-1",
|
|
|
|
|
|
"users_with_permission": [],
|
|
|
|
|
|
},
|
2019-02-27 15:45:18 +00:00
|
|
|
|
]
|
2019-05-17 11:03:41 +01:00
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_permissions",
|
2019-05-17 11:03:41 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
user_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
assert [
|
2023-08-25 09:12:23 -07:00
|
|
|
|
item["value"] for item in page.select("input[name=folder_permissions]")
|
|
|
|
|
|
] == ["folder-id-1", "folder-id-3", "folder-id-2"]
|
2019-05-17 11:03:41 +01:00
|
|
|
|
|
2019-02-27 15:45:18 +00:00
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_permissions",
|
2019-02-27 15:45:18 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
user_id=fake_uuid,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
_data=dict(folder_permissions=["folder-id-1", "folder-id-3"]),
|
2019-02-27 15:45:18 +00:00
|
|
|
|
_expected_status=302,
|
|
|
|
|
|
_expected_redirect=url_for(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.manage_users",
|
2019-02-27 15:45:18 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
mock_set_user_permissions.assert_called_with(
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
SERVICE_ONE_ID,
|
|
|
|
|
|
permissions=set(),
|
2023-08-25 09:12:23 -07:00
|
|
|
|
folder_permissions=["folder-id-1", "folder-id-3"],
|
2017-02-03 12:07:21 +00:00
|
|
|
|
)
|
2016-02-19 15:02:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
2019-04-03 17:20:32 +01:00
|
|
|
|
def test_cant_edit_user_folder_permissions_for_platform_admin_users(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_get_invites_for_service,
|
|
|
|
|
|
mock_set_user_permissions,
|
|
|
|
|
|
mock_get_template_folders,
|
2019-12-19 16:59:07 +00:00
|
|
|
|
platform_admin_user,
|
2019-04-03 17:20:32 +01:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["permissions"] = ["edit_folder_permissions"]
|
|
|
|
|
|
mocker.patch("app.user_api_client.get_user", return_value=platform_admin_user)
|
2019-04-03 17:20:32 +01:00
|
|
|
|
mock_get_template_folders.return_value = [
|
2023-08-25 09:12:23 -07:00
|
|
|
|
{
|
|
|
|
|
|
"id": "folder-id-1",
|
|
|
|
|
|
"name": "folder_one",
|
|
|
|
|
|
"parent_id": None,
|
|
|
|
|
|
"users_with_permission": [],
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "folder-id-2",
|
|
|
|
|
|
"name": "folder_one",
|
|
|
|
|
|
"parent_id": None,
|
|
|
|
|
|
"users_with_permission": [],
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "folder-id-3",
|
|
|
|
|
|
"name": "folder_one",
|
|
|
|
|
|
"parent_id": "folder-id-1",
|
|
|
|
|
|
"users_with_permission": [],
|
|
|
|
|
|
},
|
2019-04-03 17:20:32 +01:00
|
|
|
|
]
|
|
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_permissions",
|
2019-04-03 17:20:32 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=platform_admin_user["id"],
|
|
|
|
|
|
)
|
|
|
|
|
|
assert (
|
|
|
|
|
|
normalize_spaces(page.select("main .usa-body")[0].text)
|
|
|
|
|
|
== "platform@admin.gsa.gov Change email address"
|
2019-04-03 17:20:32 +01:00
|
|
|
|
)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert normalize_spaces(page.select("main .usa-body")[1].text) == (
|
|
|
|
|
|
"Platform admin users can access all template folders."
|
2019-05-17 11:03:41 +01:00
|
|
|
|
)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert page.select("input[name=folder_permissions]") == []
|
2019-04-03 17:20:32 +01:00
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_permissions",
|
2019-04-03 17:20:32 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=platform_admin_user["id"],
|
2019-05-17 11:03:41 +01:00
|
|
|
|
_data={},
|
2019-04-03 17:20:32 +01:00
|
|
|
|
_expected_status=302,
|
|
|
|
|
|
_expected_redirect=url_for(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.manage_users",
|
2019-04-03 17:20:32 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
mock_set_user_permissions.assert_called_with(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
platform_admin_user["id"],
|
2019-04-03 17:20:32 +01:00
|
|
|
|
SERVICE_ONE_ID,
|
2019-05-17 11:03:41 +01:00
|
|
|
|
permissions={
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"manage_api_keys",
|
|
|
|
|
|
"manage_service",
|
|
|
|
|
|
"manage_templates",
|
|
|
|
|
|
"send_messages",
|
|
|
|
|
|
"view_activity",
|
2019-05-17 11:03:41 +01:00
|
|
|
|
},
|
|
|
|
|
|
folder_permissions=None,
|
2019-04-03 17:20:32 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-02-25 16:51:37 +00:00
|
|
|
|
def test_cant_edit_non_member_user_permissions(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_set_user_permissions,
|
|
|
|
|
|
):
|
|
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_permissions",
|
2019-02-25 16:51:37 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
user_id=USER_ONE_ID,
|
|
|
|
|
|
_data={
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"email_address": "test@example.com",
|
|
|
|
|
|
"manage_service": "y",
|
2019-02-25 16:51:37 +00:00
|
|
|
|
},
|
|
|
|
|
|
_expected_status=404,
|
|
|
|
|
|
)
|
|
|
|
|
|
assert mock_set_user_permissions.called is False
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-11-01 15:36:27 +00:00
|
|
|
|
def test_edit_user_permissions_including_authentication_with_email_auth_service(
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
2017-11-01 15:36:27 +00:00
|
|
|
|
active_user_with_permissions,
|
2019-02-25 16:51:37 +00:00
|
|
|
|
mock_get_users_by_service,
|
2017-11-01 15:36:27 +00:00
|
|
|
|
mock_get_invites_for_service,
|
|
|
|
|
|
mock_set_user_permissions,
|
|
|
|
|
|
mock_update_user_attribute,
|
fix bug stopping editing of permissions of webauthn platform admins
We hide the radio field in the HTML for platform admins, as we don't
want anyone to be able to change their auth type. However, when the form
is validated, the form has a field called login_authentication that it
expects a value for. It silently fails as it complains that when the
user POSTed they didn't select a value for that radio field, but the
error message is on the radio fields that don't get displayed to the
user so they'd never know.
Fixing this is actually pretty hard.
We use this form in two places, one where we have a user to edit, one
where we are creating an invite from scratch. So sometimes we don't know
about a user's auth type. In addition, radio buttons are mandatory by
design, but now sometimes we don't just want to make it optional but
explicitly ignore the value being passed in? To solve this, remove the
field entirely from the form if the user is a platform admin. This means
that if the code in manage_users.py tries to access the
login_authentication value from the form, it'll error, but I think
that's okay to leave for now given we concede that this isn't a perfect
final solution.
The tests didn't flag this previously as they tried to set from sms_auth
(the default for `platform_admin_user`) TO email_auth or sms_auth. Also,
the diagnosis of this bug was confounded further by the fact that
`mock_get_users_by_service` sets what is returned by the API - the
service model then takes the IDs out of that response and calls
`User.get_user_by_id` for the matching ID (as in, the code only uses
get_users_by_service to ensure the user belongs to that service). This
means that we accidentally set the form editing the current user, as
when we log in we set `get_user_by_id` to return the user of our choice
2021-06-10 23:09:36 +01:00
|
|
|
|
mock_get_template_folders,
|
2017-11-01 15:36:27 +00:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
active_user_with_permissions["auth_type"] = "email_auth"
|
|
|
|
|
|
service_one["permissions"].append("email_auth")
|
2017-11-01 15:36:27 +00:00
|
|
|
|
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_permissions",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
2019-03-26 12:35:32 +00:00
|
|
|
|
_data={
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"email_address": active_user_with_permissions["email_address"],
|
|
|
|
|
|
"permissions_field": [
|
|
|
|
|
|
"send_messages",
|
|
|
|
|
|
"manage_templates",
|
|
|
|
|
|
"manage_service",
|
|
|
|
|
|
"manage_api_keys",
|
2020-04-23 10:57:24 +01:00
|
|
|
|
],
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"login_authentication": "sms_auth",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
},
|
|
|
|
|
|
_expected_status=302,
|
|
|
|
|
|
_expected_redirect=url_for(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.manage_users",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
),
|
2017-11-01 15:36:27 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
mock_set_user_permissions.assert_called_with(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
str(active_user_with_permissions["id"]),
|
2019-03-26 12:35:32 +00:00
|
|
|
|
SERVICE_ONE_ID,
|
2017-11-01 15:36:27 +00:00
|
|
|
|
permissions={
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"send_messages",
|
|
|
|
|
|
"manage_templates",
|
|
|
|
|
|
"manage_service",
|
|
|
|
|
|
"manage_api_keys",
|
2019-02-27 15:45:18 +00:00
|
|
|
|
},
|
2023-08-25 09:12:23 -07:00
|
|
|
|
folder_permissions=[],
|
2017-11-01 15:36:27 +00:00
|
|
|
|
)
|
|
|
|
|
|
mock_update_user_attribute.assert_called_with(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
str(active_user_with_permissions["id"]), auth_type="sms_auth"
|
2017-11-01 15:36:27 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-06-30 15:29:02 +01:00
|
|
|
|
def test_edit_user_permissions_shows_authentication_for_email_auth_service(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_get_template_folders,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["permissions"].append("email_auth")
|
2021-06-30 15:29:02 +01:00
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_permissions",
|
2021-06-30 15:29:02 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
2021-06-30 15:29:02 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
radio_buttons = page.select("input[name=login_authentication]")
|
|
|
|
|
|
values = {button["value"] for button in radio_buttons}
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert values == {"sms_auth", "email_auth"}
|
2021-06-30 15:29:02 +01:00
|
|
|
|
assert not any(button.has_attr("disabled") for button in radio_buttons)
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-02-19 15:02:13 +00:00
|
|
|
|
def test_should_show_page_for_inviting_user(
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request,
|
2019-03-15 14:57:39 +00:00
|
|
|
|
mock_get_template_folders,
|
2023-12-11 16:59:04 -05:00
|
|
|
|
active_user_with_permissions,
|
2016-02-19 15:02:13 +00:00
|
|
|
|
):
|
2023-12-11 16:59:04 -05:00
|
|
|
|
client_request.login(active_user_with_permissions)
|
2019-03-26 12:35:32 +00:00
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.invite_user",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
)
|
2016-02-19 15:02:13 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert "Invite a team member" in page.find("h1").text.strip()
|
|
|
|
|
|
assert not page.find("div", class_="checkboxes-nested")
|
2019-03-15 14:57:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
2023-12-11 16:59:04 -05:00
|
|
|
|
def test_should_not_show_page_for_inviting_user_without_permissions(
|
2023-12-12 16:45:21 -05:00
|
|
|
|
client_request, mock_get_template_folders, active_user_empty_permissions
|
2023-12-11 16:59:04 -05:00
|
|
|
|
):
|
|
|
|
|
|
client_request.login(active_user_empty_permissions)
|
|
|
|
|
|
page = client_request.get(
|
2023-12-12 16:45:21 -05:00
|
|
|
|
"main.invite_user", service_id=SERVICE_ONE_ID, _expected_status=403
|
2023-12-11 16:59:04 -05:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert "not allowed to see this page" in page.h1.string.strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-06-08 10:58:15 +01:00
|
|
|
|
def test_should_show_page_for_inviting_user_with_email_prefilled(
|
|
|
|
|
|
client_request,
|
2020-06-08 14:39:36 +01:00
|
|
|
|
mocker,
|
|
|
|
|
|
service_one,
|
2020-06-08 10:58:15 +01:00
|
|
|
|
mock_get_template_folders,
|
|
|
|
|
|
fake_uuid,
|
2020-06-08 11:19:58 +01:00
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
active_user_with_permission_to_other_service,
|
2023-07-12 12:09:44 -04:00
|
|
|
|
mock_get_organization_by_domain,
|
2020-06-08 17:39:14 +01:00
|
|
|
|
mock_get_invites_for_service,
|
2020-06-08 10:58:15 +01:00
|
|
|
|
):
|
2023-01-19 17:29:21 -05:00
|
|
|
|
client_request.login(active_user_with_permissions)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["organization"] = ORGANISATION_ID
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.user_api_client.get_user",
|
|
|
|
|
|
side_effect=[
|
|
|
|
|
|
active_user_with_permission_to_other_service,
|
|
|
|
|
|
],
|
|
|
|
|
|
)
|
2020-06-08 11:19:58 +01:00
|
|
|
|
|
2020-06-08 10:58:15 +01:00
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.invite_user",
|
2020-06-08 10:58:15 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
user_id=fake_uuid,
|
|
|
|
|
|
# We have the user’s name in the H1 but don’t want it duplicated
|
|
|
|
|
|
# in the page title
|
2023-12-12 16:45:21 -05:00
|
|
|
|
_test_page_title=False,
|
2023-12-11 10:47:21 -05:00
|
|
|
|
)
|
|
|
|
|
|
assert normalize_spaces(page.select_one("title").text).startswith(
|
|
|
|
|
|
"Invite a team member"
|
2020-06-08 10:58:15 +01:00
|
|
|
|
)
|
2023-12-11 10:47:21 -05:00
|
|
|
|
assert normalize_spaces(page.select_one("h1").text) == ("Invite Service Two User")
|
|
|
|
|
|
assert not page.select("input#email_address") or page.select("input[type=email]")
|
2020-06-08 10:58:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
2020-06-08 11:19:58 +01:00
|
|
|
|
def test_should_show_page_if_prefilled_user_is_already_a_team_member(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mock_get_template_folders,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
active_user_with_permissions,
|
2023-12-12 16:45:21 -05:00
|
|
|
|
active_caseworking_user,
|
2020-06-08 11:19:58 +01:00
|
|
|
|
):
|
2023-12-11 16:59:04 -05:00
|
|
|
|
client_request.login(active_user_with_permissions)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.user_api_client.get_user",
|
|
|
|
|
|
side_effect=[
|
|
|
|
|
|
active_caseworking_user,
|
|
|
|
|
|
],
|
|
|
|
|
|
)
|
2020-06-08 11:19:58 +01:00
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.invite_user",
|
2020-06-08 11:19:58 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
user_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert normalize_spaces(page.select_one("title").text).startswith(
|
|
|
|
|
|
"This person is already a team member"
|
2020-06-08 11:19:58 +01:00
|
|
|
|
)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert normalize_spaces(page.select_one("h1").text) == (
|
|
|
|
|
|
"This person is already a team member"
|
2020-06-08 11:19:58 +01:00
|
|
|
|
)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert normalize_spaces(page.select_one("main p").text) == (
|
|
|
|
|
|
"Test User is already member of ‘service one’."
|
2020-06-08 11:19:58 +01:00
|
|
|
|
)
|
|
|
|
|
|
assert not page.select("form")
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-06-08 17:39:14 +01:00
|
|
|
|
def test_should_show_page_if_prefilled_user_is_already_invited(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mock_get_template_folders,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
active_user_with_permission_to_other_service,
|
|
|
|
|
|
mock_get_invites_for_service,
|
2023-10-23 14:41:31 -07:00
|
|
|
|
platform_admin_user,
|
2020-06-08 17:39:14 +01:00
|
|
|
|
):
|
2024-02-23 17:38:47 -05:00
|
|
|
|
active_user_with_permission_to_other_service["email_address"] = (
|
|
|
|
|
|
"user_1@testnotify.gsa.gov"
|
|
|
|
|
|
)
|
2023-10-23 14:41:31 -07:00
|
|
|
|
client_request.login(platform_admin_user)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.user_api_client.get_user",
|
|
|
|
|
|
side_effect=[
|
|
|
|
|
|
active_user_with_permission_to_other_service,
|
|
|
|
|
|
],
|
|
|
|
|
|
)
|
2020-06-08 17:39:14 +01:00
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.invite_user",
|
2020-06-08 17:39:14 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
user_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert normalize_spaces(page.select_one("title").text).startswith(
|
|
|
|
|
|
"This person has already received an invite"
|
2021-01-08 10:56:59 +00:00
|
|
|
|
)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert normalize_spaces(page.select_one("h1").text) == (
|
|
|
|
|
|
"This person has already received an invite"
|
2020-06-08 17:39:14 +01:00
|
|
|
|
)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert normalize_spaces(page.select_one("main .usa-body").text) == (
|
|
|
|
|
|
"Service Two User has not accepted their invitation to "
|
|
|
|
|
|
"‘service one’ yet. You do not need to do anything."
|
2021-01-08 10:56:59 +00:00
|
|
|
|
)
|
|
|
|
|
|
assert not page.select("form")
|
2020-06-08 17:39:14 +01:00
|
|
|
|
|
|
|
|
|
|
|
2023-07-12 12:09:44 -04:00
|
|
|
|
def test_should_403_if_trying_to_prefill_email_address_for_user_with_no_organization(
|
2020-06-08 14:39:36 +01:00
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_template_folders,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
active_user_with_permission_to_other_service,
|
2020-06-08 17:39:14 +01:00
|
|
|
|
mock_get_invites_for_service,
|
2023-07-12 12:09:44 -04:00
|
|
|
|
mock_get_no_organization_by_domain,
|
2020-06-08 14:39:36 +01:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["organization"] = ORGANISATION_ID
|
2023-01-19 17:29:21 -05:00
|
|
|
|
client_request.login(active_user_with_permissions)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.user_api_client.get_user",
|
|
|
|
|
|
side_effect=[
|
|
|
|
|
|
active_user_with_permission_to_other_service,
|
|
|
|
|
|
],
|
|
|
|
|
|
)
|
2020-06-08 14:39:36 +01:00
|
|
|
|
client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.invite_user",
|
2020-06-08 14:39:36 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
user_id=fake_uuid,
|
|
|
|
|
|
_expected_status=403,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-07-12 12:09:44 -04:00
|
|
|
|
def test_should_403_if_trying_to_prefill_email_address_for_user_from_other_organization(
|
2020-06-08 14:39:36 +01:00
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_template_folders,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
active_user_with_permission_to_other_service,
|
2020-06-08 17:39:14 +01:00
|
|
|
|
mock_get_invites_for_service,
|
2023-07-12 12:09:44 -04:00
|
|
|
|
mock_get_organization_by_domain,
|
2020-06-08 14:39:36 +01:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["organization"] = ORGANISATION_TWO_ID
|
2023-01-19 17:29:21 -05:00
|
|
|
|
client_request.login(active_user_with_permissions)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.user_api_client.get_user",
|
|
|
|
|
|
side_effect=[
|
|
|
|
|
|
active_user_with_permission_to_other_service,
|
|
|
|
|
|
],
|
|
|
|
|
|
)
|
2020-06-08 14:39:36 +01:00
|
|
|
|
client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.invite_user",
|
2020-06-08 14:39:36 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
user_id=fake_uuid,
|
|
|
|
|
|
_expected_status=403,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-03-15 14:57:39 +00:00
|
|
|
|
def test_should_show_folder_permission_form_if_service_has_folder_permissions_enabled(
|
2023-10-23 14:41:31 -07:00
|
|
|
|
client_request, mocker, mock_get_template_folders, service_one, platform_admin_user
|
2019-03-15 14:57:39 +00:00
|
|
|
|
):
|
2023-10-23 14:41:31 -07:00
|
|
|
|
client_request.login(platform_admin_user)
|
2019-03-15 14:57:39 +00:00
|
|
|
|
mock_get_template_folders.return_value = [
|
2023-08-25 09:12:23 -07:00
|
|
|
|
{
|
|
|
|
|
|
"id": "folder-id-1",
|
|
|
|
|
|
"name": "folder_one",
|
|
|
|
|
|
"parent_id": None,
|
|
|
|
|
|
"users_with_permission": [],
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "folder-id-2",
|
|
|
|
|
|
"name": "folder_two",
|
|
|
|
|
|
"parent_id": None,
|
|
|
|
|
|
"users_with_permission": [],
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "folder-id-3",
|
|
|
|
|
|
"name": "folder_three",
|
|
|
|
|
|
"parent_id": "folder-id-1",
|
|
|
|
|
|
"users_with_permission": [],
|
|
|
|
|
|
},
|
2019-03-15 14:57:39 +00:00
|
|
|
|
]
|
2019-03-26 12:35:32 +00:00
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.invite_user",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
)
|
2019-03-15 14:57:39 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert "Invite a team member" in page.find("h1").text.strip()
|
2019-03-15 14:57:39 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
folder_checkboxes = page.find("div", class_="selection-wrapper").find_all("li")
|
2019-03-15 14:57:39 +00:00
|
|
|
|
assert len(folder_checkboxes) == 3
|
2016-02-19 15:02:13 +00:00
|
|
|
|
|
2016-02-29 17:35:21 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
@pytest.mark.parametrize(
|
2023-09-11 16:51:30 -04:00
|
|
|
|
("email_address", "gov_user"),
|
2023-08-25 09:12:23 -07:00
|
|
|
|
[("test@example.gsa.gov", True), ("test@example.com", False)],
|
|
|
|
|
|
)
|
2016-02-29 17:35:21 +00:00
|
|
|
|
def test_invite_user(
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request,
|
2023-10-23 14:41:31 -07:00
|
|
|
|
platform_admin_user,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
mocker,
|
|
|
|
|
|
sample_invite,
|
|
|
|
|
|
email_address,
|
|
|
|
|
|
gov_user,
|
2019-03-15 14:57:39 +00:00
|
|
|
|
mock_get_template_folders,
|
2023-07-12 12:09:44 -04:00
|
|
|
|
mock_get_organizations,
|
2016-02-29 17:35:21 +00:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
sample_invite["email_address"] = email_address
|
2016-02-29 17:35:21 +00:00
|
|
|
|
|
2017-02-03 12:07:21 +00:00
|
|
|
|
assert is_gov_user(email_address) == gov_user
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.InvitedUsers.client_method", return_value=[sample_invite]
|
|
|
|
|
|
)
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.Users.client_method",
|
2023-10-23 14:41:31 -07:00
|
|
|
|
return_value=[platform_admin_user],
|
2023-08-25 09:12:23 -07:00
|
|
|
|
)
|
|
|
|
|
|
mocker.patch("app.invite_api_client.create_invite", return_value=sample_invite)
|
2023-10-23 14:41:31 -07:00
|
|
|
|
client_request.login(platform_admin_user)
|
2019-03-26 12:35:32 +00:00
|
|
|
|
page = client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.invite_user",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2020-07-31 15:16:56 +01:00
|
|
|
|
_data={
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"email_address": email_address,
|
|
|
|
|
|
"permissions_field": [
|
|
|
|
|
|
"view_activity",
|
|
|
|
|
|
"send_messages",
|
|
|
|
|
|
"manage_templates",
|
|
|
|
|
|
"manage_service",
|
|
|
|
|
|
"manage_api_keys",
|
|
|
|
|
|
],
|
2020-07-31 15:16:56 +01:00
|
|
|
|
},
|
2019-03-26 12:35:32 +00:00
|
|
|
|
_follow_redirects=True,
|
2017-02-03 12:07:21 +00:00
|
|
|
|
)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert page.h1.string.strip() == "Team members"
|
|
|
|
|
|
flash_banner = page.find("div", class_="banner-default-with-tick").string.strip()
|
2021-03-04 16:54:41 +00:00
|
|
|
|
assert flash_banner == f"Invite sent to {email_address}"
|
2017-02-03 12:07:21 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
expected_permissions = {
|
|
|
|
|
|
"manage_api_keys",
|
|
|
|
|
|
"manage_service",
|
|
|
|
|
|
"manage_templates",
|
|
|
|
|
|
"send_messages",
|
|
|
|
|
|
"view_activity",
|
|
|
|
|
|
}
|
2017-02-03 12:07:21 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
app.invite_api_client.create_invite.assert_called_once_with(
|
|
|
|
|
|
sample_invite["from_user"],
|
|
|
|
|
|
sample_invite["service"],
|
|
|
|
|
|
email_address,
|
|
|
|
|
|
expected_permissions,
|
|
|
|
|
|
"sms_auth",
|
|
|
|
|
|
[],
|
|
|
|
|
|
)
|
2017-11-01 15:36:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
2020-06-08 10:58:15 +01:00
|
|
|
|
def test_invite_user_when_email_address_is_prefilled(
|
|
|
|
|
|
client_request,
|
2020-06-08 14:39:36 +01:00
|
|
|
|
service_one,
|
2023-10-23 14:41:31 -07:00
|
|
|
|
platform_admin_user,
|
2020-06-08 11:19:58 +01:00
|
|
|
|
active_user_with_permission_to_other_service,
|
2020-06-08 10:58:15 +01:00
|
|
|
|
fake_uuid,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
sample_invite,
|
|
|
|
|
|
mock_get_template_folders,
|
2020-06-08 17:39:14 +01:00
|
|
|
|
mock_get_invites_for_service,
|
2023-07-12 12:09:44 -04:00
|
|
|
|
mock_get_organization_by_domain,
|
2020-06-08 10:58:15 +01:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["organization"] = ORGANISATION_ID
|
2023-10-23 14:41:31 -07:00
|
|
|
|
client_request.login(platform_admin_user)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.user_api_client.get_user",
|
|
|
|
|
|
side_effect=[
|
|
|
|
|
|
active_user_with_permission_to_other_service,
|
|
|
|
|
|
],
|
|
|
|
|
|
)
|
|
|
|
|
|
mocker.patch("app.invite_api_client.create_invite", return_value=sample_invite)
|
2020-06-08 10:58:15 +01:00
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.invite_user",
|
2020-06-08 10:58:15 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
user_id=fake_uuid,
|
|
|
|
|
|
_data={
|
|
|
|
|
|
# No posted email address
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"permissions_field": [
|
|
|
|
|
|
"send_messages",
|
2020-06-08 10:58:15 +01:00
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
app.invite_api_client.create_invite.assert_called_once_with(
|
2023-10-23 14:41:31 -07:00
|
|
|
|
platform_admin_user["id"],
|
2020-06-08 10:58:15 +01:00
|
|
|
|
SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
active_user_with_permission_to_other_service["email_address"],
|
|
|
|
|
|
{"send_messages"},
|
|
|
|
|
|
"sms_auth",
|
2020-06-08 10:58:15 +01:00
|
|
|
|
[],
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
@pytest.mark.parametrize("auth_type", [("sms_auth"), ("email_auth")])
|
|
|
|
|
|
@pytest.mark.parametrize(
|
2023-09-11 16:51:30 -04:00
|
|
|
|
("email_address", "gov_user"),
|
2023-08-25 09:12:23 -07:00
|
|
|
|
[("test@example.gsa.gov", True), ("test@example.com", False)],
|
|
|
|
|
|
)
|
2017-11-01 15:36:27 +00:00
|
|
|
|
def test_invite_user_with_email_auth_service(
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
2023-10-23 14:41:31 -07:00
|
|
|
|
platform_admin_user,
|
2017-11-01 15:36:27 +00:00
|
|
|
|
sample_invite,
|
|
|
|
|
|
email_address,
|
|
|
|
|
|
gov_user,
|
|
|
|
|
|
mocker,
|
2019-03-15 14:57:39 +00:00
|
|
|
|
auth_type,
|
2023-07-12 12:09:44 -04:00
|
|
|
|
mock_get_organizations,
|
2019-03-15 14:57:39 +00:00
|
|
|
|
mock_get_template_folders,
|
2017-11-01 15:36:27 +00:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["permissions"].append("email_auth")
|
|
|
|
|
|
sample_invite["email_address"] = "test@example.gsa.gov"
|
2017-11-01 15:36:27 +00:00
|
|
|
|
|
2019-05-28 16:11:54 +01:00
|
|
|
|
assert is_gov_user(email_address) is gov_user
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.InvitedUsers.client_method", return_value=[sample_invite]
|
|
|
|
|
|
)
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.Users.client_method",
|
2023-10-23 14:41:31 -07:00
|
|
|
|
return_value=[platform_admin_user],
|
2023-08-25 09:12:23 -07:00
|
|
|
|
)
|
|
|
|
|
|
mocker.patch("app.invite_api_client.create_invite", return_value=sample_invite)
|
Make user API client return JSON, not a model
The data flow of other bits of our application looks like this:
```
API (returns JSON)
⬇
API client (returns a built in type, usually `dict`)
⬇
Model (returns an instance, eg of type `Service`)
⬇
View (returns HTML)
```
The user API client was architected weirdly, in that it returned a model
directly, like this:
```
API (returns JSON)
⬇
API client (returns a model, of type `User`, `InvitedUser`, etc)
⬇
View (returns HTML)
```
This mixing of different layers of the application is bad because it
makes it hard to write model code that doesn’t have circular
dependencies. As our application gets more complicated we will be
relying more on models to manage this complexity, so we should make it
easy, not hard to write them.
It also means that most of our mocking was of the User model, not just
the underlying JSON. So it would have been easy to introduce subtle bugs
to the user model, because it wasn’t being comprehensively tested. A lot
of the changed lines of code in this commit mean changing the tests to
mock only the JSON, which means that the model layer gets implicitly
tested.
For those reasons this commit changes the user API client to return
JSON, not an instance of `User` or other models.
2019-05-23 15:27:35 +01:00
|
|
|
|
|
2023-10-23 14:41:31 -07:00
|
|
|
|
client_request.login(platform_admin_user)
|
2019-03-26 12:35:32 +00:00
|
|
|
|
page = client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.invite_user",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_data={
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"email_address": email_address,
|
|
|
|
|
|
"permissions_field": [
|
|
|
|
|
|
"view_activity",
|
|
|
|
|
|
"send_messages",
|
|
|
|
|
|
"manage_templates",
|
|
|
|
|
|
"manage_service",
|
|
|
|
|
|
"manage_api_keys",
|
2020-04-23 10:57:24 +01:00
|
|
|
|
],
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"login_authentication": auth_type,
|
2019-03-26 12:35:32 +00:00
|
|
|
|
},
|
|
|
|
|
|
_follow_redirects=True,
|
|
|
|
|
|
_expected_status=200,
|
2017-11-01 15:36:27 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert page.h1.string.strip() == "Team members"
|
|
|
|
|
|
flash_banner = page.find("div", class_="banner-default-with-tick").string.strip()
|
|
|
|
|
|
assert flash_banner == "Invite sent to test@example.gsa.gov"
|
2017-11-01 15:36:27 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
expected_permissions = {
|
|
|
|
|
|
"manage_api_keys",
|
|
|
|
|
|
"manage_service",
|
|
|
|
|
|
"manage_templates",
|
|
|
|
|
|
"send_messages",
|
|
|
|
|
|
"view_activity",
|
|
|
|
|
|
}
|
2017-11-01 15:36:27 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
app.invite_api_client.create_invite.assert_called_once_with(
|
|
|
|
|
|
sample_invite["from_user"],
|
|
|
|
|
|
sample_invite["service"],
|
|
|
|
|
|
email_address,
|
|
|
|
|
|
expected_permissions,
|
|
|
|
|
|
auth_type,
|
|
|
|
|
|
[],
|
|
|
|
|
|
)
|
2019-03-19 14:16:23 +00:00
|
|
|
|
|
|
|
|
|
|
|
2023-12-21 10:58:32 -05:00
|
|
|
|
def test_resend_expired_invitation(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mock_get_invites_for_service,
|
|
|
|
|
|
expired_invite,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_get_template_folders,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
):
|
2023-12-07 07:52:40 -05:00
|
|
|
|
mock_resend = mocker.patch("app.invite_api_client.resend_invite")
|
2023-12-21 10:58:32 -05:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.invite_api_client.get_invited_user_for_service",
|
|
|
|
|
|
return_value=expired_invite,
|
|
|
|
|
|
)
|
2023-12-07 07:52:40 -05:00
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
"main.resend_invite",
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
invited_user_id=expired_invite["id"],
|
|
|
|
|
|
_follow_redirects=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
assert normalize_spaces(page.h1.text) == "Team members"
|
|
|
|
|
|
assert mock_resend.called
|
2023-12-21 10:58:32 -05:00
|
|
|
|
called_args = set(mock_resend.call_args.args) | set(
|
|
|
|
|
|
mock_resend.call_args.kwargs.values()
|
|
|
|
|
|
)
|
|
|
|
|
|
assert SERVICE_ONE_ID in called_args
|
|
|
|
|
|
assert expired_invite["id"] in called_args
|
2023-12-07 07:52:40 -05:00
|
|
|
|
|
|
|
|
|
|
|
2017-02-03 10:42:01 +00:00
|
|
|
|
def test_cancel_invited_user_cancels_user_invitations(
|
2019-02-25 16:51:37 +00:00
|
|
|
|
client_request,
|
|
|
|
|
|
mock_get_invites_for_service,
|
Make user API client return JSON, not a model
The data flow of other bits of our application looks like this:
```
API (returns JSON)
⬇
API client (returns a built in type, usually `dict`)
⬇
Model (returns an instance, eg of type `Service`)
⬇
View (returns HTML)
```
The user API client was architected weirdly, in that it returned a model
directly, like this:
```
API (returns JSON)
⬇
API client (returns a model, of type `User`, `InvitedUser`, etc)
⬇
View (returns HTML)
```
This mixing of different layers of the application is bad because it
makes it hard to write model code that doesn’t have circular
dependencies. As our application gets more complicated we will be
relying more on models to manage this complexity, so we should make it
easy, not hard to write them.
It also means that most of our mocking was of the User model, not just
the underlying JSON. So it would have been easy to introduce subtle bugs
to the user model, because it wasn’t being comprehensively tested. A lot
of the changed lines of code in this commit mean changing the tests to
mock only the JSON, which means that the model layer gets implicitly
tested.
For those reasons this commit changes the user API client to return
JSON, not an instance of `User` or other models.
2019-05-23 15:27:35 +01:00
|
|
|
|
sample_invite,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
active_user_with_permissions,
|
2020-08-17 14:30:09 +01:00
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_get_template_folders,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
mocker,
|
|
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mock_cancel = mocker.patch("app.invite_api_client.cancel_invited_user")
|
|
|
|
|
|
mocker.patch(
|
2023-12-21 10:58:32 -05:00
|
|
|
|
"app.invite_api_client.get_invited_user_for_service",
|
|
|
|
|
|
return_value=sample_invite,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
)
|
2020-08-17 14:30:09 +01:00
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.cancel_invited_user",
|
2019-02-25 16:51:37 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
invited_user_id=sample_invite["id"],
|
2020-08-17 14:30:09 +01:00
|
|
|
|
_follow_redirects=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert normalize_spaces(page.h1.text) == "Team members"
|
2020-08-17 14:30:09 +01:00
|
|
|
|
flash_banner = normalize_spaces(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
page.find("div", class_="banner-default-with-tick").text
|
2019-02-25 16:51:37 +00:00
|
|
|
|
)
|
2020-08-17 14:30:09 +01:00
|
|
|
|
assert flash_banner == f"Invitation cancelled for {sample_invite['email_address']}"
|
2019-02-25 16:51:37 +00:00
|
|
|
|
mock_cancel.assert_called_once_with(
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
invited_user_id=sample_invite["id"],
|
2019-02-25 16:51:37 +00:00
|
|
|
|
)
|
2016-03-01 16:12:26 +00:00
|
|
|
|
|
2019-02-25 16:51:37 +00:00
|
|
|
|
|
|
|
|
|
|
def test_cancel_invited_user_doesnt_work_if_user_not_invited_to_this_service(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mock_get_invites_for_service,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mock_cancel = mocker.patch("app.invite_api_client.cancel_invited_user")
|
2019-02-25 16:51:37 +00:00
|
|
|
|
client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.cancel_invited_user",
|
2019-02-25 16:51:37 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
Make user API client return JSON, not a model
The data flow of other bits of our application looks like this:
```
API (returns JSON)
⬇
API client (returns a built in type, usually `dict`)
⬇
Model (returns an instance, eg of type `Service`)
⬇
View (returns HTML)
```
The user API client was architected weirdly, in that it returned a model
directly, like this:
```
API (returns JSON)
⬇
API client (returns a model, of type `User`, `InvitedUser`, etc)
⬇
View (returns HTML)
```
This mixing of different layers of the application is bad because it
makes it hard to write model code that doesn’t have circular
dependencies. As our application gets more complicated we will be
relying more on models to manage this complexity, so we should make it
easy, not hard to write them.
It also means that most of our mocking was of the User model, not just
the underlying JSON. So it would have been easy to introduce subtle bugs
to the user model, because it wasn’t being comprehensively tested. A lot
of the changed lines of code in this commit mean changing the tests to
mock only the JSON, which means that the model layer gets implicitly
tested.
For those reasons this commit changes the user API client to return
JSON, not an instance of `User` or other models.
2019-05-23 15:27:35 +01:00
|
|
|
|
invited_user_id=sample_uuid(),
|
2019-02-25 16:51:37 +00:00
|
|
|
|
_expected_status=404,
|
|
|
|
|
|
)
|
|
|
|
|
|
assert mock_cancel.called is False
|
2016-03-07 10:19:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
@pytest.mark.parametrize(
|
2023-09-11 16:51:30 -04:00
|
|
|
|
("invite_status", "expected_text"),
|
2023-08-25 09:12:23 -07:00
|
|
|
|
[
|
|
|
|
|
|
(
|
|
|
|
|
|
"pending",
|
|
|
|
|
|
(
|
2023-12-18 15:38:36 -05:00
|
|
|
|
"invited_user@test.gsa.gov(invited) "
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"Permissions "
|
|
|
|
|
|
"Can See dashboard "
|
|
|
|
|
|
"Can Send messages "
|
|
|
|
|
|
"Can Manage settings, team and usage "
|
|
|
|
|
|
"Can Manage API integration "
|
|
|
|
|
|
"Cancel invitation for invited_user@test.gsa.gov"
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
2024-04-22 16:09:25 -06:00
|
|
|
|
# Test case removed due to the removal of canceled users from the dashboard
|
|
|
|
|
|
# (
|
|
|
|
|
|
# "cancelled",
|
|
|
|
|
|
# (
|
|
|
|
|
|
# "invited_user@test.gsa.gov(cancelled invite) "
|
|
|
|
|
|
# "Permissions"
|
|
|
|
|
|
# # all permissions are greyed out
|
|
|
|
|
|
# ),
|
|
|
|
|
|
# ),
|
2023-08-25 09:12:23 -07:00
|
|
|
|
],
|
|
|
|
|
|
)
|
2017-02-03 10:42:01 +00:00
|
|
|
|
def test_manage_users_shows_invited_user(
|
2017-08-17 10:44:36 +01:00
|
|
|
|
client_request,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
mocker,
|
|
|
|
|
|
active_user_with_permissions,
|
2019-05-17 13:06:26 +01:00
|
|
|
|
mock_get_template_folders,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
sample_invite,
|
2018-01-26 17:14:00 +00:00
|
|
|
|
invite_status,
|
|
|
|
|
|
expected_text,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
sample_invite["status"] = invite_status
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.InvitedUsers.client_method", return_value=[sample_invite]
|
|
|
|
|
|
)
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.Users.client_method",
|
|
|
|
|
|
return_value=[active_user_with_permissions],
|
|
|
|
|
|
)
|
2016-03-07 10:19:44 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
page = client_request.get("main.manage_users", service_id=SERVICE_ONE_ID)
|
|
|
|
|
|
assert page.h1.string.strip() == "Team members"
|
|
|
|
|
|
assert normalize_spaces(page.select(".user-list-item")[0].text) == expected_text
|
2016-03-07 13:59:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
2017-02-03 10:42:01 +00:00
|
|
|
|
def test_manage_users_does_not_show_accepted_invite(
|
2018-11-30 17:39:39 +00:00
|
|
|
|
client_request,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
mocker,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
sample_invite,
|
2019-05-17 13:06:26 +01:00
|
|
|
|
mock_get_template_folders,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
):
|
2016-03-07 13:59:54 +00:00
|
|
|
|
invited_user_id = uuid.uuid4()
|
2023-08-25 09:12:23 -07:00
|
|
|
|
sample_invite["id"] = invited_user_id
|
|
|
|
|
|
sample_invite["status"] = "accepted"
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.InvitedUsers.client_method", return_value=[sample_invite]
|
|
|
|
|
|
)
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.Users.client_method",
|
|
|
|
|
|
return_value=[active_user_with_permissions],
|
|
|
|
|
|
)
|
2016-03-07 13:59:54 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
page = client_request.get("main.manage_users", service_id=SERVICE_ONE_ID)
|
2016-03-07 13:59:54 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert page.h1.string.strip() == "Team members"
|
|
|
|
|
|
user_lists = page.find_all("div", {"class": "user-list"})
|
2017-02-03 12:07:21 +00:00
|
|
|
|
assert len(user_lists) == 1
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert not page.find(text="invited_user@test.gsa.gov")
|
2016-03-09 13:00:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_user_cant_invite_themselves(
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
mocker,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
mock_create_invite,
|
2019-03-15 14:57:39 +00:00
|
|
|
|
mock_get_template_folders,
|
2016-03-09 13:00:52 +00:00
|
|
|
|
):
|
2019-03-26 12:35:32 +00:00
|
|
|
|
page = client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.invite_user",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_data={
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"email_address": active_user_with_permissions["email_address"],
|
|
|
|
|
|
"permissions_field": ["send_messages", "manage_service", "manage_api_keys"],
|
2019-03-26 12:35:32 +00:00
|
|
|
|
},
|
|
|
|
|
|
_follow_redirects=True,
|
2023-12-11 10:47:21 -05:00
|
|
|
|
_expected_status=200,
|
2017-02-03 12:07:21 +00:00
|
|
|
|
)
|
2023-12-11 10:47:21 -05:00
|
|
|
|
assert page.h1.string.strip() == "Invite a team member"
|
|
|
|
|
|
form_error = page.find("span", class_="usa-error-message").text.strip()
|
|
|
|
|
|
assert form_error == "Error: You cannot send an invitation to yourself"
|
2017-02-03 12:07:21 +00:00
|
|
|
|
assert not mock_create_invite.called
|
2016-03-21 15:25:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
2023-11-08 07:51:57 -08:00
|
|
|
|
def test_user_cant_invite_themselves_platform_admin(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
mock_create_invite,
|
|
|
|
|
|
mock_get_template_folders,
|
|
|
|
|
|
):
|
|
|
|
|
|
platform_admin = create_platform_admin_user()
|
|
|
|
|
|
client_request.login(platform_admin)
|
|
|
|
|
|
page = client_request.post(
|
|
|
|
|
|
"main.invite_user",
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_follow_redirects=True,
|
|
|
|
|
|
_expected_status=200,
|
|
|
|
|
|
)
|
|
|
|
|
|
assert "Invite a team member" in page.h1.string.strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-02-03 10:42:01 +00:00
|
|
|
|
def test_no_permission_manage_users_page(
|
2018-05-03 17:00:05 +01:00
|
|
|
|
client_request,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
service_one,
|
2018-05-03 17:00:05 +01:00
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_get_invites_for_service,
|
2019-05-17 13:06:26 +01:00
|
|
|
|
mock_get_template_folders,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
api_user_active,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
resp_text = client_request.get("main.manage_users", service_id=service_one["id"])
|
|
|
|
|
|
assert url_for(".invite_user", service_id=service_one["id"]) not in resp_text
|
2017-02-03 12:07:21 +00:00
|
|
|
|
assert "Edit permission" not in resp_text
|
|
|
|
|
|
assert "Team members" not in resp_text
|
2016-03-23 10:46:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
@pytest.mark.parametrize(
|
2023-09-11 16:51:30 -04:00
|
|
|
|
("folders_user_can_see", "expected_message"),
|
2023-08-25 09:12:23 -07:00
|
|
|
|
[
|
|
|
|
|
|
(3, "Can see all folders"),
|
|
|
|
|
|
(2, "Can see 2 folders"),
|
|
|
|
|
|
(1, "Can see 1 folder"),
|
|
|
|
|
|
(0, "Cannot see any folders"),
|
|
|
|
|
|
],
|
|
|
|
|
|
)
|
2019-04-04 17:55:37 +01:00
|
|
|
|
def test_manage_user_page_shows_how_many_folders_user_can_view(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_template_folders,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_get_invites_for_service,
|
|
|
|
|
|
api_user_active,
|
|
|
|
|
|
folders_user_can_see,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
expected_message,
|
2019-04-04 17:55:37 +01:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["permissions"] = ["edit_folder_permissions"]
|
2019-04-04 17:55:37 +01:00
|
|
|
|
mock_get_template_folders.return_value = [
|
2023-08-25 09:12:23 -07:00
|
|
|
|
{
|
|
|
|
|
|
"id": "folder-id-1",
|
|
|
|
|
|
"name": "f1",
|
|
|
|
|
|
"parent_id": None,
|
|
|
|
|
|
"users_with_permission": [],
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "folder-id-2",
|
|
|
|
|
|
"name": "f2",
|
|
|
|
|
|
"parent_id": None,
|
|
|
|
|
|
"users_with_permission": [],
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": "folder-id-3",
|
|
|
|
|
|
"name": "f3",
|
|
|
|
|
|
"parent_id": None,
|
|
|
|
|
|
"users_with_permission": [],
|
|
|
|
|
|
},
|
2019-04-04 17:55:37 +01:00
|
|
|
|
]
|
|
|
|
|
|
for i in range(folders_user_can_see):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mock_get_template_folders.return_value[i]["users_with_permission"].append(
|
|
|
|
|
|
api_user_active["id"]
|
|
|
|
|
|
)
|
2019-04-04 17:55:37 +01:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
page = client_request.get("main.manage_users", service_id=service_one["id"])
|
2019-04-04 17:55:37 +01:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_div = page.select_one(
|
|
|
|
|
|
"h2[title='notify@digital.cabinet-office.gov.uk']"
|
|
|
|
|
|
).parent
|
2023-12-18 15:38:36 -05:00
|
|
|
|
assert user_div.select_one(".tick-cross-list-hint").text.strip() == expected_message
|
2019-04-04 17:55:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_manage_user_page_doesnt_show_folder_hint_if_service_has_no_folders(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_template_folders,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_get_invites_for_service,
|
|
|
|
|
|
api_user_active,
|
|
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["permissions"] = ["edit_folder_permissions"]
|
2019-04-04 17:55:37 +01:00
|
|
|
|
mock_get_template_folders.return_value = []
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
page = client_request.get("main.manage_users", service_id=service_one["id"])
|
2019-04-04 17:55:37 +01:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_div = page.select_one(
|
|
|
|
|
|
"h2[title='notify@digital.cabinet-office.gov.uk']"
|
|
|
|
|
|
).parent
|
|
|
|
|
|
assert user_div.find(".tick-cross-list-hint:last-child") is None
|
2019-04-04 17:55:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_manage_user_page_doesnt_show_folder_hint_if_service_cant_edit_folder_permissions(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_template_folders,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_get_invites_for_service,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
api_user_active,
|
2019-04-04 17:55:37 +01:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["permissions"] = []
|
2019-04-04 17:55:37 +01:00
|
|
|
|
mock_get_template_folders.return_value = [
|
2023-08-25 09:12:23 -07:00
|
|
|
|
{
|
|
|
|
|
|
"id": "folder-id-1",
|
|
|
|
|
|
"name": "f1",
|
|
|
|
|
|
"parent_id": None,
|
|
|
|
|
|
"users_with_permission": [api_user_active["id"]],
|
|
|
|
|
|
},
|
2019-04-04 17:55:37 +01:00
|
|
|
|
]
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
page = client_request.get("main.manage_users", service_id=service_one["id"])
|
2019-04-04 17:55:37 +01:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_div = page.select_one(
|
|
|
|
|
|
"h2[title='notify@digital.cabinet-office.gov.uk']"
|
|
|
|
|
|
).parent
|
|
|
|
|
|
assert user_div.find(".tick-cross-list-hint:last-child") is None
|
2019-04-04 17:55:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
2019-03-26 15:51:44 +00:00
|
|
|
|
def test_remove_user_from_service(
|
2019-03-14 17:31:51 +00:00
|
|
|
|
client_request,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
active_user_with_permissions,
|
2020-03-10 13:18:32 +00:00
|
|
|
|
api_user_active,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
service_one,
|
|
|
|
|
|
mock_remove_user_from_service,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mock_event_handler = mocker.patch(
|
|
|
|
|
|
"app.main.views.manage_users.create_remove_user_from_service_event"
|
|
|
|
|
|
)
|
2020-03-10 13:18:32 +00:00
|
|
|
|
|
2019-03-14 17:31:51 +00:00
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.remove_user_from_service",
|
|
|
|
|
|
service_id=service_one["id"],
|
|
|
|
|
|
user_id=active_user_with_permissions["id"],
|
|
|
|
|
|
_expected_redirect=url_for("main.manage_users", service_id=service_one["id"]),
|
2019-03-14 17:31:51 +00:00
|
|
|
|
)
|
|
|
|
|
|
mock_remove_user_from_service.assert_called_once_with(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one["id"], str(active_user_with_permissions["id"])
|
2019-03-14 17:31:51 +00:00
|
|
|
|
)
|
2016-06-03 11:10:38 +01:00
|
|
|
|
|
2020-03-10 13:18:32 +00:00
|
|
|
|
mock_event_handler.assert_called_once_with(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
|
|
|
|
|
removed_by_id=api_user_active["id"],
|
|
|
|
|
|
service_id=service_one["id"],
|
2020-03-10 13:18:32 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
2016-06-03 11:10:38 +01:00
|
|
|
|
|
|
|
|
|
|
def test_can_invite_user_as_platform_admin(
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
service_one,
|
|
|
|
|
|
platform_admin_user,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
mock_get_invites_for_service,
|
2019-05-17 13:06:26 +01:00
|
|
|
|
mock_get_template_folders,
|
2017-02-03 10:42:01 +00:00
|
|
|
|
mocker,
|
|
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.Users.client_method",
|
|
|
|
|
|
return_value=[active_user_with_permissions],
|
|
|
|
|
|
)
|
2017-02-03 12:07:21 +00:00
|
|
|
|
|
2019-03-26 12:35:32 +00:00
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.manage_users",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert url_for(".invite_user", service_id=service_one["id"]) in str(page)
|
2019-02-19 15:35:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_edit_user_email_page(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
service_one,
|
2019-02-25 16:51:37 +00:00
|
|
|
|
mock_get_users_by_service,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker,
|
2019-02-19 15:35:51 +00:00
|
|
|
|
):
|
|
|
|
|
|
user = active_user_with_permissions
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker.patch("app.user_api_client.get_user", return_value=user)
|
2019-02-19 15:35:51 +00:00
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_email", service_id=service_one["id"], user_id=sample_uuid()
|
2019-02-19 15:35:51 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert page.find("h1").text == "Change team member’s email address"
|
|
|
|
|
|
assert page.select("p[id=user_name]")[
|
|
|
|
|
|
0
|
|
|
|
|
|
].text == "This will change the email address for {}.".format(user["name"])
|
|
|
|
|
|
assert page.select("input[type=email]")[0].attrs["value"] == user["email_address"]
|
|
|
|
|
|
assert normalize_spaces(page.select("main button[type=submit]")[0].text) == "Save"
|
2019-02-19 18:01:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
2019-02-25 16:51:37 +00:00
|
|
|
|
def test_edit_user_email_page_404_for_non_team_member(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
):
|
|
|
|
|
|
client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_email",
|
2019-02-25 16:51:37 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
user_id=USER_ONE_ID,
|
|
|
|
|
|
_expected_status=404,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-02-19 18:01:01 +00:00
|
|
|
|
def test_edit_user_email_redirects_to_confirmation(
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request,
|
2019-02-19 18:01:01 +00:00
|
|
|
|
active_user_with_permissions,
|
2019-02-25 16:51:37 +00:00
|
|
|
|
mock_get_users_by_service,
|
Make user API client return JSON, not a model
The data flow of other bits of our application looks like this:
```
API (returns JSON)
⬇
API client (returns a built in type, usually `dict`)
⬇
Model (returns an instance, eg of type `Service`)
⬇
View (returns HTML)
```
The user API client was architected weirdly, in that it returned a model
directly, like this:
```
API (returns JSON)
⬇
API client (returns a model, of type `User`, `InvitedUser`, etc)
⬇
View (returns HTML)
```
This mixing of different layers of the application is bad because it
makes it hard to write model code that doesn’t have circular
dependencies. As our application gets more complicated we will be
relying more on models to manage this complexity, so we should make it
easy, not hard to write them.
It also means that most of our mocking was of the User model, not just
the underlying JSON. So it would have been easy to introduce subtle bugs
to the user model, because it wasn’t being comprehensively tested. A lot
of the changed lines of code in this commit mean changing the tests to
mock only the JSON, which means that the model layer gets implicitly
tested.
For those reasons this commit changes the user API client to return
JSON, not an instance of `User` or other models.
2019-05-23 15:27:35 +01:00
|
|
|
|
mock_get_user_by_email_not_found,
|
2019-02-19 18:01:01 +00:00
|
|
|
|
):
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_email",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
2019-03-26 12:35:32 +00:00
|
|
|
|
_expected_status=302,
|
|
|
|
|
|
_expected_redirect=url_for(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.confirm_edit_user_email",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
2019-03-26 12:35:32 +00:00
|
|
|
|
),
|
2019-02-19 18:01:01 +00:00
|
|
|
|
)
|
2020-01-13 12:03:39 +00:00
|
|
|
|
with client_request.session_transaction() as session:
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert (
|
|
|
|
|
|
session[
|
|
|
|
|
|
"team_member_email_change-{}".format(active_user_with_permissions["id"])
|
|
|
|
|
|
]
|
|
|
|
|
|
== "test@user.gsa.gov"
|
|
|
|
|
|
)
|
2019-02-20 11:50:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
2019-02-25 12:04:07 +00:00
|
|
|
|
def test_edit_user_email_without_changing_goes_back_to_team_members(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
active_user_with_permissions,
|
Make user API client return JSON, not a model
The data flow of other bits of our application looks like this:
```
API (returns JSON)
⬇
API client (returns a built in type, usually `dict`)
⬇
Model (returns an instance, eg of type `Service`)
⬇
View (returns HTML)
```
The user API client was architected weirdly, in that it returned a model
directly, like this:
```
API (returns JSON)
⬇
API client (returns a model, of type `User`, `InvitedUser`, etc)
⬇
View (returns HTML)
```
This mixing of different layers of the application is bad because it
makes it hard to write model code that doesn’t have circular
dependencies. As our application gets more complicated we will be
relying more on models to manage this complexity, so we should make it
easy, not hard to write them.
It also means that most of our mocking was of the User model, not just
the underlying JSON. So it would have been easy to introduce subtle bugs
to the user model, because it wasn’t being comprehensively tested. A lot
of the changed lines of code in this commit mean changing the tests to
mock only the JSON, which means that the model layer gets implicitly
tested.
For those reasons this commit changes the user API client to return
JSON, not an instance of `User` or other models.
2019-05-23 15:27:35 +01:00
|
|
|
|
mock_get_user_by_email,
|
2019-02-25 16:51:37 +00:00
|
|
|
|
mock_get_users_by_service,
|
2019-02-25 12:04:07 +00:00
|
|
|
|
mock_update_user_attribute,
|
|
|
|
|
|
):
|
|
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_email",
|
2019-02-25 12:04:07 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
|
|
|
|
|
_data={"email_address": active_user_with_permissions["email_address"]},
|
2019-02-25 12:04:07 +00:00
|
|
|
|
_expected_status=302,
|
|
|
|
|
|
_expected_redirect=url_for(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.manage_users",
|
2019-02-25 12:04:07 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
assert mock_update_user_attribute.called is False
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
@pytest.mark.parametrize("original_email_address", ["test@gsa.gov", "test@example.com"])
|
2019-04-18 16:03:13 +01:00
|
|
|
|
def test_edit_user_email_can_change_any_email_address_to_a_gov_email_address(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
active_user_with_permissions,
|
Make user API client return JSON, not a model
The data flow of other bits of our application looks like this:
```
API (returns JSON)
⬇
API client (returns a built in type, usually `dict`)
⬇
Model (returns an instance, eg of type `Service`)
⬇
View (returns HTML)
```
The user API client was architected weirdly, in that it returned a model
directly, like this:
```
API (returns JSON)
⬇
API client (returns a model, of type `User`, `InvitedUser`, etc)
⬇
View (returns HTML)
```
This mixing of different layers of the application is bad because it
makes it hard to write model code that doesn’t have circular
dependencies. As our application gets more complicated we will be
relying more on models to manage this complexity, so we should make it
easy, not hard to write them.
It also means that most of our mocking was of the User model, not just
the underlying JSON. So it would have been easy to introduce subtle bugs
to the user model, because it wasn’t being comprehensively tested. A lot
of the changed lines of code in this commit mean changing the tests to
mock only the JSON, which means that the model layer gets implicitly
tested.
For those reasons this commit changes the user API client to return
JSON, not an instance of `User` or other models.
2019-05-23 15:27:35 +01:00
|
|
|
|
mock_get_user_by_email_not_found,
|
2019-04-18 16:03:13 +01:00
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_update_user_attribute,
|
2023-07-12 12:09:44 -04:00
|
|
|
|
mock_get_organizations,
|
2019-05-28 16:11:54 +01:00
|
|
|
|
original_email_address,
|
2019-04-18 16:03:13 +01:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
active_user_with_permissions["email_address"] = original_email_address
|
2019-04-18 16:03:13 +01:00
|
|
|
|
|
|
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_email",
|
2019-04-18 16:03:13 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
|
|
|
|
|
_data={"email_address": "new-email-address@gsa.gov"},
|
2019-04-18 16:03:13 +01:00
|
|
|
|
_expected_status=302,
|
|
|
|
|
|
_expected_redirect=url_for(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.confirm_edit_user_email",
|
2019-04-18 16:03:13 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
2019-04-18 16:03:13 +01:00
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_edit_user_email_can_change_a_non_gov_email_address_to_another_non_gov_email_address(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
active_user_with_permissions,
|
Make user API client return JSON, not a model
The data flow of other bits of our application looks like this:
```
API (returns JSON)
⬇
API client (returns a built in type, usually `dict`)
⬇
Model (returns an instance, eg of type `Service`)
⬇
View (returns HTML)
```
The user API client was architected weirdly, in that it returned a model
directly, like this:
```
API (returns JSON)
⬇
API client (returns a model, of type `User`, `InvitedUser`, etc)
⬇
View (returns HTML)
```
This mixing of different layers of the application is bad because it
makes it hard to write model code that doesn’t have circular
dependencies. As our application gets more complicated we will be
relying more on models to manage this complexity, so we should make it
easy, not hard to write them.
It also means that most of our mocking was of the User model, not just
the underlying JSON. So it would have been easy to introduce subtle bugs
to the user model, because it wasn’t being comprehensively tested. A lot
of the changed lines of code in this commit mean changing the tests to
mock only the JSON, which means that the model layer gets implicitly
tested.
For those reasons this commit changes the user API client to return
JSON, not an instance of `User` or other models.
2019-05-23 15:27:35 +01:00
|
|
|
|
mock_get_user_by_email_not_found,
|
2019-04-18 16:03:13 +01:00
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_update_user_attribute,
|
2023-07-12 12:09:44 -04:00
|
|
|
|
mock_get_organizations,
|
2019-04-18 16:03:13 +01:00
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
active_user_with_permissions["email_address"] = "old@example.com"
|
2019-04-18 16:03:13 +01:00
|
|
|
|
|
|
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_email",
|
2019-04-18 16:03:13 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
|
|
|
|
|
_data={"email_address": "new@example.com"},
|
2019-04-18 16:03:13 +01:00
|
|
|
|
_expected_status=302,
|
|
|
|
|
|
_expected_redirect=url_for(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.confirm_edit_user_email",
|
2019-04-18 16:03:13 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
2019-04-18 16:03:13 +01:00
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_edit_user_email_cannot_change_a_gov_email_address_to_a_non_gov_email_address(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
active_user_with_permissions,
|
Make user API client return JSON, not a model
The data flow of other bits of our application looks like this:
```
API (returns JSON)
⬇
API client (returns a built in type, usually `dict`)
⬇
Model (returns an instance, eg of type `Service`)
⬇
View (returns HTML)
```
The user API client was architected weirdly, in that it returned a model
directly, like this:
```
API (returns JSON)
⬇
API client (returns a model, of type `User`, `InvitedUser`, etc)
⬇
View (returns HTML)
```
This mixing of different layers of the application is bad because it
makes it hard to write model code that doesn’t have circular
dependencies. As our application gets more complicated we will be
relying more on models to manage this complexity, so we should make it
easy, not hard to write them.
It also means that most of our mocking was of the User model, not just
the underlying JSON. So it would have been easy to introduce subtle bugs
to the user model, because it wasn’t being comprehensively tested. A lot
of the changed lines of code in this commit mean changing the tests to
mock only the JSON, which means that the model layer gets implicitly
tested.
For those reasons this commit changes the user API client to return
JSON, not an instance of `User` or other models.
2019-05-23 15:27:35 +01:00
|
|
|
|
mock_get_user_by_email_not_found,
|
2019-04-18 16:03:13 +01:00
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_update_user_attribute,
|
2023-07-12 12:09:44 -04:00
|
|
|
|
mock_get_organizations,
|
2019-04-18 16:03:13 +01:00
|
|
|
|
):
|
|
|
|
|
|
page = client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_email",
|
2019-04-18 16:03:13 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
|
|
|
|
|
_data={"email_address": "new_email@example.com"},
|
2019-04-18 16:03:13 +01:00
|
|
|
|
_expected_status=200,
|
|
|
|
|
|
)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert (
|
|
|
|
|
|
"Enter a public sector email address"
|
|
|
|
|
|
in page.select_one(".usa-error-message").text
|
|
|
|
|
|
)
|
2020-01-13 12:03:39 +00:00
|
|
|
|
with client_request.session_transaction() as session:
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert (
|
|
|
|
|
|
"team_member_email_change-{}".format(active_user_with_permissions["id"])
|
|
|
|
|
|
not in session
|
|
|
|
|
|
)
|
2019-04-18 16:03:13 +01:00
|
|
|
|
|
|
|
|
|
|
|
2019-02-20 11:50:34 +00:00
|
|
|
|
def test_confirm_edit_user_email_page(
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request,
|
2019-02-20 11:50:34 +00:00
|
|
|
|
active_user_with_permissions,
|
2019-02-25 16:51:37 +00:00
|
|
|
|
mock_get_users_by_service,
|
2019-02-20 11:50:34 +00:00
|
|
|
|
mock_get_user,
|
|
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
new_email = "new_email@gsa.gov"
|
2019-03-26 12:35:32 +00:00
|
|
|
|
with client_request.session_transaction() as session:
|
2020-01-13 12:03:39 +00:00
|
|
|
|
session[
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"team_member_email_change-{}".format(active_user_with_permissions["id"])
|
2020-01-13 12:03:39 +00:00
|
|
|
|
] = new_email
|
2019-03-26 12:35:32 +00:00
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.confirm_edit_user_email",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
2019-03-26 12:35:32 +00:00
|
|
|
|
)
|
2019-02-20 11:50:34 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert "Confirm change of email address" in page.text
|
2019-02-20 17:34:58 +00:00
|
|
|
|
for text in [
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"New email address:",
|
2019-02-20 17:34:58 +00:00
|
|
|
|
new_email,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"We will send {} an email to tell them about the change.".format(
|
|
|
|
|
|
active_user_with_permissions["name"]
|
|
|
|
|
|
),
|
2019-02-20 17:34:58 +00:00
|
|
|
|
]:
|
2019-03-26 12:35:32 +00:00
|
|
|
|
assert text in page.text
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert "Confirm" in page.text
|
2019-02-20 11:50:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
2019-02-22 16:13:46 +00:00
|
|
|
|
def test_confirm_edit_user_email_page_redirects_if_session_empty(
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request,
|
2019-02-25 16:51:37 +00:00
|
|
|
|
mock_get_users_by_service,
|
2019-03-26 12:35:32 +00:00
|
|
|
|
active_user_with_permissions,
|
2019-02-22 16:13:46 +00:00
|
|
|
|
):
|
2019-03-26 12:35:32 +00:00
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.confirm_edit_user_email",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
2019-03-26 12:35:32 +00:00
|
|
|
|
_follow_redirects=True,
|
|
|
|
|
|
)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert "Confirm change of email address" not in page.text
|
2019-02-22 16:13:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
2019-02-25 16:51:37 +00:00
|
|
|
|
def test_confirm_edit_user_email_page_404s_for_non_team_member(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
):
|
|
|
|
|
|
client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.confirm_edit_user_email",
|
2019-02-25 16:51:37 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
user_id=USER_ONE_ID,
|
|
|
|
|
|
_expected_status=404,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-02-20 11:50:34 +00:00
|
|
|
|
def test_confirm_edit_user_email_changes_user_email(
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request,
|
2019-02-20 11:50:34 +00:00
|
|
|
|
active_user_with_permissions,
|
2019-04-03 11:47:46 +01:00
|
|
|
|
api_user_active,
|
2019-02-20 11:50:34 +00:00
|
|
|
|
service_one,
|
|
|
|
|
|
mocker,
|
2019-04-03 11:47:46 +01:00
|
|
|
|
mock_update_user_attribute,
|
2019-02-20 11:50:34 +00:00
|
|
|
|
):
|
2019-04-03 11:47:46 +01:00
|
|
|
|
# We want active_user_with_permissions (the current user) to update the email address for api_user_active
|
|
|
|
|
|
# By default both users would have the same id, so we change the id of api_user_active
|
2023-08-25 09:12:23 -07:00
|
|
|
|
api_user_active["id"] = str(uuid.uuid4())
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.Users.client_method",
|
|
|
|
|
|
return_value=[api_user_active, active_user_with_permissions],
|
|
|
|
|
|
)
|
2019-04-03 11:47:46 +01:00
|
|
|
|
# get_user gets called twice - first to check if current user can see the page, then to see if the team member
|
|
|
|
|
|
# whose email address we're changing belongs to the service
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.user_api_client.get_user",
|
|
|
|
|
|
side_effect=[active_user_with_permissions, api_user_active],
|
|
|
|
|
|
)
|
|
|
|
|
|
mock_event_handler = mocker.patch(
|
|
|
|
|
|
"app.main.views.manage_users.create_email_change_event"
|
|
|
|
|
|
)
|
2019-04-03 11:47:46 +01:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
new_email = "new_email@gsa.gov"
|
2019-03-26 12:35:32 +00:00
|
|
|
|
with client_request.session_transaction() as session:
|
2023-08-25 09:12:23 -07:00
|
|
|
|
session["team_member_email_change-{}".format(api_user_active["id"])] = new_email
|
2019-04-03 11:47:46 +01:00
|
|
|
|
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.confirm_edit_user_email",
|
|
|
|
|
|
service_id=service_one["id"],
|
|
|
|
|
|
user_id=api_user_active["id"],
|
2019-03-26 12:35:32 +00:00
|
|
|
|
_expected_status=302,
|
|
|
|
|
|
_expected_redirect=url_for(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.manage_users",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
2019-04-03 11:47:46 +01:00
|
|
|
|
|
2019-02-26 16:28:05 +00:00
|
|
|
|
mock_update_user_attribute.assert_called_once_with(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
api_user_active["id"],
|
2019-02-26 16:28:05 +00:00
|
|
|
|
email_address=new_email,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
updated_by=active_user_with_permissions["id"],
|
2019-02-26 16:28:05 +00:00
|
|
|
|
)
|
2019-04-03 11:47:46 +01:00
|
|
|
|
mock_event_handler.assert_called_once_with(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=api_user_active["id"],
|
|
|
|
|
|
updated_by_id=active_user_with_permissions["id"],
|
|
|
|
|
|
original_email_address=api_user_active["email_address"],
|
|
|
|
|
|
new_email_address=new_email,
|
|
|
|
|
|
)
|
2019-02-25 16:51:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_confirm_edit_user_email_doesnt_change_user_email_for_non_team_member(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
):
|
|
|
|
|
|
with client_request.session_transaction() as session:
|
2023-08-25 09:12:23 -07:00
|
|
|
|
session["team_member_email_change"] = "new_email@gsa.gov"
|
2019-02-25 16:51:37 +00:00
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.confirm_edit_user_email",
|
2019-02-25 16:51:37 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
user_id=USER_ONE_ID,
|
|
|
|
|
|
_expected_status=404,
|
|
|
|
|
|
)
|
2019-02-21 13:03:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
2019-02-22 11:31:35 +00:00
|
|
|
|
def test_edit_user_permissions_page_displays_redacted_mobile_number_and_change_link(
|
2019-02-21 13:03:06 +00:00
|
|
|
|
client_request,
|
|
|
|
|
|
active_user_with_permissions,
|
2019-02-25 14:27:37 +00:00
|
|
|
|
mock_get_users_by_service,
|
2019-02-27 15:45:18 +00:00
|
|
|
|
mock_get_template_folders,
|
2019-02-21 13:03:06 +00:00
|
|
|
|
service_one,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker,
|
2019-02-21 13:03:06 +00:00
|
|
|
|
):
|
|
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_permissions",
|
|
|
|
|
|
service_id=service_one["id"],
|
|
|
|
|
|
user_id=active_user_with_permissions["id"],
|
2019-02-21 13:03:06 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert active_user_with_permissions["name"] in page.find("h1").text
|
|
|
|
|
|
mobile_number_paragraph = page.select("p[id=user_mobile_number]")[0]
|
|
|
|
|
|
assert "202-8 • • • • 303" in mobile_number_paragraph.text
|
2019-02-22 11:31:35 +00:00
|
|
|
|
change_link = mobile_number_paragraph.findChild()
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert change_link.attrs[
|
|
|
|
|
|
"href"
|
|
|
|
|
|
] == "/services/{}/users/{}/edit-mobile-number".format(
|
|
|
|
|
|
service_one["id"], active_user_with_permissions["id"]
|
2019-02-21 13:03:06 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-03-26 15:51:44 +00:00
|
|
|
|
def test_edit_user_permissions_with_delete_query_shows_banner(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
mock_get_template_folders,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
service_one,
|
2019-03-26 15:51:44 +00:00
|
|
|
|
):
|
|
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_permissions",
|
|
|
|
|
|
service_id=service_one["id"],
|
|
|
|
|
|
user_id=active_user_with_permissions["id"],
|
|
|
|
|
|
delete=1,
|
2019-03-26 15:51:44 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
banner = page.find("div", class_="banner-dangerous")
|
2019-03-26 15:51:44 +00:00
|
|
|
|
assert banner.contents[0].strip() == "Are you sure you want to remove Test User?"
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert banner.form.attrs["action"] == url_for(
|
|
|
|
|
|
"main.remove_user_from_service",
|
|
|
|
|
|
service_id=service_one["id"],
|
|
|
|
|
|
user_id=active_user_with_permissions["id"],
|
2019-03-26 15:51:44 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-02-22 11:31:35 +00:00
|
|
|
|
def test_edit_user_mobile_number_page(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
active_user_with_permissions,
|
2019-02-26 11:47:15 +00:00
|
|
|
|
mock_get_users_by_service,
|
2019-02-22 11:31:35 +00:00
|
|
|
|
service_one,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker,
|
2019-02-22 11:31:35 +00:00
|
|
|
|
):
|
|
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_mobile_number",
|
|
|
|
|
|
service_id=service_one["id"],
|
|
|
|
|
|
user_id=active_user_with_permissions["id"],
|
2019-02-22 11:31:35 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert page.find("h1").text == "Change team member’s mobile number"
|
|
|
|
|
|
assert page.select("p[id=user_name]")[0].text == (
|
Make user API client return JSON, not a model
The data flow of other bits of our application looks like this:
```
API (returns JSON)
⬇
API client (returns a built in type, usually `dict`)
⬇
Model (returns an instance, eg of type `Service`)
⬇
View (returns HTML)
```
The user API client was architected weirdly, in that it returned a model
directly, like this:
```
API (returns JSON)
⬇
API client (returns a model, of type `User`, `InvitedUser`, etc)
⬇
View (returns HTML)
```
This mixing of different layers of the application is bad because it
makes it hard to write model code that doesn’t have circular
dependencies. As our application gets more complicated we will be
relying more on models to manage this complexity, so we should make it
easy, not hard to write them.
It also means that most of our mocking was of the User model, not just
the underlying JSON. So it would have been easy to introduce subtle bugs
to the user model, because it wasn’t being comprehensively tested. A lot
of the changed lines of code in this commit mean changing the tests to
mock only the JSON, which means that the model layer gets implicitly
tested.
For those reasons this commit changes the user API client to return
JSON, not an instance of `User` or other models.
2019-05-23 15:27:35 +01:00
|
|
|
|
"This will change the mobile number for {}."
|
2023-08-25 09:12:23 -07:00
|
|
|
|
).format(active_user_with_permissions["name"])
|
|
|
|
|
|
assert page.select("input[name=mobile_number]")[0].attrs["value"] == "202-8••••303"
|
|
|
|
|
|
assert normalize_spaces(page.select("main button[type=submit]")[0].text) == "Save"
|
2019-02-21 13:03:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
2019-02-22 12:28:18 +00:00
|
|
|
|
def test_edit_user_mobile_number_redirects_to_confirmation(
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request,
|
2019-02-22 12:28:18 +00:00
|
|
|
|
active_user_with_permissions,
|
2019-02-26 11:47:15 +00:00
|
|
|
|
mock_get_users_by_service,
|
2019-02-22 12:28:18 +00:00
|
|
|
|
):
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_mobile_number",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
|
|
|
|
|
_data={"mobile_number": "2028675309"},
|
2019-03-26 12:35:32 +00:00
|
|
|
|
_expected_status=302,
|
|
|
|
|
|
_expected_redirect=url_for(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.confirm_edit_user_mobile_number",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
2019-03-26 12:35:32 +00:00
|
|
|
|
),
|
2019-02-22 12:28:18 +00:00
|
|
|
|
)
|
2019-02-21 13:03:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
2019-02-25 14:27:37 +00:00
|
|
|
|
def test_edit_user_mobile_number_redirects_to_manage_users_if_number_not_changed(
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request,
|
2019-02-25 14:27:37 +00:00
|
|
|
|
active_user_with_permissions,
|
2019-02-26 11:47:15 +00:00
|
|
|
|
mock_get_users_by_service,
|
2019-02-25 14:27:37 +00:00
|
|
|
|
service_one,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
mock_get_user,
|
|
|
|
|
|
):
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.edit_user_mobile_number",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
|
|
|
|
|
_data={"mobile_number": "202-8••••303"},
|
2019-03-26 12:35:32 +00:00
|
|
|
|
_expected_status=302,
|
|
|
|
|
|
_expected_redirect=url_for(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.manage_users",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
2019-02-25 14:27:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
2019-02-22 15:06:42 +00:00
|
|
|
|
def test_confirm_edit_user_mobile_number_page(
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request,
|
2019-02-22 15:06:42 +00:00
|
|
|
|
active_user_with_permissions,
|
2019-02-26 11:47:15 +00:00
|
|
|
|
mock_get_users_by_service,
|
2019-02-22 15:06:42 +00:00
|
|
|
|
service_one,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
mock_get_user,
|
|
|
|
|
|
):
|
2023-08-25 09:12:23 -07:00
|
|
|
|
new_number = "2028675309"
|
2019-03-26 12:35:32 +00:00
|
|
|
|
with client_request.session_transaction() as session:
|
2023-08-25 09:12:23 -07:00
|
|
|
|
session["team_member_mobile_change"] = new_number
|
2019-03-26 12:35:32 +00:00
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.confirm_edit_user_mobile_number",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
2019-03-26 12:35:32 +00:00
|
|
|
|
)
|
2019-02-22 15:06:42 +00:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert "Confirm change of mobile number" in page.text
|
2019-02-22 15:06:42 +00:00
|
|
|
|
for text in [
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"New mobile number:",
|
2019-02-22 15:06:42 +00:00
|
|
|
|
new_number,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"We will send {} a text message to tell them about the change.".format(
|
|
|
|
|
|
active_user_with_permissions["name"]
|
|
|
|
|
|
),
|
2019-02-22 15:06:42 +00:00
|
|
|
|
]:
|
2019-03-26 12:35:32 +00:00
|
|
|
|
assert text in page.text
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert "Confirm" in page.text
|
2019-02-21 13:03:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
2019-02-25 14:27:37 +00:00
|
|
|
|
def test_confirm_edit_user_mobile_number_page_redirects_if_session_empty(
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request,
|
2019-02-25 14:27:37 +00:00
|
|
|
|
active_user_with_permissions,
|
2019-02-26 11:47:15 +00:00
|
|
|
|
mock_get_users_by_service,
|
2019-02-25 14:27:37 +00:00
|
|
|
|
service_one,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
mock_get_user,
|
|
|
|
|
|
):
|
2019-03-26 12:35:32 +00:00
|
|
|
|
page = client_request.get(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.confirm_edit_user_mobile_number",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=active_user_with_permissions["id"],
|
2019-03-26 12:35:32 +00:00
|
|
|
|
_expected_status=302,
|
|
|
|
|
|
)
|
2023-08-25 09:12:23 -07:00
|
|
|
|
assert "Confirm change of mobile number" not in page.text
|
2019-02-25 14:27:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
2019-02-22 16:01:04 +00:00
|
|
|
|
def test_confirm_edit_user_mobile_number_changes_user_mobile_number(
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request,
|
2019-02-22 16:01:04 +00:00
|
|
|
|
active_user_with_permissions,
|
2019-04-03 11:47:46 +01:00
|
|
|
|
api_user_active,
|
2019-02-22 16:01:04 +00:00
|
|
|
|
service_one,
|
|
|
|
|
|
mocker,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mock_update_user_attribute,
|
2019-02-22 16:01:04 +00:00
|
|
|
|
):
|
2019-04-03 11:47:46 +01:00
|
|
|
|
# We want active_user_with_permissions (the current user) to update the mobile number for api_user_active
|
|
|
|
|
|
# By default both users would have the same id, so we change the id of api_user_active
|
2023-08-25 09:12:23 -07:00
|
|
|
|
api_user_active["id"] = str(uuid.uuid4())
|
2019-04-03 11:47:46 +01:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.models.user.Users.client_method",
|
|
|
|
|
|
return_value=[api_user_active, active_user_with_permissions],
|
|
|
|
|
|
)
|
2019-04-03 11:47:46 +01:00
|
|
|
|
# get_user gets called twice - first to check if current user can see the page, then to see if the team member
|
|
|
|
|
|
# whose mobile number we're changing belongs to the service
|
2023-08-25 09:12:23 -07:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
"app.user_api_client.get_user",
|
|
|
|
|
|
side_effect=[active_user_with_permissions, api_user_active],
|
|
|
|
|
|
)
|
|
|
|
|
|
mock_event_handler = mocker.patch(
|
|
|
|
|
|
"app.main.views.manage_users.create_mobile_number_change_event"
|
|
|
|
|
|
)
|
2019-04-03 11:47:46 +01:00
|
|
|
|
|
2023-08-25 09:12:23 -07:00
|
|
|
|
new_number = "2028675309"
|
2019-03-26 12:35:32 +00:00
|
|
|
|
with client_request.session_transaction() as session:
|
2023-08-25 09:12:23 -07:00
|
|
|
|
session["team_member_mobile_change"] = new_number
|
2019-04-03 11:47:46 +01:00
|
|
|
|
|
2019-03-26 12:35:32 +00:00
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.confirm_edit_user_mobile_number",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=api_user_active["id"],
|
2019-03-26 12:35:32 +00:00
|
|
|
|
_expected_status=302,
|
|
|
|
|
|
_expected_redirect=url_for(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.manage_users",
|
2019-03-26 12:35:32 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
2019-02-26 16:28:05 +00:00
|
|
|
|
mock_update_user_attribute.assert_called_once_with(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
api_user_active["id"],
|
2019-02-26 16:28:05 +00:00
|
|
|
|
mobile_number=new_number,
|
2023-08-25 09:12:23 -07:00
|
|
|
|
updated_by=active_user_with_permissions["id"],
|
2019-02-26 16:28:05 +00:00
|
|
|
|
)
|
2019-04-03 11:47:46 +01:00
|
|
|
|
mock_event_handler.assert_called_once_with(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
user_id=api_user_active["id"],
|
|
|
|
|
|
updated_by_id=active_user_with_permissions["id"],
|
|
|
|
|
|
original_mobile_number=api_user_active["mobile_number"],
|
|
|
|
|
|
new_mobile_number=new_number,
|
|
|
|
|
|
)
|
2019-02-26 11:47:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_confirm_edit_user_mobile_number_doesnt_change_user_mobile_for_non_team_member(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
|
):
|
|
|
|
|
|
with client_request.session_transaction() as session:
|
2023-08-25 09:12:23 -07:00
|
|
|
|
session["team_member_mobile_change"] = "2028675309"
|
2019-02-26 11:47:15 +00:00
|
|
|
|
client_request.post(
|
2023-08-25 09:12:23 -07:00
|
|
|
|
"main.confirm_edit_user_mobile_number",
|
2019-02-26 11:47:15 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
user_id=USER_ONE_ID,
|
|
|
|
|
|
_expected_status=404,
|
|
|
|
|
|
)
|