Skip to content

Commit

Permalink
Merge branch 'dev' into LTD-5573-make-makedown-safe-remove
Browse files Browse the repository at this point in the history
  • Loading branch information
depsiatwal authored Nov 4, 2024
2 parents e5d58be + d544e4a commit f0f4c3f
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 23 deletions.
22 changes: 22 additions & 0 deletions caseworker/core/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
)
from caseworker.core.constants import (
ADMIN_TEAM_ID,
SUPER_USER_ROLE_ID,
TAU_TEAM_ID,
LICENSING_UNIT_TEAM_ID,
LICENSING_UNIT_SENIOR_MANAGER_ROLE_ID,
Expand Down Expand Up @@ -180,6 +181,21 @@ def is_organisation_active(request, organisation):
return organisation["status"]["key"] == "active"


@rules.predicate
def is_super_user(request):
user = get_logged_in_caseworker(request)
return user.get("role", {}).get("id") == SUPER_USER_ROLE_ID


@rules.predicate
def check_user_is_not_logged_in_caseworker(request, user):
caseworker = get_logged_in_caseworker(request)
caseworker_user_id = caseworker["id"]
if not user:
return True
return user.get("user", {}).get("id") != caseworker_user_id


rules.add_rule("can_user_allocate_case", is_case_caseworker_operable)
rules.add_rule("can_user_change_case", is_user_allocated)
rules.add_rule("can_user_move_case_forward", is_user_allocated)
Expand All @@ -205,3 +221,9 @@ def is_organisation_active(request, organisation):
"can_licence_status_be_changed", is_user_licencing_unit_senior_manager & is_case_finalised_and_licence_editable
)
rules.add_rule("can_user_manage_organisation", is_user_manage_organisations_role & is_organisation_active)
rules.add_rule("can_caseworker_edit_role", is_super_user | is_user_in_admin_team) # noqa
rules.add_rule("can_caseworker_edit_team", is_super_user | is_user_in_admin_team) # noqa
rules.add_rule(
"can_caseworker_deactivate",
(is_super_user | is_user_in_admin_team) & check_user_is_not_logged_in_caseworker, # noqa
)
12 changes: 7 additions & 5 deletions caseworker/templates/users/profile.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{% extends 'layouts/two-pane.html' %}
{% load rules %}

