diff --git a/snpdb/models/models.py b/snpdb/models/models.py index 925cd8171..aa026b244 100644 --- a/snpdb/models/models.py +++ b/snpdb/models/models.py @@ -22,7 +22,7 @@ from django.conf import settings from django.contrib.auth.models import User, Group from django.core.cache import cache -from django.core.exceptions import PermissionDenied, ValidationError +from django.core.exceptions import FieldDoesNotExist, PermissionDenied, ValidationError from django.db import models from django.db.models import QuerySet, TextChoices from django.db.models.deletion import SET_NULL, CASCADE, PROTECT @@ -206,6 +206,10 @@ def get_subclass_by_name(class_name): @staticmethod def get_or_create(class_name, unique_keyword, unique_value): klass = Wiki.get_subclass_by_name(class_name) + try: + klass._meta.get_field(unique_keyword) + except FieldDoesNotExist: + raise PermissionDenied(f"'{unique_keyword}' is not a valid field for {class_name}") wiki, _ = klass.objects.get_or_create(**{unique_keyword: unique_value}) return wiki diff --git a/snpdb/templatetags/model_tags.py b/snpdb/templatetags/model_tags.py index 86a88b104..58348f2e5 100644 --- a/snpdb/templatetags/model_tags.py +++ b/snpdb/templatetags/model_tags.py @@ -1,4 +1,5 @@ from django.template.library import Library +from django.utils.html import escape from django.utils.safestring import mark_safe from snpdb.models import Trio, Quad @@ -18,5 +19,5 @@ def quad_table(quad: Quad): @register.simple_tag def trio_short_description(trio: Trio): - params = (trio.mother_details, trio.father_details, trio.proband) + params = (escape(trio.mother_details), escape(trio.father_details), escape(trio.proband)) return mark_safe("M: %s/F: %s/P: %s" % params) diff --git a/snpdb/views/views.py b/snpdb/views/views.py index bcde1a434..efcdd0fdd 100644 --- a/snpdb/views/views.py +++ b/snpdb/views/views.py @@ -13,6 +13,7 @@ from django.core.exceptions import PermissionDenied, ImproperlyConfigured, ObjectDoesNotExist from django.db.utils import IntegrityError from django.forms.models import inlineformset_factory, ALL_FIELDS +from django.utils.html import escape from django.forms.widgets import TextInput from django.http import HttpRequest from django.http.response import HttpResponse, HttpResponseRedirect, HttpResponseServerError, JsonResponse @@ -1353,11 +1354,11 @@ def sample_gene_matrix(request, variant_annotation_version, samples, gene_list, sample_code = "%03d" % i if can_access: view_sample_url = reverse('view_sample', kwargs={'sample_id': sample.pk}) - - sample_link = f'{sample.name}' + safe_name = escape(sample.name) + sample_link = f'{safe_name}' if sample_link in used_sample_names: - uniq_sample_name = sample.name + "_" + sample_code - sample_link = f'{uniq_sample_name}' + safe_uniq_name = escape(sample.name + "_" + sample_code) + sample_link = f'{safe_uniq_name}' sample_name = sample_link else: