|
4 | 4 | import pathlib |
5 | 5 | import re |
6 | 6 | from collections import OrderedDict |
| 7 | +from datetime import timedelta |
7 | 8 | from enum import Enum |
8 | 9 | from json import dumps |
9 | 10 | from pathlib import Path |
|
14 | 15 | from django.contrib.auth.models import Permission |
15 | 16 | from django.test import tag as test_tag |
16 | 17 | from django.urls import reverse |
| 18 | +from django.utils import timezone |
17 | 19 | from drf_spectacular.drainage import GENERATOR_STATS |
18 | 20 | from drf_spectacular.settings import spectacular_settings |
19 | 21 | from drf_spectacular.validation import validate_schema |
@@ -919,6 +921,102 @@ def test_close_finding_pushes_note_to_jira_when_configured(self): |
919 | 921 | self.assertTrue(add_comment_mock.called) |
920 | 922 |
|
921 | 923 |
|
| 924 | +class FindingCreateUpdateMitigatedFieldsAPITest(DojoAPITestCase): |
| 925 | + fixtures = ["dojo_testdata.json"] |
| 926 | + |
| 927 | + def setUp(self): |
| 928 | + testuser = User.objects.get(username="admin") |
| 929 | + token = Token.objects.get(user=testuser) |
| 930 | + self.client = APIClient() |
| 931 | + self.client.credentials(HTTP_AUTHORIZATION=f"Token {token.key}") |
| 932 | + self.admin = testuser |
| 933 | + self.base_url = "/api/v2/findings/" |
| 934 | + |
| 935 | + def _minimal_create_payload(self, title: str): |
| 936 | + return { |
| 937 | + "test": 3, |
| 938 | + "found_by": [], |
| 939 | + "title": title, |
| 940 | + "date": "2020-05-20", |
| 941 | + "cwe": 1, |
| 942 | + "severity": "High", |
| 943 | + "description": "TEST finding", |
| 944 | + "mitigation": "MITIGATION", |
| 945 | + "impact": "HIGH", |
| 946 | + "references": "", |
| 947 | + "active": False, |
| 948 | + "verified": False, |
| 949 | + "false_p": False, |
| 950 | + "duplicate": False, |
| 951 | + "out_of_scope": False, |
| 952 | + "under_review": False, |
| 953 | + "under_defect_review": False, |
| 954 | + "numerical_severity": "S0", |
| 955 | + } |
| 956 | + |
| 957 | + def test_create_rejects_mitigated_fields_by_default(self): |
| 958 | + payload = self._minimal_create_payload("API create with mitigated disallowed") |
| 959 | + past = (timezone.now() - timedelta(days=7)).replace(microsecond=0) |
| 960 | + payload.update({ |
| 961 | + "is_mitigated": True, |
| 962 | + "mitigated": past.isoformat(), |
| 963 | + "mitigated_by": self.admin.id, |
| 964 | + }) |
| 965 | + |
| 966 | + response = self.client.post(self.base_url, payload, format="json") |
| 967 | + self.assertEqual(400, response.status_code, response.content[:1000]) |
| 968 | + self.assertIn("mitigated", response.data) |
| 969 | + self.assertIn("mitigated_by", response.data) |
| 970 | + |
| 971 | + def test_update_rejects_mitigated_fields_by_default(self): |
| 972 | + finding_id = 7 |
| 973 | + past = (timezone.now() - timedelta(days=7)).replace(microsecond=0) |
| 974 | + payload = { |
| 975 | + "is_mitigated": True, |
| 976 | + "mitigated": past.isoformat(), |
| 977 | + "mitigated_by": self.admin.id, |
| 978 | + } |
| 979 | + response = self.client.patch(f"{self.base_url}{finding_id}/", payload, format="json") |
| 980 | + self.assertEqual(400, response.status_code, response.content[:1000]) |
| 981 | + self.assertIn("mitigated", response.data) |
| 982 | + self.assertIn("mitigated_by", response.data) |
| 983 | + |
| 984 | + def test_create_sets_mitigated_fields_when_permitted(self): |
| 985 | + with patch("dojo.finding.helper.can_edit_mitigated_data", return_value=True): |
| 986 | + payload = self._minimal_create_payload("API create with mitigated allowed") |
| 987 | + past = (timezone.now() - timedelta(days=7)).replace(microsecond=0) |
| 988 | + payload.update({ |
| 989 | + "is_mitigated": True, |
| 990 | + "mitigated": past.isoformat(), |
| 991 | + "mitigated_by": self.admin.id, |
| 992 | + }) |
| 993 | + |
| 994 | + response = self.client.post(self.base_url, payload, format="json") |
| 995 | + self.assertEqual(201, response.status_code, response.content[:1000]) |
| 996 | + |
| 997 | + created_id = response.data.get("id") |
| 998 | + self.assertIsNotNone(created_id) |
| 999 | + created = Finding.objects.get(id=created_id) |
| 1000 | + self.assertEqual(created.mitigated.replace(microsecond=0, tzinfo=created.mitigated.tzinfo), past) |
| 1001 | + self.assertEqual(created.mitigated_by, self.admin) |
| 1002 | + |
| 1003 | + def test_update_sets_mitigated_fields_when_permitted(self): |
| 1004 | + finding_id = 7 |
| 1005 | + with patch("dojo.finding.helper.can_edit_mitigated_data", return_value=True): |
| 1006 | + past = (timezone.now() - timedelta(days=7)).replace(microsecond=0) |
| 1007 | + payload = { |
| 1008 | + "is_mitigated": True, |
| 1009 | + "mitigated": past.isoformat(), |
| 1010 | + "mitigated_by": self.admin.id, |
| 1011 | + } |
| 1012 | + response = self.client.patch(f"{self.base_url}{finding_id}/", payload, format="json") |
| 1013 | + self.assertEqual(200, response.status_code, response.content[:1000]) |
| 1014 | + |
| 1015 | + updated = Finding.objects.get(id=finding_id) |
| 1016 | + self.assertEqual(updated.mitigated.replace(microsecond=0, tzinfo=updated.mitigated.tzinfo), past) |
| 1017 | + self.assertEqual(updated.mitigated_by, self.admin) |
| 1018 | + |
| 1019 | + |
922 | 1020 | class EndpointStatusTest(BaseClass.BaseClassTest): |
923 | 1021 | fixtures = ["dojo_testdata.json"] |
924 | 1022 |
|
|
0 commit comments