{% block back_link %}
<a href="{% url 'users:users' %}" id="back-link" class="govuk-back-link">
Expand All @@ -20,8 +21,8 @@ <h1 class="govuk-heading-l">
</h1>
</div>
<div class="lite-app-bar__controls">
{% if can_deactivate %}
{% if request.session.lite_api_user_id|stringformat:"s" != data.user.id|stringformat:"s" %}
{% test_rule 'can_caseworker_deactivate' request data as show_deactivate %}
{% if show_deactivate %}
{% if data.user.status == 'Active' %}
<a id="button-deactivate-user" href="{% url 'users:change_status' data.user.id 'deactivate' %}" role="button" draggable="false" class="govuk-button govuk-button--secondary">
{% lcs 'users.UserProfile.DEACTIVATE_BUTTON' %}
Expand All @@ -31,7 +32,6 @@ <h1 class="govuk-heading-l">
{% lcs 'users.UserProfile.REACTIVATE_BUTTON' %}
</a>
{% endif %}
{% endif %}
{% endif %}
</div>
</div>
Expand Down Expand Up @@ -81,7 +81,8 @@ <h1 class="govuk-heading-l">
<a href="{% url 'teams:team' data.user.team.id %}" id="user-team-name" class="govuk-link govuk-link--no-visited-state">{{ data.user.team.name }}</a>
</dd>
<dd class="govuk-summary-list__actions">
{% if can_edit_team %}
{% test_rule 'can_caseworker_edit_team' request as show_edit_team %}
{% if show_edit_team %}
<a id="link-edit-team" href="{% url 'users:edit' data.user.id %}#team" class="govuk-link govuk-link--no-visited-state">
{% lcs 'users.UserProfile.SummaryList.CHANGE' %}
<span class="govuk-visually-hidden">{% lcs 'users.UserProfile.SummaryList.TEAM' %}</span>
Expand All @@ -97,7 +98,8 @@ <h1 class="govuk-heading-l">
{{ data.user.role.name }}
</dd>
<dd class="govuk-summary-list__actions">
{% if can_edit_role %}
{% test_rule 'can_caseworker_edit_role' request as show_edit_role %}
{% if show_edit_role %}
<a id="link-edit-role" href="{% url 'users:edit' data.user.id %}#role" class="govuk-link govuk-link--no-visited-state">
{% lcs 'users.UserProfile.SummaryList.CHANGE' %}
<span class="govuk-visually-hidden">{% lcs 'users.UserProfile.SummaryList.ROLE' %}</span>
Expand Down
12 changes: 0 additions & 12 deletions caseworker/users/views/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from core.auth.views import LoginRequiredMixin
from caseworker.core.constants import (
ADMIN_TEAM_ID,
SUPER_USER_ROLE_ID,
UserStatuses,
)
from lite_content.lite_internal_frontend import strings
Expand Down Expand Up @@ -78,19 +77,8 @@ def get_success_url(self):
class ViewUser(TemplateView):
def get(self, request, **kwargs):
data, _ = get_gov_user(request, str(kwargs["pk"]))
request_user, _ = get_gov_user(request, str(request.session["lite_api_user_id"]))
super_user = is_super_user(request_user)
can_deactivate = not is_super_user(data)
can_edit_role = data["user"]["id"] != request.session["lite_api_user_id"]
can_edit_team = super_user or is_user_in_team(request_user, ADMIN_TEAM_ID)

context = {
"data": data,
"super_user": super_user,
"super_user_role_id": SUPER_USER_ROLE_ID,
"can_deactivate": can_deactivate,
"can_edit_role": can_edit_role,
"can_edit_team": can_edit_team,
}
return render(request, "users/profile.html", context)

Expand Down
8 changes: 3 additions & 5 deletions exporter/applications/views/security_approvals/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class Layout:
TITLE = "Are any products on this application subject to ITAR controls?"

label = """
We need to know if this export involves any defence articles including technical data that are
We need to know if this export involves any defence articles including technical data that are
subject to controls under the United States (US) International Traffic in Arms regulations (ITAR).
"""

Expand Down Expand Up @@ -126,11 +126,9 @@ class Layout:
)

f1686_reference_number = forms.CharField(
required=False,
widget=forms.TextInput,
label="Reference number",
error_messages={
"required": "Enter a reference number",
},
label="Reference number (optional)",
)

