From d046fb8c68dab3f20554afdef3c0affc3947e616 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Fri, 13 Sep 2024 10:57:04 +0100 Subject: [PATCH 1/8] Reverts account and frozen author fields to charfields. --- .../0096_alter_account_activation_code_and_more.py | 14 +++++++------- src/core/models.py | 14 +++++++------- .../0080_frozen_author_bleach_20240507_1350.py | 14 +++++++------- src/submission/models.py | 14 +++++++------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/core/migrations/0096_alter_account_activation_code_and_more.py b/src/core/migrations/0096_alter_account_activation_code_and_more.py index 424abfd9c..d8281c00f 100644 --- a/src/core/migrations/0096_alter_account_activation_code_and_more.py +++ b/src/core/migrations/0096_alter_account_activation_code_and_more.py @@ -19,32 +19,32 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='account', name='department', - field=core.model_utils.JanewayBleachCharField(blank=True, max_length=300, verbose_name='Department'), + field=models.CharField(blank=True, max_length=300, verbose_name='Department'), ), migrations.AlterField( model_name='account', name='first_name', - field=core.model_utils.JanewayBleachCharField(max_length=300, verbose_name='First name'), + field=models.CharField(max_length=300, verbose_name='First name'), ), migrations.AlterField( model_name='account', name='institution', - field=core.model_utils.JanewayBleachCharField(blank=True, max_length=1000, verbose_name='Institution'), + field=models.CharField(blank=True, max_length=1000, verbose_name='Institution'), ), migrations.AlterField( model_name='account', name='last_name', - field=core.model_utils.JanewayBleachCharField(max_length=300, verbose_name='Last name'), + field=models.CharField(max_length=300, verbose_name='Last name'), ), migrations.AlterField( model_name='account', name='middle_name', - field=core.model_utils.JanewayBleachCharField(blank=True, max_length=300, verbose_name='Middle name'), + field=models.CharField(blank=True, max_length=300, verbose_name='Middle name'), ), migrations.AlterField( model_name='account', name='salutation', - field=core.model_utils.JanewayBleachCharField(blank=True, choices=[('Miss', 'Miss'), ('Ms', 'Ms'), ('Mrs', 'Mrs'), ('Mr', 'Mr'), ('Mx', 'Mx'), ('Dr', 'Dr'), ('Prof.', 'Prof.')], max_length=10, verbose_name='Salutation'), + field=models.CharField(blank=True, choices=[('Miss', 'Miss'), ('Ms', 'Ms'), ('Mrs', 'Mrs'), ('Mr', 'Mr'), ('Mx', 'Mx'), ('Dr', 'Dr'), ('Prof.', 'Prof.')], max_length=10, verbose_name='Salutation'), ), migrations.AlterField( model_name='account', @@ -54,6 +54,6 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='account', name='suffix', - field=core.model_utils.JanewayBleachCharField(blank=True, max_length=300, verbose_name='Name suffix'), + field=models.CharField(blank=True, max_length=300, verbose_name='Name suffix'), ), ] diff --git a/src/core/models.py b/src/core/models.py index 9a3661a4b..c496d5dc9 100644 --- a/src/core/models.py +++ b/src/core/models.py @@ -235,30 +235,30 @@ class Account(AbstractBaseUser, PermissionsMixin): username = models.CharField(max_length=254, unique=True, verbose_name=_('Username')) name_prefix = models.CharField(max_length=10, blank=True) - first_name = JanewayBleachCharField( + first_name = models.CharField( max_length=300, blank=False, verbose_name=_('First name'), ) - middle_name = JanewayBleachCharField( + middle_name = models.CharField( max_length=300, blank=True, verbose_name=_('Middle name'), ) - last_name = JanewayBleachCharField( + last_name = models.CharField( max_length=300, blank=False, verbose_name=_('Last name'), ) activation_code = models.CharField(max_length=100, null=True, blank=True) - salutation = JanewayBleachCharField( + salutation = models.CharField( max_length=10, choices=SALUTATION_CHOICES, blank=True, verbose_name=_('Salutation'), ) - suffix = JanewayBleachCharField( + suffix = models.CharField( max_length=300, blank=True, verbose_name=_('Name suffix'), @@ -268,12 +268,12 @@ class Account(AbstractBaseUser, PermissionsMixin): verbose_name=_('Biography'), ) orcid = models.CharField(max_length=40, null=True, blank=True, verbose_name=_('ORCiD')) - institution = JanewayBleachCharField( + institution = models.CharField( max_length=1000, blank=True, verbose_name=_('Institution'), ) - department = JanewayBleachCharField( + department = models.CharField( max_length=300, blank=True, verbose_name=_('Department'), diff --git a/src/submission/migrations/0080_frozen_author_bleach_20240507_1350.py b/src/submission/migrations/0080_frozen_author_bleach_20240507_1350.py index 2cc7ae683..114c9153d 100644 --- a/src/submission/migrations/0080_frozen_author_bleach_20240507_1350.py +++ b/src/submission/migrations/0080_frozen_author_bleach_20240507_1350.py @@ -15,12 +15,12 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='frozenauthor', name='department', - field=core.model_utils.JanewayBleachCharField(blank=True, max_length=300), + field=models.CharField(blank=True, max_length=300), ), migrations.AlterField( model_name='frozenauthor', name='first_name', - field=core.model_utils.JanewayBleachCharField(blank=True, max_length=300), + field=models.CharField(blank=True, max_length=300), ), migrations.AlterField( model_name='frozenauthor', @@ -40,26 +40,26 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='frozenauthor', name='institution', - field=core.model_utils.JanewayBleachCharField(blank=True, max_length=1000), + field=models.CharField(blank=True, max_length=1000), ), migrations.AlterField( model_name='frozenauthor', name='last_name', - field=core.model_utils.JanewayBleachCharField(blank=True, max_length=300), + field=models.CharField(blank=True, max_length=300), ), migrations.AlterField( model_name='frozenauthor', name='middle_name', - field=core.model_utils.JanewayBleachCharField(blank=True, max_length=300), + field=models.CharField(blank=True, max_length=300), ), migrations.AlterField( model_name='frozenauthor', name='name_prefix', - field=core.model_utils.JanewayBleachCharField(blank=True, help_text='Optional name prefix (e.g: Prof or Dr)', max_length=300), + field=models.CharField(blank=True, help_text='Optional name prefix (e.g: Prof or Dr)', max_length=300), ), migrations.AlterField( model_name='frozenauthor', name='name_suffix', - field=core.model_utils.JanewayBleachCharField(blank=True, help_text='Optional name suffix (e.g.: Jr or III)', max_length=300), + field=models.CharField(blank=True, help_text='Optional name suffix (e.g.: Jr or III)', max_length=300), ), ] diff --git a/src/submission/models.py b/src/submission/models.py index a9b6d80c9..3623f4d86 100755 --- a/src/submission/models.py +++ b/src/submission/models.py @@ -1911,23 +1911,23 @@ class FrozenAuthor(AbstractLastModifiedModel): on_delete=models.SET_NULL, ) - name_prefix = JanewayBleachCharField( + name_prefix = models.CharField( max_length=300, blank=True, help_text=_("Optional name prefix (e.g: Prof or Dr)") ) - name_suffix = JanewayBleachCharField( + name_suffix = models.CharField( max_length=300, blank=True, help_text=_("Optional name suffix (e.g.: Jr or III)") ) - first_name = JanewayBleachCharField(max_length=300, blank=True) - middle_name = JanewayBleachCharField(max_length=300, blank=True) - last_name = JanewayBleachCharField(max_length=300, blank=True) + first_name = models.CharField(max_length=300, blank=True) + middle_name = models.CharField(max_length=300, blank=True) + last_name = models.CharField(max_length=300, blank=True) - institution = JanewayBleachCharField(max_length=1000, blank=True) - department = JanewayBleachCharField(max_length=300, blank=True) + institution = models.CharField(max_length=1000, blank=True) + department = models.CharField(max_length=300, blank=True) frozen_biography = JanewayBleachField( blank=True, verbose_name=_('Frozen Biography'), From 642daadf27b5b8e5ae91c9e05d40209afa500e46 Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Fri, 13 Sep 2024 11:18:18 +0100 Subject: [PATCH 2/8] Adds a button_classes var to style ORCID reg btn --- src/templates/common/elements/orcid_registration.html | 6 +++++- src/themes/OLH/templates/core/accounts/register.html | 2 +- src/themes/clean/templates/core/accounts/register.html | 2 +- src/themes/material/templates/core/accounts/register.html | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/templates/common/elements/orcid_registration.html b/src/templates/common/elements/orcid_registration.html index ee83a4b71..ee1357699 100644 --- a/src/templates/common/elements/orcid_registration.html +++ b/src/templates/common/elements/orcid_registration.html @@ -9,6 +9,10 @@ [remove]

{% else %} - {% trans "Register with ORCiD" %} + + {% trans "Register with ORCiD" %} + {% endif %} {% endif %} diff --git a/src/themes/OLH/templates/core/accounts/register.html b/src/themes/OLH/templates/core/accounts/register.html index 5a3d372c4..3898ca57e 100644 --- a/src/themes/OLH/templates/core/accounts/register.html +++ b/src/themes/OLH/templates/core/accounts/register.html @@ -30,7 +30,7 @@
{% trans "Register for an account with" %} {{ request.press.name }}.

{% blocktrans %}For more information read our password guide.{% endblocktrans %}

- {% include "common/elements/orcid_registration.html" %} + {% include "common/elements/orcid_registration.html" with button_classes="button expanded orcid-button" %} {% include "elements/forms/errors.html" with form=form %} diff --git a/src/themes/clean/templates/core/accounts/register.html b/src/themes/clean/templates/core/accounts/register.html index 2511eafdf..be56f96d8 100644 --- a/src/themes/clean/templates/core/accounts/register.html +++ b/src/themes/clean/templates/core/accounts/register.html @@ -20,7 +20,7 @@
{% trans "Register for an account with" %} {{ request.press.name }}.
{% include "common/elements/password_rules.html" %}

{% blocktrans %}For more information read our password guide.{% endblocktrans %}

- {% include "common/elements/orcid_registration.html" %} + {% include "common/elements/orcid_registration.html" with button_classes="btn orcid-button btn-block" %}
{% bootstrap_form form %}

diff --git a/src/themes/material/templates/core/accounts/register.html b/src/themes/material/templates/core/accounts/register.html index 40c25933b..9599b9345 100644 --- a/src/themes/material/templates/core/accounts/register.html +++ b/src/themes/material/templates/core/accounts/register.html @@ -24,7 +24,7 @@

{% blocktrans trimmed %}For more information read our password guide.{% endblocktrans %}

- {% include "common/elements/orcid_registration.html" %} + {% include "common/elements/orcid_registration.html" with button_classes="btn wide-button orcid-button" %}
{% include "elements/forms/errors.html" %} {% csrf_token %} From e46ae81a7cf4d6b21077dc62f335efb8ee551b96 Mon Sep 17 00:00:00 2001 From: Mauro MSL Date: Tue, 17 Sep 2024 19:38:26 +0100 Subject: [PATCH 3/8] #4405: Adds plain text sanitizer for model/forms --- src/utils/forms.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/utils/forms.py b/src/utils/forms.py index 1b6bb5eaf..e44988180 100644 --- a/src/utils/forms.py +++ b/src/utils/forms.py @@ -1,3 +1,4 @@ +import bleach from django.forms import ( CharField, CheckboxInput, @@ -8,6 +9,7 @@ ) from django.utils.translation import gettext_lazy as _ from django.conf import settings +from django.core.exceptions import ValidationError from modeltranslation import forms as mt_forms, translator from captcha.fields import ReCaptchaField @@ -18,6 +20,9 @@ from submission import models as submission_models +ENTITIES_MAP = (("&", "&"), (">", ">"), ("<", "<")) + + class JanewayTranslationModelForm(mt_forms.TranslationModelForm): def __init__(self, *args, **kwargs): super(JanewayTranslationModelForm, self).__init__(*args, **kwargs) @@ -109,3 +114,38 @@ def __init__(self, *args, **kwargs): captcha = CharField(widget=HiddenInput, required=False) self.fields["captcha"] = captcha + + +def text_sanitizer(text_value, tags=None, attrs=None, excl=ENTITIES_MAP): + """ A sanitizer for clearing potential harmful html/css/js from the input + :param text_value: the string to sanitize + :param tags: A list of allowed html tags + :param attrs: A dict of allowed html attributes + :param excl: A list of pairs of allowed items and their replacement + :return: Sanitized string + """ + tags = tags or [] + attrs = attrs or {} + excl = excl or {} + + cleaned = bleach.clean( + text_value, + tags=tags, + attributes=attrs, + strip=True, + ) + # Allow certain entities that bleach won't whitelist + # https://github.com/mozilla/bleach/issues/192#issuecomment-2304545475 + for escaped, raw in excl: + cleaned = cleaned.replace(escaped, raw) + + return cleaned + + +def plain_text_validator(value): + """ A field validator that ensures a textual input has no harmful code""" + sanitized = text_sanitizer(value) + if value != sanitized: + raise ValidationError( + _("HTML is not allowed in this field") + ) From 7a5ac58d2131c2c71ddbca86a09bf012d3a88e63 Mon Sep 17 00:00:00 2001 From: Mauro MSL Date: Tue, 17 Sep 2024 19:38:59 +0100 Subject: [PATCH 4/8] #4405: Flag models to use new HTML sanitizer --- src/core/models.py | 8 ++++++++ src/submission/models.py | 40 +++++++++++++++++++++++++++++++--------- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/core/models.py b/src/core/models.py index c496d5dc9..f3ba5e03a 100644 --- a/src/core/models.py +++ b/src/core/models.py @@ -53,6 +53,7 @@ from submission import models as submission_models from utils.logger import get_logger from utils import logic as utils_logic +from utils.forms import plain_text_validator from production import logic as production_logic fs = JanewayFileSystemStorage() @@ -239,16 +240,19 @@ class Account(AbstractBaseUser, PermissionsMixin): max_length=300, blank=False, verbose_name=_('First name'), + validators=[plain_text_validator], ) middle_name = models.CharField( max_length=300, blank=True, verbose_name=_('Middle name'), + validators=[plain_text_validator], ) last_name = models.CharField( max_length=300, blank=False, verbose_name=_('Last name'), + validators=[plain_text_validator], ) activation_code = models.CharField(max_length=100, null=True, blank=True) @@ -257,11 +261,13 @@ class Account(AbstractBaseUser, PermissionsMixin): choices=SALUTATION_CHOICES, blank=True, verbose_name=_('Salutation'), + validators=[plain_text_validator], ) suffix = models.CharField( max_length=300, blank=True, verbose_name=_('Name suffix'), + validators=[plain_text_validator], ) biography = JanewayBleachField( blank=True, @@ -272,11 +278,13 @@ class Account(AbstractBaseUser, PermissionsMixin): max_length=1000, blank=True, verbose_name=_('Institution'), + validators=[plain_text_validator], ) department = models.CharField( max_length=300, blank=True, verbose_name=_('Department'), + validators=[plain_text_validator], ) twitter = models.CharField(max_length=300, null=True, blank=True, verbose_name=_('Twitter Handle')) facebook = models.CharField(max_length=300, null=True, blank=True, verbose_name=_('Facebook Handle')) diff --git a/src/submission/models.py b/src/submission/models.py index 3623f4d86..80e953776 100755 --- a/src/submission/models.py +++ b/src/submission/models.py @@ -54,6 +54,7 @@ from review import models as review_models from utils.function_cache import cache from utils.logger import get_logger +from utils.forms import plain_text_validator from journal import models as journal_models from review.const import ( ReviewerDecisions as RD, @@ -1914,20 +1915,41 @@ class FrozenAuthor(AbstractLastModifiedModel): name_prefix = models.CharField( max_length=300, blank=True, - help_text=_("Optional name prefix (e.g: Prof or Dr)") - - ) + help_text=_("Optional name prefix (e.g: Prof or Dr)"), + validators=[plain_text_validator], + ) name_suffix = models.CharField( max_length=300, blank=True, - help_text=_("Optional name suffix (e.g.: Jr or III)") + help_text=_("Optional name suffix (e.g.: Jr or III)"), + validators=[plain_text_validator], + ) + first_name = models.CharField( + max_length=300, + blank=True, + validators=[plain_text_validator], + ) + middle_name = models.CharField( + max_length=300, + blank=True, + validators=[plain_text_validator], ) - first_name = models.CharField(max_length=300, blank=True) - middle_name = models.CharField(max_length=300, blank=True) - last_name = models.CharField(max_length=300, blank=True) + last_name = models.CharField( + max_length=300, + blank=True, + validators=[plain_text_validator], +) - institution = models.CharField(max_length=1000, blank=True) - department = models.CharField(max_length=300, blank=True) + institution = models.CharField( + max_length=1000, + blank=True, + validators=[plain_text_validator], +) + department = models.CharField( + max_length=300, + blank=True, + validators=[plain_text_validator], + ) frozen_biography = JanewayBleachField( blank=True, verbose_name=_('Frozen Biography'), From e55c46a8aa4077449c6cecbd13cd3f197ce48a74 Mon Sep 17 00:00:00 2001 From: Mauro MSL Date: Tue, 17 Sep 2024 19:39:46 +0100 Subject: [PATCH 5/8] #4405: Update validators on migrations --- ...096_alter_account_activation_code_and_more.py | 16 +++++++++------- .../0080_frozen_author_bleach_20240507_1350.py | 15 ++++++++------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/core/migrations/0096_alter_account_activation_code_and_more.py b/src/core/migrations/0096_alter_account_activation_code_and_more.py index d8281c00f..e9221a26f 100644 --- a/src/core/migrations/0096_alter_account_activation_code_and_more.py +++ b/src/core/migrations/0096_alter_account_activation_code_and_more.py @@ -3,6 +3,8 @@ import core.model_utils from django.db import migrations, models +import utils + class Migration(migrations.Migration): @@ -19,32 +21,32 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='account', name='department', - field=models.CharField(blank=True, max_length=300, verbose_name='Department'), + field=models.CharField(blank=True, max_length=300, verbose_name='Department', validators=[utils.forms.plain_text_validator]), ), migrations.AlterField( model_name='account', name='first_name', - field=models.CharField(max_length=300, verbose_name='First name'), + field=models.CharField(max_length=300, verbose_name='First name', validators=[utils.forms.plain_text_validator]), ), migrations.AlterField( model_name='account', name='institution', - field=models.CharField(blank=True, max_length=1000, verbose_name='Institution'), + field=models.CharField(blank=True, max_length=1000, verbose_name='Institution', validators=[utils.forms.plain_text_validator]), ), migrations.AlterField( model_name='account', name='last_name', - field=models.CharField(max_length=300, verbose_name='Last name'), + field=models.CharField(max_length=300, verbose_name='Last name', validators=[utils.forms.plain_text_validator]), ), migrations.AlterField( model_name='account', name='middle_name', - field=models.CharField(blank=True, max_length=300, verbose_name='Middle name'), + field=models.CharField(blank=True, max_length=300, verbose_name='Middle name', validators=[utils.forms.plain_text_validator]), ), migrations.AlterField( model_name='account', name='salutation', - field=models.CharField(blank=True, choices=[('Miss', 'Miss'), ('Ms', 'Ms'), ('Mrs', 'Mrs'), ('Mr', 'Mr'), ('Mx', 'Mx'), ('Dr', 'Dr'), ('Prof.', 'Prof.')], max_length=10, verbose_name='Salutation'), + field=models.CharField(blank=True, choices=[('Miss', 'Miss'), ('Ms', 'Ms'), ('Mrs', 'Mrs'), ('Mr', 'Mr'), ('Mx', 'Mx'), ('Dr', 'Dr'), ('Prof.', 'Prof.')], max_length=10, verbose_name='Salutation', validators=[utils.forms.plain_text_validator]), ), migrations.AlterField( model_name='account', @@ -54,6 +56,6 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='account', name='suffix', - field=models.CharField(blank=True, max_length=300, verbose_name='Name suffix'), + field=models.CharField(blank=True, max_length=300, verbose_name='Name suffix', validators=[utils.forms.plain_text_validator]), ), ] diff --git a/src/submission/migrations/0080_frozen_author_bleach_20240507_1350.py b/src/submission/migrations/0080_frozen_author_bleach_20240507_1350.py index 114c9153d..d49a0fb61 100644 --- a/src/submission/migrations/0080_frozen_author_bleach_20240507_1350.py +++ b/src/submission/migrations/0080_frozen_author_bleach_20240507_1350.py @@ -2,6 +2,7 @@ import core.model_utils from django.db import migrations, models +import utils.forms class Migration(migrations.Migration): @@ -15,12 +16,12 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='frozenauthor', name='department', - field=models.CharField(blank=True, max_length=300), + field=models.CharField(blank=True, max_length=300, validators=[utils.forms.plain_text_validator]), ), migrations.AlterField( model_name='frozenauthor', name='first_name', - field=models.CharField(blank=True, max_length=300), + field=models.CharField(blank=True, max_length=300, validators=[utils.forms.plain_text_validator]), ), migrations.AlterField( model_name='frozenauthor', @@ -40,26 +41,26 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='frozenauthor', name='institution', - field=models.CharField(blank=True, max_length=1000), + field=models.CharField(blank=True, max_length=1000, validators=[utils.forms.plain_text_validator]), ), migrations.AlterField( model_name='frozenauthor', name='last_name', - field=models.CharField(blank=True, max_length=300), + field=models.CharField(blank=True, max_length=300, validators=[utils.forms.plain_text_validator]), ), migrations.AlterField( model_name='frozenauthor', name='middle_name', - field=models.CharField(blank=True, max_length=300), + field=models.CharField(blank=True, max_length=300, validators=[utils.forms.plain_text_validator]), ), migrations.AlterField( model_name='frozenauthor', name='name_prefix', - field=models.CharField(blank=True, help_text='Optional name prefix (e.g: Prof or Dr)', max_length=300), + field=models.CharField(blank=True, help_text='Optional name prefix (e.g: Prof or Dr)', max_length=300, validators=[utils.forms.plain_text_validator]), ), migrations.AlterField( model_name='frozenauthor', name='name_suffix', - field=models.CharField(blank=True, help_text='Optional name suffix (e.g.: Jr or III)', max_length=300), + field=models.CharField(blank=True, help_text='Optional name suffix (e.g.: Jr or III)', max_length=300, validators=[utils.forms.plain_text_validator]), ), ] From df50c59fc87947b44a8ebf2981edeb56d22c9325 Mon Sep 17 00:00:00 2001 From: Mauro MSL Date: Tue, 17 Sep 2024 19:39:57 +0100 Subject: [PATCH 6/8] #4405: Adds unit tests --- src/utils/tests.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/utils/tests.py b/src/utils/tests.py index 64ab1153b..5ce3bc161 100644 --- a/src/utils/tests.py +++ b/src/utils/tests.py @@ -10,6 +10,7 @@ from django.test import TestCase, override_settings from django.utils import timezone, translation from django.core import mail +from django.core.exceptions import ValidationError from django.core.management import call_command from django.contrib.admin.sites import site from django.contrib.auth import get_user_model @@ -29,7 +30,11 @@ from utils import install from utils.transactional_emails import * -from utils.forms import FakeModelForm, KeywordModelForm +from utils.forms import ( + FakeModelForm, + KeywordModelForm, + plain_text_validator, +) from utils.logic import generate_sitemap from utils.testing import helpers from utils.shared import clear_cache @@ -792,6 +797,23 @@ class Meta: self.assertFalse(journal.keywords.exists()) +class TestPlainTextValidator(TestCase): + + def test_plain_text_validator_valid(self): + name_test = "Kathryn Janeway" + ampersand_test = "Voyager & co" + try: + plain_text_validator(name_test) + plain_text_validator(ampersand_test) + except ValidationError: + self.fail("Valid plain text input raised a ValidationError") + + def test_plain_text_validator_invalid(self): + rogue_input = 'Borg Queen' + with self.assertRaises(ValidationError): + plain_text_validator(rogue_input) + + class TestModels(TestCase): @classmethod From e633722dc7bfeca1a1457559fc36fb28717c86a9 Mon Sep 17 00:00:00 2001 From: Mauro MSL Date: Tue, 17 Sep 2024 19:40:13 +0100 Subject: [PATCH 7/8] 4405: Adds acceptance tests --- src/submission/tests.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/submission/tests.py b/src/submission/tests.py index 6b4f57a2e..d3e490d57 100644 --- a/src/submission/tests.py +++ b/src/submission/tests.py @@ -13,6 +13,7 @@ from django.utils import translation, timezone from django.urls.base import clear_script_prefix from django.conf import settings +from django.core.exceptions import ValidationError from django.shortcuts import reverse from django.test.utils import override_settings @@ -567,6 +568,33 @@ def test_author_form_with_good_orcid(self): '0000-0003-2126-266X', ) + def test_author_form_harmful_inputs(self): + harmful_string = ' This are not the droids you are looking for ' + for i, attr in enumerate({ + "first_name", + "last_name", + "middle_name", + "name_prefix", + "suffix", + "institution", + "department", + }): + form = forms.AuthorForm( + { + 'first_name': 'Andy', + 'last_name': 'Byers', + 'biography': 'Andy', + 'institution': 'Birkbeck, University of London', + 'email': f'andy{i}@janeway.systems', + 'orcid': 'https://orcid.org/0000-0003-2126-266X', + **{attr: harmful_string}, + } + ) + self.assertFalse( + form.is_valid(), + f"Harmful code injected into field '{attr}'" + ) + @override_settings(URL_CONFIG='domain') def test_article_encoding_bibtex(self): article = helpers.create_article( From f96434ac585263e1cc6927078b8a8374ee562c7a Mon Sep 17 00:00:00 2001 From: Andy Byers Date: Wed, 18 Sep 2024 11:53:23 +0100 Subject: [PATCH 8/8] Sets default class for orcid reg button. --- src/templates/common/elements/orcid_registration.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/common/elements/orcid_registration.html b/src/templates/common/elements/orcid_registration.html index ee1357699..f16882b26 100644 --- a/src/templates/common/elements/orcid_registration.html +++ b/src/templates/common/elements/orcid_registration.html @@ -11,7 +11,7 @@ {% else %} + class="{{ button_classes|default:"orcid-button" }}"> {% trans "Register with ORCiD" %} {% endif %}