Projet

Général

Profil

0001-pwa-allow-absolute-redirection-url-from-internal-pag.patch

Nicolas Roche, 16 septembre 2021 17:44

Télécharger (6,79 ko)

Voir les différences:

Subject: [PATCH] pwa: allow absolute redirection url from internal page
 (#56974)

 combo/apps/pwa/models.py                      | 10 ++++-
 .../pwa/templates/combo/pwa/navigation.html   |  4 +-
 tests/test_pwa.py                             | 41 +++++++++++++++++++
 3 files changed, 51 insertions(+), 4 deletions(-)
combo/apps/pwa/models.py
13 13
# GNU Affero General Public License for more details.
14 14
#
15 15
# You should have received a copy of the GNU Affero General Public License
16 16
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 17

  
18 18
import base64
19 19
import json
20 20
import os
21
import urllib.parse
21 22

  
22 23
from django.conf import settings
23 24
from django.contrib.postgres.fields import JSONField
24 25
from django.core import serializers
25 26
from django.core.files.base import ContentFile
26 27
from django.core.files.storage import default_storage
27 28
from django.db import models
28 29
from django.utils.encoding import force_bytes, force_text
29 30
from django.utils.translation import ugettext_lazy as _
30 31
from py_vapid import Vapid
31 32

  
32 33
from combo import utils
33 34
from combo.data.fields import RichTextField
35
from combo.middleware import get_request
34 36

  
35 37

  
36 38
class PwaSettings(models.Model):
37 39
    APPLICATION_ICON_SIZES = ['%sx%s' % (x, x) for x in (48, 96, 192, 256, 512)]
38 40
    application_name = models.CharField(verbose_name=_('Application Name'), max_length=64, blank=True)
39 41
    application_icon = models.FileField(
40 42
        verbose_name=_('Application Icon'),
41 43
        help_text=_(
......
132 134
    class Meta:
133 135
        ordering = ('order',)
134 136

  
135 137
    def get_label(self):
136 138
        return self.label or self.link_page.title
137 139

  
138 140
    def get_url(self):
139 141
        if self.link_page:
140
            return self.link_page.get_online_url()
142
            url = self.link_page.get_online_url()
141 143
        else:
142
            return utils.get_templated_url(self.url)
144
            url = utils.get_templated_url(self.url)
145
        if not urllib.parse.urlparse(url).netloc and get_request():
146
            site_base = get_request().build_absolute_uri()
147
            url = site_base + url.lstrip('/')
148
        return url
143 149

  
144 150
    def css_class_names(self):
145 151
        css_class_names = self.extra_css_class or ''
146 152
        if self.link_page:
147 153
            css_class_names += ' page-%s' % self.link_page.slug
148 154
        return css_class_names
149 155

  
150 156
    @classmethod
combo/apps/pwa/templates/combo/pwa/navigation.html
2 2
<div class="pwa-navigation" id="pwa-navigation"
3 3
  {% if include_user_name %}data-pwa-user-name="{% skeleton_extra_placeholder user-name %}{{user.get_full_name}}{% end_skeleton_extra_placeholder %}"{% endif %}>
4 4
<div>
5 5
<ul>
6 6
  {% for entry in entries %}
7 7
  <li class="{{ entry.css_class_names }}{% if entry.link_page in page.get_parents_and_self  %} selected{% endif %}" data-entry-pk="{{ entry.pk }}"
8 8
      {% if entry.notification_count %}data-notification-count-url="{{site_base}}/api/notification/count/"{% endif %}
9 9
      {% if entry.use_user_name_as_label %}data-include-user-name{% endif %}>
10
      <a href="{% if entry.link_page_id %}{{ site_base }}{% endif %}{{ entry.get_url }}"
10
      <a href="{{ entry.get_url }}"
11 11
         {% if entry.icon %}style="background-image: url({{site_base}}{{entry.icon.url}});"{% endif %}
12 12
         ><span>{{ entry.get_label }}</span></a></li>
13 13
  {% endfor %}
14 14
</ul>
15 15
</div>
16 16
</div>
17 17
<script>
18 18
$('li[data-include-user-name]').each(function(idx, elem) {
......
31 31
    crossDomain: true,
32 32
    success: function(data) {
33 33
      if (data.new) {
34 34
        $entry.find('span').append(' <span class="badge">' + data.new + '</span>');
35 35
      }
36 36
  }});
37 37
});
38 38
</script>
39
{% endif %}
39
{% endif %}
tests/test_pwa.py
1 1
import base64
2
from html.parser import HTMLParser
2 3
from unittest import mock
3 4

  
4 5
import pytest
5 6
from django.conf import settings
6 7
from django.core.files import File
7 8
from django.template import Context, Template
8 9
from django.test import override_settings
9 10
from django.test.client import RequestFactory
......
248 249
        assert nav.count('background-image') == 1
249 250
        assert nav.count('data-notification-count-url=') == 1
250 251
        assert nav.count('data-pwa-user-name=""') == 1
251 252

  
252 253
        nav = t.render(Context({'request': request, 'render_skeleton': True}))
253 254
        assert 'data-pwa-user-name="{% block placeholder-user-name %}' in nav
254 255

  
255 256

  
257
def test_pwa_navigation_templatetag_internal_redirection(app):
258
    page1 = Page(title='One', slug='one')
259
    page2 = Page(title='Two', slug='two', redirect_url='http://www.example.org/test')
260
    page3 = Page(title='Three', slug='three', redirect_url='../test')
261
    page4 = Page(title='Four', slug='four', redirect_url='{{test_url}}plop')
262
    page1.save()
263
    page2.save()
264
    page3.save()
265
    page4.save()
266
    entry1 = PwaNavigationEntry(link_page=page1, order=1)
267
    entry2 = PwaNavigationEntry(link_page=page2, order=2)
268
    entry3 = PwaNavigationEntry(link_page=page3, order=3)
269
    entry4 = PwaNavigationEntry(link_page=page4, order=4)
270
    entry1.save()
271
    entry2.save()
272
    entry3.save()
273
    entry4.save()
274
    t = Template('{% load pwa %}{% pwa_navigation %}')
275

  
276
    with override_settings(TEMPLATE_VARS={'pwa_display': 'standalone'}):
277
        request = RequestFactory().get('/')
278
        with mock.patch('combo.apps.pwa.models.get_request', return_value=request):
279
            nav = t.render(Context({'request': request}))
280

  
281
    class MyHTMLParser(HTMLParser):
282
        def handle_starttag(self, tag, attrs):
283
            if tag == 'a':
284
                results.append(attrs[0][1])
285

  
286
    parser = MyHTMLParser()
287
    results = []
288
    parser.feed(nav)
289
    assert results == [
290
        'http://testserver/one/',
291
        'http://www.example.org/test',
292
        'http://testserver/three/',
293
        'http://testserver/four/',
294
    ]
295

  
296

  
256 297
def test_pwa_application_icon(app, admin_user):
257 298
    app = login(app)
258 299
    with override_settings(TEMPLATE_VARS={'pwa_display': 'standalone'}):
259 300
        PwaSettings.objects.all().delete()
260 301
        resp = app.get('/manage/pwa/')
261 302
        resp.form['application_icon'] = Upload(
262 303
            'test.png',
263 304
            base64.decodebytes(
264
-