Skip to content

Commit 23b6edd

Browse files
authored
Make notes read-only on the test create serializer (#15334)
Notes get added to a test through the notes endpoint, not when you create the test. The finding create serializer already keeps notes read-only, so this does the same for tests. Added a regression test.
1 parent 35c08a0 commit 23b6edd

2 files changed

Lines changed: 60 additions & 4 deletions

File tree

dojo/test/api/serializer.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
from dojo.models import (
55
Engagement,
6-
Notes,
76
Test,
87
Test_Import,
98
Test_Import_Finding_Action,
@@ -65,11 +64,11 @@ class TestCreateSerializer(serializers.ModelSerializer):
6564
engagement = serializers.PrimaryKeyRelatedField(
6665
queryset=Engagement.objects.all(),
6766
)
67+
# notes are added through the notes endpoint, not at create time, so keep
68+
# this read-only here (findings already do the same).
6869
notes = serializers.PrimaryKeyRelatedField(
69-
allow_null=True,
70-
queryset=Notes.objects.all(),
7170
many=True,
72-
required=False,
71+
read_only=True,
7372
)
7473

7574
class Meta:
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import logging
2+
3+
from django.utils import timezone
4+
from rest_framework.authtoken.models import Token
5+
6+
from dojo.models import Engagement, Notes, Product, Product_Type, Test, Test_Type, User
7+
8+
from .dojo_test_case import DojoAPITestCase
9+
10+
logger = logging.getLogger(__name__)
11+
12+
13+
class TestCreateNotesReadOnlyAPI(DojoAPITestCase):
14+
15+
"""notes should be read-only when creating a test (added through the notes endpoint instead)."""
16+
17+
def setUp(self):
18+
user, _ = User.objects.get_or_create(username="admin", defaults={"is_superuser": True, "is_staff": True})
19+
token, _ = Token.objects.get_or_create(user=user)
20+
self.client.credentials(HTTP_AUTHORIZATION=f"Token {token.key}")
21+
22+
product_type, _ = Product_Type.objects.get_or_create(name="notes-readonly-api")
23+
product, _ = Product.objects.get_or_create(
24+
name="TestCreateNotesReadOnlyAPI",
25+
description="Test",
26+
prod_type=product_type,
27+
)
28+
self.engagement, _ = Engagement.objects.get_or_create(
29+
name="notes readonly api",
30+
product=product,
31+
target_start=timezone.now(),
32+
target_end=timezone.now(),
33+
)
34+
self.test_type, _ = Test_Type.objects.get_or_create(name="Acunetix Scan")
35+
# a Note row that already exists independently of the create request
36+
self.existing_note = Notes.objects.create(entry="preexisting", author=user)
37+
38+
def _payload(self, **overrides):
39+
payload = {
40+
"engagement": self.engagement.id,
41+
"test_type": self.test_type.id,
42+
"title": "notes readonly",
43+
"target_start": "2026-07-01T00:00:00Z",
44+
"target_end": "2026-07-02T00:00:00Z",
45+
}
46+
payload.update(overrides)
47+
return payload
48+
49+
def test_notes_supplied_on_create_are_ignored(self):
50+
response = self.client.post("/api/v2/tests/", self._payload(notes=[self.existing_note.id]), format="json")
51+
self.assertEqual(201, response.status_code, response.content)
52+
body = response.json()
53+
# read side unchanged: notes is still part of the representation ...
54+
self.assertIn("notes", body)
55+
# ... but read-only, so the supplied id is not adopted by the new Test
56+
self.assertEqual([], body["notes"])
57+
self.assertEqual(0, Test.objects.get(id=body["id"]).notes.count())

0 commit comments

Comments
 (0)