feat(formbuilder): answers must belong to the submission's form
An Answer's field could point at a field of a *different* form than its submission — and since forms are club-scoped, across clubs too. Validate field.form == submission.form in clean(). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.db.models import UniqueConstraint
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
@@ -100,3 +101,7 @@ class Answer(UUIDModel):
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.submission} - {self.field}"
|
||||
|
||||
def clean(self):
|
||||
if self.field_id and self.submission_id and self.field.form_id != self.submission.form_id:
|
||||
raise ValidationError({"field": _("Must belong to the same form as the submission.")})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import IntegrityError
|
||||
from django.db.models import ProtectedError
|
||||
from django.test import TestCase
|
||||
@@ -329,3 +330,20 @@ class FormReportTests(FormbuilderTestBase):
|
||||
|
||||
self.assertEqual(report.count, 0)
|
||||
self.assertEqual(report.rows, [])
|
||||
|
||||
|
||||
class AnswerCleanTests(FormbuilderTestBase):
|
||||
def test_rejects_field_from_another_form(self):
|
||||
other_form = Form.objects.create(club=self.club, title="Other", slug="other")
|
||||
other_field = Field.objects.create(form=other_form, key="x", label="X", order=1)
|
||||
submission = Submission.objects.create(form=self.form, member=self.member)
|
||||
answer = Answer(submission=submission, field=other_field, value="v")
|
||||
|
||||
with self.assertRaises(ValidationError) as ctx:
|
||||
answer.full_clean()
|
||||
self.assertIn("field", ctx.exception.error_dict)
|
||||
|
||||
def test_accepts_field_from_the_submissions_form(self):
|
||||
submission = Submission.objects.create(form=self.form, member=self.member)
|
||||
|
||||
Answer(submission=submission, field=self.name, value="v").full_clean()
|
||||
|
||||
Reference in New Issue
Block a user