f1686_approval_date = CustomErrorDateInputField(
Expand Down
72 changes: 72 additions & 0 deletions unit_tests/caseworker/core/test_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
ADMIN_TEAM_ID,
FCDO_TEAM_ID,
LICENSING_UNIT_TEAM_ID,
SUPER_USER_ROLE_ID,
TAU_TEAM_ID,
LICENSING_UNIT_SENIOR_MANAGER_ROLE_ID,
Permission,
Expand Down Expand Up @@ -698,3 +699,74 @@ def test_can_user_manage_organisation(
request = get_mock_request(user)
data_organisation["status"]["key"] = organisation_status
assert rules.test_rule("can_user_manage_organisation", request, data_organisation) is expected


@pytest.mark.parametrize(
("user_role", "user_team", "expected"),
(
(SUPER_USER_ROLE_ID, ADMIN_TEAM_ID, True),
(SUPER_USER_ROLE_ID, TAU_TEAM_ID, True),
(LICENSING_UNIT_SENIOR_MANAGER_ROLE_ID, ADMIN_TEAM_ID, True),
(LICENSING_UNIT_SENIOR_MANAGER_ROLE_ID, TAU_TEAM_ID, False),
(None, None, False),
),
)
def test_can_caseworker_edit_role(mock_gov_user, get_mock_request, user_team, user_role, expected):
user = mock_gov_user["user"]
user["role"]["id"] = user_role
user["team"]["id"] = user_team
request = get_mock_request(user)
assert rules.test_rule("can_caseworker_edit_role", request) is expected


@pytest.mark.parametrize(
("user_role", "user_team", "expected"),
(
(SUPER_USER_ROLE_ID, ADMIN_TEAM_ID, True),
(SUPER_USER_ROLE_ID, TAU_TEAM_ID, True),
(LICENSING_UNIT_SENIOR_MANAGER_ROLE_ID, ADMIN_TEAM_ID, True),
(LICENSING_UNIT_SENIOR_MANAGER_ROLE_ID, TAU_TEAM_ID, False),
(None, None, False),
),
)
def test_can_caseworker_edit_team(mock_gov_user, get_mock_request, user_team, user_role, expected):

user = mock_gov_user["user"]
user["role"]["id"] = user_role
user["team"]["id"] = user_team

request = get_mock_request(user)
assert rules.test_rule("can_caseworker_edit_team", request) is expected


@pytest.mark.parametrize(
("user_role", "user_team", "user_data", "expected"),
(
(SUPER_USER_ROLE_ID, ADMIN_TEAM_ID, {"user": {"id": "123"}}, True),
(SUPER_USER_ROLE_ID, TAU_TEAM_ID, {"user": {"id": "123"}}, True),
(LICENSING_UNIT_SENIOR_MANAGER_ROLE_ID, ADMIN_TEAM_ID, {"user": {"id": "123"}}, True),
(SUPER_USER_ROLE_ID, ADMIN_TEAM_ID, {"user": {"id": "2a43805b-c082-47e7-9188-c8b3e1a83cb0"}}, False),
(SUPER_USER_ROLE_ID, TAU_TEAM_ID, {"user": {"id": "2a43805b-c082-47e7-9188-c8b3e1a83cb0"}}, False),
(
LICENSING_UNIT_SENIOR_MANAGER_ROLE_ID,
ADMIN_TEAM_ID,
{"user": {"id": "2a43805b-c082-47e7-9188-c8b3e1a83cb0"}},
False,
),
(
LICENSING_UNIT_SENIOR_MANAGER_ROLE_ID,
TAU_TEAM_ID,
{"user": {"id": "2a43805b-c082-47e7-9188-c8b3e1a83cb0"}},
False,
),
(SUPER_USER_ROLE_ID, ADMIN_TEAM_ID, None, True),
(None, None, None, False),
),
)
def test_can_caseworker_deactivate(mock_gov_user, get_mock_request, user_team, user_role, user_data, expected):

user = mock_gov_user["user"]
user["role"]["id"] = user_role
user["team"]["id"] = user_team
request = get_mock_request(user)
assert rules.test_rule("can_caseworker_deactivate", request, user_data) is expected
115 changes: 115 additions & 0 deletions unit_tests/caseworker/users/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,121 @@ def test_view_user_edit_team_permissions(
assert (soup.find("a", {"id": "link-edit-team"}) is not None) == can_edit_team


@pytest.mark.parametrize(
"role_id, team_id, can_edit_role",
(
(SUPER_USER_ROLE_ID, ADMIN_TEAM_ID, True),
(NON_SUPER_USER_ROLE_ID, NON_ADMIN_TEAM_ID, False),
(SUPER_USER_ROLE_ID, NON_ADMIN_TEAM_ID, True),
(NON_SUPER_USER_ROLE_ID, ADMIN_TEAM_ID, True),
(SUPER_USER_ROLE_ID, ADMIN_TEAM_ID, True),
),
)
def test_view_user_edit_role_permissions(
authorized_client,
requests_mock,
mock_gov_user,
role_id,
team_id,
can_edit_role,
):
user_id = str(uuid.uuid4())

mock_gov_user["user"] = {
"id": user_id,
"role": {
"id": role_id,
"permissions": {},
"name": "Test Role",
},
"team": {
"id": team_id,
},
}
requests_mock.get(
client._build_absolute_uri(f"/gov-users/{user_id}/"),
json={
"user": {
"id": user_id,
"role": {
"id": role_id,
},
"team": {
"id": team_id,
},
},
},
)

url = reverse("users:user", kwargs={"pk": user_id})
response = authorized_client.get(url)

soup = BeautifulSoup(response.content, "html.parser")
assert (soup.find("a", {"id": "link-edit-role"}) is not None) == can_edit_role


@pytest.mark.parametrize(
"role_id, team_id, edit_user_id ,can_deactivate",
(
(SUPER_USER_ROLE_ID, ADMIN_TEAM_ID, "2a43805b-c082-47e7-9188-c8b3e1a83cb0", False),
(SUPER_USER_ROLE_ID, NON_ADMIN_TEAM_ID, "2a43805b-c082-47e7-9188-c8b3e1a83cb0", False),
(NON_SUPER_USER_ROLE_ID, ADMIN_TEAM_ID, "2a43805b-c082-47e7-9188-c8b3e1a83cb0", False),
(SUPER_USER_ROLE_ID, ADMIN_TEAM_ID, "4a43805b-c082-47e7-9188-c8b3e1a83cb1", True),
(NON_SUPER_USER_ROLE_ID, NON_ADMIN_TEAM_ID, "4a43805b-c082-47e7-9188-c8b3e1a83cb1", False), ##£``
(SUPER_USER_ROLE_ID, NON_ADMIN_TEAM_ID, "4a43805b-c082-47e7-9188-c8b3e1a83cb1", True),
(NON_SUPER_USER_ROLE_ID, ADMIN_TEAM_ID, "4a43805b-c082-47e7-9188-c8b3e1a83cb1", True),
(SUPER_USER_ROLE_ID, ADMIN_TEAM_ID, "4a43805b-c082-47e7-9188-c8b3e1a83cb1", True),
),
)
def test_view_user_deactivate_permissions(
authorized_client,
requests_mock,
mock_gov_user,
role_id,
team_id,
edit_user_id,
can_deactivate,
):

gov_user_id = mock_gov_user["user"]["id"]

requests_mock.get(
client._build_absolute_uri(f"/gov-users/{gov_user_id}/"),
json={
"user": {
"id": gov_user_id,
"role": {
"id": role_id,
},
"team": {
"id": team_id,
},
},
},
)
requests_mock.get(
client._build_absolute_uri(f"/gov-users/{edit_user_id}/"),
json={
"user": {
"id": edit_user_id,
"role": {
"id": role_id,
},
"team": {
"id": team_id,
},
"status": "Active",
},
},
)

url = reverse("users:user", kwargs={"pk": edit_user_id})
response = authorized_client.get(url)

soup = BeautifulSoup(response.content, "html.parser")
assert (soup.find("a", {"id": "button-deactivate-user"}) is not None) == can_deactivate


@pytest.mark.parametrize(
"role_id, team_id, can_edit_team, team_payload",
(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,20 @@ def post_to_edit_security_approvals(post_to_step_factory, edit_security_approval
"f1686_approval_date": "2020-02-02",
},
),
(
"edit_security_approvals_f1686_details",
{
"f1686_contracting_authority": "some text",
"f1686_approval_date_0": "01",
"f1686_approval_date_1": "01",
"f1686_approval_date_2": "2022",
},
{
"f1686_contracting_authority": "some text",
"f1686_reference_number": "",
"f1686_approval_date": "2022-01-01",
},
),
),
)
def test_edit_export_details_post(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ def test_security_other_details(data, is_valid, errors):
{
"f1686_contracting_authority": ["Enter the contracting authority (or signatory and job role)"],
"f1686_approval_date": ["Enter the approval date"],
"f1686_reference_number": ["Enter a reference number"],
},
),
(
Expand Down

0 comments on commit f0f4c3f

Please sign in to comment.