Add option for disabled bookmark URL validation (#36)
This commit is contained in:
parent
0f231bcd9f
commit
c28c80fd4c
19
bookmarks/migrations/0005_auto_20210103_1212.py
Normal file
19
bookmarks/migrations/0005_auto_20210103_1212.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 2.2.13 on 2021-01-03 12:12
|
||||||
|
|
||||||
|
import bookmarks.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('bookmarks', '0004_auto_20200926_1028'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='bookmark',
|
||||||
|
name='url',
|
||||||
|
field=models.CharField(max_length=2048, validators=[bookmarks.validators.BookmarkURLValidator()]),
|
||||||
|
),
|
||||||
|
]
|
@ -5,6 +5,7 @@ from django.contrib.auth import get_user_model
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from bookmarks.utils import unique
|
from bookmarks.utils import unique
|
||||||
|
from bookmarks.validators import BookmarkURLValidator
|
||||||
|
|
||||||
|
|
||||||
class Tag(models.Model):
|
class Tag(models.Model):
|
||||||
@ -32,7 +33,7 @@ def build_tag_string(tag_names: List[str], delimiter: str = ','):
|
|||||||
|
|
||||||
|
|
||||||
class Bookmark(models.Model):
|
class Bookmark(models.Model):
|
||||||
url = models.URLField(max_length=2048)
|
url = models.CharField(max_length=2048, validators=[BookmarkURLValidator()])
|
||||||
title = models.CharField(max_length=512, blank=True)
|
title = models.CharField(max_length=512, blank=True)
|
||||||
description = models.TextField(blank=True)
|
description = models.TextField(blank=True)
|
||||||
website_title = models.CharField(max_length=512, blank=True, null=True)
|
website_title = models.CharField(max_length=512, blank=True, null=True)
|
||||||
@ -71,7 +72,7 @@ class Bookmark(models.Model):
|
|||||||
|
|
||||||
class BookmarkForm(forms.ModelForm):
|
class BookmarkForm(forms.ModelForm):
|
||||||
# Use URLField for URL
|
# Use URLField for URL
|
||||||
url = forms.URLField()
|
url = forms.CharField(validators=[BookmarkURLValidator()])
|
||||||
tag_string = forms.CharField(required=False)
|
tag_string = forms.CharField(required=False)
|
||||||
# Do not require title and description in form as we fill these automatically if they are empty
|
# Do not require title and description in form as we fill these automatically if they are empty
|
||||||
title = forms.CharField(max_length=512,
|
title = forms.CharField(max_length=512,
|
||||||
|
90
bookmarks/tests/test_bookmark_validation.py
Normal file
90
bookmarks/tests/test_bookmark_validation.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.test import TestCase, override_settings
|
||||||
|
|
||||||
|
from bookmarks.models import BookmarkForm, Bookmark
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
ENABLED_URL_VALIDATION_TEST_CASES = [
|
||||||
|
('thisisnotavalidurl', False),
|
||||||
|
('http://domain', False),
|
||||||
|
('unknownscheme://domain.com', False),
|
||||||
|
('http://domain.com', True),
|
||||||
|
('http://www.domain.com', True),
|
||||||
|
('https://domain.com', True),
|
||||||
|
('https://www.domain.com', True),
|
||||||
|
]
|
||||||
|
|
||||||
|
DISABLED_URL_VALIDATION_TEST_CASES = [
|
||||||
|
('thisisnotavalidurl', True),
|
||||||
|
('http://domain', True),
|
||||||
|
('unknownscheme://domain.com', True),
|
||||||
|
('http://domain.com', True),
|
||||||
|
('http://www.domain.com', True),
|
||||||
|
('https://domain.com', True),
|
||||||
|
('https://www.domain.com', True),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class BookmarkValidationTestCase(TestCase):
|
||||||
|
|
||||||
|
def setUp(self) -> None:
|
||||||
|
self.user = User.objects.create_user('testuser', 'test@example.com', 'password123')
|
||||||
|
|
||||||
|
@override_settings(LD_DISABLE_URL_VALIDATION=False)
|
||||||
|
def test_bookmark_model_should_validate_url_if_not_disabled_in_settings(self):
|
||||||
|
self._run_bookmark_model_url_validity_checks(ENABLED_URL_VALIDATION_TEST_CASES)
|
||||||
|
|
||||||
|
@override_settings(LD_DISABLE_URL_VALIDATION=True)
|
||||||
|
def test_bookmark_model_should_not_validate_url_if_disabled_in_settings(self):
|
||||||
|
self._run_bookmark_model_url_validity_checks(DISABLED_URL_VALIDATION_TEST_CASES)
|
||||||
|
|
||||||
|
def test_bookmark_form_should_validate_required_fields(self):
|
||||||
|
form = BookmarkForm(data={'url': ''})
|
||||||
|
|
||||||
|
self.assertEqual(len(form.errors), 1)
|
||||||
|
self.assertIn('required', str(form.errors))
|
||||||
|
|
||||||
|
form = BookmarkForm(data={'url': None})
|
||||||
|
|
||||||
|
self.assertEqual(len(form.errors), 1)
|
||||||
|
self.assertIn('required', str(form.errors))
|
||||||
|
|
||||||
|
@override_settings(LD_DISABLE_URL_VALIDATION=False)
|
||||||
|
def test_bookmark_form_should_validate_url_if_not_disabled_in_settings(self):
|
||||||
|
self._run_bookmark_form_url_validity_checks(ENABLED_URL_VALIDATION_TEST_CASES)
|
||||||
|
|
||||||
|
@override_settings(LD_DISABLE_URL_VALIDATION=True)
|
||||||
|
def test_bookmark_form_should_not_validate_url_if_disabled_in_settings(self):
|
||||||
|
self._run_bookmark_form_url_validity_checks(DISABLED_URL_VALIDATION_TEST_CASES)
|
||||||
|
|
||||||
|
def _run_bookmark_model_url_validity_checks(self, cases):
|
||||||
|
for case in cases:
|
||||||
|
url, expectation = case
|
||||||
|
bookmark = Bookmark(
|
||||||
|
url=url,
|
||||||
|
date_added=datetime.datetime.now(),
|
||||||
|
date_modified=datetime.datetime.now(),
|
||||||
|
owner=self.user
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
bookmark.full_clean()
|
||||||
|
self.assertTrue(expectation, 'Did not expect validation error')
|
||||||
|
except ValidationError as e:
|
||||||
|
self.assertFalse(expectation, 'Expected validation error')
|
||||||
|
self.assertTrue('url' in e.message_dict, 'Expected URL validation to fail')
|
||||||
|
|
||||||
|
def _run_bookmark_form_url_validity_checks(self, cases):
|
||||||
|
for case in cases:
|
||||||
|
url, expectation = case
|
||||||
|
form = BookmarkForm(data={'url': url})
|
||||||
|
|
||||||
|
if expectation:
|
||||||
|
self.assertEqual(len(form.errors), 0)
|
||||||
|
else:
|
||||||
|
self.assertEqual(len(form.errors), 1)
|
||||||
|
self.assertIn('Enter a valid URL', str(form.errors))
|
14
bookmarks/validators.py
Normal file
14
bookmarks/validators.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from django.conf import settings
|
||||||
|
from django.core import validators
|
||||||
|
|
||||||
|
|
||||||
|
class BookmarkURLValidator(validators.URLValidator):
|
||||||
|
"""
|
||||||
|
Extends default Django URLValidator and cancels validation if it is disabled in settings.
|
||||||
|
This allows to switch URL validation on/off dynamically which helps with testing
|
||||||
|
"""
|
||||||
|
def __call__(self, value):
|
||||||
|
if settings.LD_DISABLE_URL_VALIDATION:
|
||||||
|
return
|
||||||
|
|
||||||
|
super().__call__(value)
|
@ -157,3 +157,6 @@ REST_FRAMEWORK = {
|
|||||||
|
|
||||||
# Registration switch
|
# Registration switch
|
||||||
ALLOW_REGISTRATION = False
|
ALLOW_REGISTRATION = False
|
||||||
|
|
||||||
|
# URL validation flag
|
||||||
|
LD_DISABLE_URL_VALIDATION = os.getenv('LD_DISABLE_URL_VALIDATION', False) in (True, 'True', '1')
|
||||||
|
Loading…
Reference in New Issue
Block a user