', self.full_name],
+ u'Full Name cannot contain the following characters: < >',
+ False
)
def test_email_field(self):
diff --git a/openedx/core/djangoapps/user_api/accounts/api.py b/openedx/core/djangoapps/user_api/accounts/api.py
index 1bda1ee67d..9043af0ac9 100644
--- a/openedx/core/djangoapps/user_api/accounts/api.py
+++ b/openedx/core/djangoapps/user_api/accounts/api.py
@@ -2,10 +2,12 @@
"""
Programmatic integration point for User API Accounts sub-application
"""
-from django.utils.translation import override as override_language, ugettext as _
-from django.db import transaction, IntegrityError
+import re
import datetime
from pytz import UTC
+
+from django.utils.translation import override as override_language, ugettext as _
+from django.db import transaction, IntegrityError
from django.core.exceptions import ObjectDoesNotExist
from django.conf import settings
from django.core.validators import validate_email, ValidationError
@@ -133,8 +135,10 @@ def update_account_settings(requesting_user, update, username=None):
# If user has requested to change name, store old name because we must update associated metadata
# after the save process is complete.
+ changing_full_name = False
old_name = None
if "name" in update:
+ changing_full_name = True
old_name = existing_user_profile.name
# Check for fields that are not editable. Marking them read-only causes them to be ignored, but we wish to 400.
@@ -169,6 +173,12 @@ def update_account_settings(requesting_user, update, username=None):
"user_message": err.message
}
+ if changing_full_name and contains_html(update['name']):
+ field_errors["name"] = {
+ "developer_message": u"Error thrown from validate_full_name: '{}'".format('Full Name is in-valid'),
+ "user_message": _(u"Full Name cannot contain the following characters: < >")
+ }
+
# If we have encountered any validation errors, return them to the user.
if field_errors:
raise errors.AccountValidationError(field_errors)
@@ -514,6 +524,14 @@ def _get_user_and_profile(username):
return existing_user, existing_user_profile
+def contains_html(value):
+ """
+ Validator method to check whether name contains html tags
+ """
+ regex = re.compile('(<|>)', re.UNICODE)
+ return bool(regex.search(value))
+
+
def _validate(validation_func, err, *args):
"""Generic validation function that returns default on
no errors, but the message associated with the err class
diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_api.py b/openedx/core/djangoapps/user_api/accounts/tests/test_api.py
index d3157642d3..4e79f7f80c 100644
--- a/openedx/core/djangoapps/user_api/accounts/tests/test_api.py
+++ b/openedx/core/djangoapps/user_api/accounts/tests/test_api.py
@@ -179,22 +179,25 @@ class TestAccountApi(UserSettingsEventTestMixin, TestCase):
def test_update_multiple_validation_errors(self):
"""Test that all validation errors are built up and returned at once"""
# Send a read-only error, serializer error, and email validation error.
+
naughty_update = {
"username": "not_allowed",
"gender": "undecided",
- "email": "not an email address"
+ "email": "not an email address",
+ "name": "
NameContent spoof"
}
with self.assertRaises(AccountValidationError) as context_manager:
update_account_settings(self.user, naughty_update)
field_errors = context_manager.exception.field_errors
- self.assertEqual(3, len(field_errors))
+ self.assertEqual(4, len(field_errors))
self.assertEqual("This field is not editable via this API", field_errors["username"]["developer_message"])
self.assertIn(
"Value \'undecided\' is not valid for field \'gender\'",
field_errors["gender"]["developer_message"]
)
self.assertIn("Valid e-mail address required.", field_errors["email"]["developer_message"])
+ self.assertIn("Full Name cannot contain the following characters: < >", field_errors["name"]["user_message"])
@patch('django.core.mail.send_mail')
@patch('student.views.render_to_string', Mock(side_effect=mock_render_to_string, autospec=True))