general: add support for substitution variables in URLs (#14622)
This commit is contained in:
parent
fe831e5d68
commit
e7915bd406
|
@ -87,7 +87,7 @@ def get_page_dict(request, page, manifest):
|
|||
|
||||
if page.redirect_url:
|
||||
page_dict['external'] = True
|
||||
page_dict['url'] = page.redirect_url
|
||||
page_dict['url'] = page.get_redirect_url()
|
||||
|
||||
if icon_cells:
|
||||
page_dict['icon'] = icon_cells[0].icon
|
||||
|
|
|
@ -29,7 +29,7 @@ from django.utils.http import urlencode
|
|||
|
||||
from combo.data.models import CellBase
|
||||
from combo.data.library import register_cell_class
|
||||
from combo.utils import sign_url
|
||||
from combo.utils import sign_url, get_templated_url
|
||||
|
||||
from .forms import NewslettersManageForm
|
||||
|
||||
|
@ -120,8 +120,9 @@ class NewslettersCell(CellBase):
|
|||
return filtered
|
||||
|
||||
def get_newsletters(self, **kwargs):
|
||||
endpoint = self.url + 'newsletters/'
|
||||
url = get_signed_url(endpoint, self.url, **kwargs)
|
||||
url = get_templated_url(self.url)
|
||||
endpoint = url + 'newsletters/'
|
||||
url = get_signed_url(endpoint, url, **kwargs)
|
||||
response = requests.get(url)
|
||||
if response.ok:
|
||||
json_response = response.json()
|
||||
|
@ -129,8 +130,9 @@ class NewslettersCell(CellBase):
|
|||
return []
|
||||
|
||||
def get_subscriptions(self, **kwargs):
|
||||
endpoint = self.url + 'subscriptions/'
|
||||
url = get_signed_url(endpoint, self.url, **kwargs)
|
||||
url = get_templated_url(self.url)
|
||||
endpoint = url + 'subscriptions/'
|
||||
url = get_signed_url(endpoint, url, **kwargs)
|
||||
response = requests.get(url)
|
||||
if response.ok:
|
||||
json_response = response.json()
|
||||
|
@ -140,9 +142,10 @@ class NewslettersCell(CellBase):
|
|||
def set_subscriptions(self, subscriptions, **kwargs):
|
||||
logger = logging.getLogger(__name__)
|
||||
headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
|
||||
url = get_templated_url(self.url)
|
||||
try:
|
||||
endpoint = self.url + 'subscriptions/'
|
||||
url = get_signed_url(endpoint, self.url, **kwargs)
|
||||
endpoint = url + 'subscriptions/'
|
||||
url = get_signed_url(endpoint, url, **kwargs)
|
||||
response = requests.post(url, data=json.dumps(subscriptions),
|
||||
headers=headers)
|
||||
if not response.json()['data']:
|
||||
|
|
|
@ -258,6 +258,9 @@ class Page(models.Model):
|
|||
ordered_pages = Page.get_as_reordered_flat_hierarchy(cls.objects.all())
|
||||
return [x.get_serialized_page() for x in ordered_pages]
|
||||
|
||||
def get_redirect_url(self):
|
||||
return utils.get_templated_url(self.redirect_url)
|
||||
|
||||
|
||||
class CellMeta(MediaDefiningClass, ModelBase):
|
||||
pass
|
||||
|
@ -605,7 +608,7 @@ class LinkCell(CellBase):
|
|||
context['url'] = self.link_page.get_online_url()
|
||||
context['title'] = self.title or self.link_page.title
|
||||
else:
|
||||
context['url'] = self.url
|
||||
context['url'] = utils.get_templated_url(self.url)
|
||||
context['title'] = self.title or self.url
|
||||
if self.anchor:
|
||||
context['url'] += '#' + self.anchor
|
||||
|
@ -632,7 +635,7 @@ class FeedCell(CellBase):
|
|||
cache_key = hashlib.md5(self.url).hexdigest()
|
||||
feed_content = cache.get(cache_key)
|
||||
if not feed_content:
|
||||
feed_response = requests.get(self.url)
|
||||
feed_response = requests.get(utils.get_templated_url(self.url))
|
||||
if feed_response.status_code == 200:
|
||||
feed_content = feed_response.content
|
||||
cache.set(cache_key, feed_content, 600)
|
||||
|
@ -737,7 +740,7 @@ class ParametersCell(CellBase):
|
|||
if hasattr(self, '_form'):
|
||||
ctx['form'] = self._form
|
||||
ctx['title'] = self.title
|
||||
ctx['url'] = self.url
|
||||
ctx['url'] = utils.get_templated_url(self.url)
|
||||
return ctx
|
||||
|
||||
def get_default_form_class(self):
|
||||
|
|
|
@ -44,6 +44,7 @@ else:
|
|||
get_idps = lambda: []
|
||||
|
||||
from combo.data.models import CellBase, Page, ParentContentCell, TextCell
|
||||
from combo import utils
|
||||
|
||||
|
||||
def login(request, *args, **kwargs):
|
||||
|
@ -147,15 +148,17 @@ def skeleton(request):
|
|||
# look in redirect pages after the best match for the source
|
||||
redirect_pages = Page.objects.exclude(redirect_url__isnull=True).exclude(redirect_url='')
|
||||
for page in redirect_pages:
|
||||
if source.startswith(page.redirect_url):
|
||||
if selected_page is None or len(page.redirect_url) > len(selected_page.redirect_url):
|
||||
redirect_url = utils.get_templated_url(page.redirect_url)
|
||||
if source.startswith(redirect_url):
|
||||
if selected_page is None or len(redirect_url) > len(selected_page.get_redirect_url()):
|
||||
selected_page = page
|
||||
|
||||
if selected_page is None:
|
||||
# if there was no page found, look for a domain match
|
||||
netloc = urlparse.urlparse(source).netloc
|
||||
for page in redirect_pages:
|
||||
if urlparse.urlparse(page.redirect_url).netloc == netloc:
|
||||
redirect_url = utils.get_templated_url(page.redirect_url)
|
||||
if urlparse.urlparse(redirect_url).netloc == netloc:
|
||||
selected_page = page
|
||||
break
|
||||
|
||||
|
@ -289,7 +292,7 @@ def publish_page(request, page, status=200, template_name=None):
|
|||
raise PermissionDenied()
|
||||
|
||||
if page.redirect_url:
|
||||
return HttpResponseRedirect(page.redirect_url)
|
||||
return HttpResponseRedirect(page.get_redirect_url())
|
||||
|
||||
cells = CellBase.get_cells(page_id=page.id)
|
||||
extend_with_parent_cells(cells)
|
||||
|
|
|
@ -19,6 +19,7 @@ import base64
|
|||
import hmac
|
||||
import hashlib
|
||||
import binascii
|
||||
import re
|
||||
|
||||
from HTMLParser import HTMLParser
|
||||
import logging
|
||||
|
@ -169,6 +170,16 @@ class Requests(RequestsSession):
|
|||
|
||||
requests = Requests()
|
||||
|
||||
|
||||
def get_templated_url(url):
|
||||
template_vars = settings.TEMPLATE_VARS
|
||||
def repl(matchobj):
|
||||
if matchobj.group(0)[1:-1] in template_vars:
|
||||
return template_vars[matchobj.group(0)[1:-1]]
|
||||
return matchobj.group(0)
|
||||
return re.sub(r'(\[.*?\])', repl, url)
|
||||
|
||||
|
||||
# Simple signature scheme for query strings
|
||||
|
||||
def sign_url(url, key, algo='sha256', timestamp=None, nonce=None):
|
||||
|
|
|
@ -4,6 +4,8 @@ import pytest
|
|||
import urllib
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.test import override_settings
|
||||
|
||||
from combo.wsgi import application
|
||||
from combo.data.models import Page, CellBase, TextCell, ParentContentCell, FeedCell
|
||||
|
||||
|
@ -75,6 +77,15 @@ def test_page_redirect(app):
|
|||
resp = app.get('/elsewhere/', status=302)
|
||||
assert resp.location == 'http://example.net'
|
||||
|
||||
def test_page_templated_redirect(app):
|
||||
Page.objects.all().delete()
|
||||
with override_settings(TEMPLATE_VARS={'test_url': 'http://example.net'}):
|
||||
page = Page(title='Elsewhere', slug='elsewhere', template_name='standard',
|
||||
redirect_url='[test_url]')
|
||||
page.save()
|
||||
resp = app.get('/elsewhere/', status=302)
|
||||
assert resp.location == 'http://example.net'
|
||||
|
||||
def test_page_private_unlogged(app):
|
||||
Page.objects.all().delete()
|
||||
page = Page(title='Home', slug='index', template_name='standard', public=False)
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
from combo.utils import aes_hex_decrypt, aes_hex_encrypt
|
||||
from combo.utils import aes_hex_decrypt, aes_hex_encrypt, get_templated_url
|
||||
from django.conf import settings
|
||||
from django.test import override_settings
|
||||
|
||||
|
||||
def test_crypto_url():
|
||||
invoice_id = '12-1234'
|
||||
key = settings.SECRET_KEY
|
||||
assert aes_hex_decrypt(key, aes_hex_encrypt(key, invoice_id)) == invoice_id
|
||||
assert aes_hex_decrypt(key, aes_hex_encrypt(key, invoice_id)) == invoice_id
|
||||
|
||||
|
||||
def test_templated_url():
|
||||
assert get_templated_url('[test_url]') == '[test_url]'
|
||||
with override_settings(TEMPLATE_VARS={'test_url': 'http://www.example.net'}):
|
||||
assert get_templated_url('[test_url]') == 'http://www.example.net'
|
||||
assert get_templated_url('[test_url]/hello') == 'http://www.example.net/hello'
|
||||
|
|
Loading…
Reference in New Issue