From 56b0c00d045553611a9f856f11d5dcf8002fed4c Mon Sep 17 00:00:00 2001
From: Ernesto Rico Schmidt <ernesto@helsinki.at>
Date: Tue, 4 Jun 2024 16:30:44 -0400
Subject: [PATCH] feat: add validation of cba_domains & line_in_channels

---
 program/models.py | 42 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/program/models.py b/program/models.py
index d61561cf..7b89f728 100644
--- a/program/models.py
+++ b/program/models.py
@@ -17,11 +17,12 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
-
+import jsonschema
 from rest_framework.exceptions import ValidationError
 from versatileimagefield.fields import PPOIField, VersatileImageField
 
 from django.contrib.auth.models import User
+from django.core.exceptions import ValidationError as DjangoValidationError
 from django.db import models
 from django.db.models import Max, Q
 from django.utils import timezone
@@ -548,10 +549,40 @@ class ImageShapeField(models.CharField):
         super().__init__(*args, **kwargs)
 
 
+def validate_cba_domains(value):
+    schema = {
+        "type": "array",
+        "items": {"type": "string"},
+    }
+
+    try:
+        jsonschema.validate(value, schema)
+    except jsonschema.exceptions.ValidationError as e:
+        raise DjangoValidationError(e.args[0])
+
+
+def validate_line_in_channels(value):
+    schema = {
+        "type": "object",
+        "patternProperties": {
+            "^.*$": {"type": "string"},
+        },
+    }
+
+    try:
+        jsonschema.validate(value, schema)
+    except jsonschema.exceptions.ValidationError as e:
+        raise DjangoValidationError(e.args[0])
+
+
 class RadioSettings(models.Model):
     cba_api_key = models.CharField(blank=True, max_length=64, verbose_name="CBA API key")
     cba_domains = models.JSONField(
-        blank=True, default=list, help_text="JSON array of strings", verbose_name="CBA domains"
+        blank=True,
+        default=list,
+        help_text="JSON array of strings",
+        validators=[validate_cba_domains],
+        verbose_name="CBA domains",
     )
     fallback_default_pool = models.CharField(blank=True, max_length=32)
     fallback_show = models.ForeignKey(
@@ -559,7 +590,12 @@ class RadioSettings(models.Model):
     )
     host_image_aspect_ratio = ImageAspectRadioField(default="1:1")
     host_image_shape = ImageShapeField(default="round")
-    line_in_channels = models.JSONField(blank=True, default=dict, help_text="JSON key/value pairs")
+    line_in_channels = models.JSONField(
+        blank=True,
+        default=dict,
+        help_text="JSON key/value pairs",
+        validators=[validate_line_in_channels],
+    )
     micro_show = models.ForeignKey(
         Show, blank=True, null=True, on_delete=models.CASCADE, related_name="+"
     )
-- 
GitLab