Skip to content

Commit

Permalink
Perform validation of ext URL during form editing
Browse files Browse the repository at this point in the history
  • Loading branch information
jrief committed Jan 14, 2021
1 parent c9e8f4f commit 65d91e1
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 18 deletions.
15 changes: 15 additions & 0 deletions cmsplugin_cascade/admin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from urllib.parse import urlparse
import requests

from django.conf.urls import url
from django.contrib import admin
Expand Down Expand Up @@ -42,6 +43,7 @@ def get_urls(self):
url(r'^published_pages/$', self.get_published_pagelist, name='get_published_pagelist'),
url(r'^fetch_fonticons/(?P<iconfont_id>[0-9]+)$', self.fetch_fonticons),
url(r'^fetch_fonticons/$', self.fetch_fonticons, name='fetch_fonticons'),
url(r'^validate_exturl/$', self.validate_exturl, name='validate_exturl'),
]
urls.extend(super().get_urls())
return urls
Expand Down Expand Up @@ -111,6 +113,19 @@ def fetch_fonticons(self, request, iconfont_id=None):
data['families'] = icon_font.get_icon_families()
return JsonResponse(data)

def validate_exturl(self, request):
"""
Perform a GET request onto the given external URL and return its status.
"""
exturl = request.GET.get('exturl')
request_headers = {'User-Agent': 'Django-CMS-Cascade'}
try:
response = requests.get(exturl, allow_redirects=True, headers=request_headers)
except Exception:
return JsonResponse({'status_code': 500})
else:
return JsonResponse({'status_code': response.status_code})

def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
extra_context = dict(extra_context or {}, icon_fonts=IconFont.objects.all())
return super().changeform_view(
Expand Down
21 changes: 3 additions & 18 deletions cmsplugin_cascade/link/forms.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import requests
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.contrib.admin.sites import site as admin_site
from django.db.models.fields.related import ManyToOneRel
Expand All @@ -11,7 +10,8 @@

from cms.utils import get_current_site
from cms.models import Page
from entangled.forms import EntangledModelFormMixin, get_related_object
from entangled.forms import EntangledModelFormMixin
from entangled.utils import get_related_object
from filer.models.filemodels import File as FilerFileModel
from filer.fields.file import AdminFileWidget, FilerFileField

Expand Down Expand Up @@ -199,23 +199,8 @@ def _post_clean(self):
self.add_error('download_file', error)
elif link_type == 'exturl':
ext_url = self.cleaned_data['glossary'].get('ext_url', False)
if ext_url:
try:
request_headers = {'User-Agent': 'Django-CMS-Cascade'}
response = requests.head(ext_url, allow_redirects=True, headers=request_headers)
if response.status_code != 200:
error = ValidationError(
_("No external page found on {url}.").format(url=ext_url),
code='invalid',
)
except Exception as exc:
error = ValidationError(
_("Failed to connect to {url}.").format(url=ext_url),
code='invalid',
)
elif ext_url in empty_fields:
if ext_url in empty_fields:
error = ValidationError(_("No valid URL provided."), code='required')
if error:
self.add_error('ext_url', error)
elif link_type == 'email':
if self.cleaned_data['glossary'].get('mail_to', False) in empty_fields:
Expand Down
1 change: 1 addition & 0 deletions cmsplugin_cascade/link/plugin_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class LinkPluginBase(CascadePluginBase):
html_tag_attributes = {'title': 'title', 'target': 'target'}

class Media:
css = {'all': ['cascade/css/admin/linkplugin.css']}
js = ['admin/js/jquery.init.js', 'cascade/js/admin/linkplugin.js']

@classmethod
Expand Down
13 changes: 13 additions & 0 deletions cmsplugin_cascade/static/cascade/css/admin/linkplugin.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#id_ext_url {
background-position-x: calc(100% - 8px);
background-position-y: 50%;
background-clip: padding-box;
background-size: 24px;
background-repeat: no-repeat;
}
#id_ext_url.valid {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="green" width="16" height="16"><path fill-rule="evenodd" d="M10.97 4.97a.75.75 0 0 1 1.071 1.05l-3.992 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425a.236.236 0 0 1 .02-.022z"/></svg>') !important;
}
#id_ext_url.invalid {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" fill="darkorange" width="16" height="16"><path d="M7.938 2.016A.13.13 0 0 1 8.002 2a.13.13 0 0 1 .063.016.146.146 0 0 1 .054.057l6.857 11.667c.036.06.035.124.002.183a.163.163 0 0 1-.054.06.116.116 0 0 1-.066.017H1.146a.115.115 0 0 1-.066-.017.163.163 0 0 1-.054-.06.176.176 0 0 1 .002-.183L7.884 2.073a.147.147 0 0 1 .054-.057zm1.044-.45a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566z"/><path d="M7.002 12a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 5.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995z"/></svg>');
}
16 changes: 16 additions & 0 deletions cmsplugin_cascade/static/cascade/js/admin/linkplugin.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
django.jQuery(function($) {
'use strict';
var $link_type = $("#id_link_type"), $cmspage_select = $("#id_cms_page");
var $link_ext_url = $('#id_ext_url');
var $link_target = $(".form-row.field-link_target");
var $link_title = $(".form-row.field-link_title");

Expand Down Expand Up @@ -34,6 +35,9 @@ django.jQuery(function($) {
$cmspage_select.change(function(evt) {
self.toggleCMSPage(evt.target.value);
});
$link_ext_url.on('blur', function(evt) {
self.validateExtUrl(evt.target.value);
});
this.refreshChangeForm();
},
initializeLinkTypes: function() {
Expand Down Expand Up @@ -73,8 +77,20 @@ django.jQuery(function($) {
$selSection.val(null);
});
},
validateExtUrl: function(exturl) {
$.get(django.cascade.validate_exturl_url, {
exturl: exturl,
}, function(response) {
if (response.status_code === 200) {
$link_ext_url.addClass('valid').removeClass('invalid');
} else {
$link_ext_url.addClass('invalid').removeClass('valid');
}
});
},
refreshChangeForm: function() {
this.toggleLinkTypes($link_type.val());
this.validateExtUrl($link_ext_url.val());
this.$super && this.$super();
}
});
Expand Down
1 change: 1 addition & 0 deletions cmsplugin_cascade/templates/cascade/admin/change_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ <h2>{% trans "There are no further settings for this plugin" %}</h2>
'{{ icof.id }}': '{{ icof.get_stylesheet_url }}'{% if not forloop.last %},{% endif %}{% endfor %}
};
django.cascade.fetch_fonticons_url = "{% url 'admin:fetch_fonticons' %}";
django.cascade.validate_exturl_url = "{% url 'admin:validate_exturl' %}";
{% endif %}
</script>
{% endblock %}

0 comments on commit 65d91e1

Please sign in to comment.