Fix badges for tags containing special characters. Fixes #240, #237

This commit is contained in:
Pēteris Caune 2019-05-14 14:43:43 +03:00
parent dd9fbc9e8c
commit b528b23996
No known key found for this signature in database
GPG Key ID: E28D7679E9A9EDE2
6 changed files with 47 additions and 9 deletions

View File

@ -6,6 +6,10 @@ All notable changes to this project will be documented in this file.
### Improvements ### Improvements
- Add the `prunetokenbucket` management command - Add the `prunetokenbucket` management command
### Bug Fixes
- Fix badges for tags containing special characters (#240, #237)
## 1.7.0 - 2019-05-02 ## 1.7.0 - 2019-05-02
### Improvements ### Improvements

View File

@ -60,3 +60,14 @@ class BadgeTestCase(BaseTestCase):
r = self.client.get(self.json_url) r = self.client.get(self.json_url)
self.assertContains(r, "late") self.assertContains(r, "late")
def test_it_handles_special_characters(self):
self.check.tags = "db@dc1"
self.check.save()
sig = base64_hmac(str(self.project.badge_key), "db@dc1", settings.SECRET_KEY)
sig = sig[:8]
url = "/badge/%s/%s/db%%2540dc1.svg" % (self.project.badge_key, sig)
r = self.client.get(url)
self.assertEqual(r.status_code, 200)

View File

@ -1,7 +1,21 @@
from django.urls import path from urllib.parse import quote, unquote
from django.urls import path, register_converter
from hc.api import views from hc.api import views
class QuoteConverter:
regex = '[\w%~_.-]+'
def to_python(self, value):
return unquote(value)
def to_url(self, value):
return quote(value, safe="")
register_converter(QuoteConverter, 'quoted')
urlpatterns = [ urlpatterns = [
path('ping/<uuid:code>/', views.ping, name="hc-ping-slash"), path('ping/<uuid:code>/', views.ping, name="hc-ping-slash"),
path('ping/<uuid:code>', views.ping, name="hc-ping"), path('ping/<uuid:code>', views.ping, name="hc-ping"),
@ -17,13 +31,13 @@ urlpatterns = [
path('api/v1/channels/', views.channels), path('api/v1/channels/', views.channels),
path('badge/<slug:badge_key>/<slug:signature>/<slug:tag>.svg', views.badge, path('badge/<slug:badge_key>/<slug:signature>/<quoted:tag>.svg', views.badge,
name="hc-badge"), name="hc-badge"),
path('badge/<slug:badge_key>/<slug:signature>.svg', views.badge, path('badge/<slug:badge_key>/<slug:signature>.svg', views.badge,
{"tag": "*"}, name="hc-badge-all"), {"tag": "*"}, name="hc-badge-all"),
path('badge/<slug:badge_key>/<slug:signature>/<slug:tag>.json', views.badge, path('badge/<slug:badge_key>/<slug:signature>/<quoted:tag>.json', views.badge,
{"format": "json"}, name="hc-badge-json"), {"format": "json"}, name="hc-badge-json"),
path('badge/<slug:badge_key>/<slug:signature>.json', views.badge, path('badge/<slug:badge_key>/<slug:signature>.json', views.badge,

View File

@ -4,12 +4,17 @@ from hc.api.models import Check
class BadgesTestCase(BaseTestCase): class BadgesTestCase(BaseTestCase):
def setUp(self):
super(BadgesTestCase, self).setUp()
self.url = "/projects/%s/badges/" % self.project.code
def test_it_shows_badges(self): def test_it_shows_badges(self):
Check.objects.create(project=self.project, tags="foo a-B_1 baz@") Check.objects.create(project=self.project, tags="foo a-B_1 baz@")
Check.objects.create(project=self.bobs_project, tags="bobs-tag") Check.objects.create(project=self.bobs_project, tags="bobs-tag")
self.client.login(username="alice@example.org", password="password") self.client.login(username="alice@example.org", password="password")
r = self.client.get("/projects/%s/badges/" % self.project.code) r = self.client.get(self.url)
self.assertContains(r, "foo.svg") self.assertContains(r, "foo.svg")
self.assertContains(r, "a-B_1.svg") self.assertContains(r, "a-B_1.svg")
@ -27,6 +32,13 @@ class BadgesTestCase(BaseTestCase):
self.project.save() self.project.save()
self.client.login(username="alice@example.org", password="password") self.client.login(username="alice@example.org", password="password")
r = self.client.get("/projects/%s/badges/" % self.project.code) r = self.client.get(self.url)
self.assertContains(r, "badge/alices-badge-key/") self.assertContains(r, "badge/alices-badge-key/")
self.assertContains(r, "badge/alices-badge-key/") self.assertContains(r, "badge/alices-badge-key/")
def test_it_handles_special_characers_in_tags(self):
Check.objects.create(project=self.project, tags="db@dc1")
self.client.login(username="alice@example.org", password="password")
r = self.client.get(self.url)
self.assertContains(r, "db%2540dc1.svg")

View File

@ -528,9 +528,6 @@ def badges(request, code):
urls = [] urls = []
for tag in sorted_tags: for tag in sorted_tags:
if not re.match("^[\w-]+$", tag) and tag != "*":
continue
urls.append({ urls.append({
"tag": tag, "tag": tag,
"svg": get_badge_url(project.badge_key, tag), "svg": get_badge_url(project.badge_key, tag),

View File

@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load compress static hc_extras %} {% load compress static hc_extras %}
{% block title %}Account Settings - {% site_name %}{% endblock %} {% block title %}Status Badges - {% site_name %}{% endblock %}
{% block content %} {% block content %}
<div class="row"> <div class="row">