Projet

Général

Profil

0006-notifications-enforce-namespacing-on-external-ids-to.patch

Benjamin Dauvergne, 18 mars 2018 22:13

Télécharger (6,39 ko)

Voir les différences:

Subject: [PATCH 6/8] notifications: enforce namespacing on external ids (to be
 rebased)

 combo/apps/notifications/api_views.py | 34 +++++++++++++++++++---------------
 combo/apps/notifications/models.py    |  7 +++++++
 tests/test_notification.py            | 30 +++++++++++++++++++++++++++---
 3 files changed, 53 insertions(+), 18 deletions(-)
combo/apps/notifications/api_views.py
23 23

  
24 24
class NotificationSerializer(serializers.Serializer):
25 25
    summary = serializers.CharField(required=True, allow_blank=False, max_length=140)
26
    id = serializers.SlugField(required=False, allow_null=True)
26
    id = serializers.CharField(required=False, allow_null=True)
27 27
    body = serializers.CharField(allow_blank=False, default='')
28 28
    url = serializers.URLField(allow_blank=True, default='')
29 29
    origin = serializers.CharField(allow_blank=True, default='')
......
42 42
            response = {'err': 1, 'err_desc': serializer.errors}
43 43
            return Response(response, status.HTTP_400_BAD_REQUEST)
44 44
        data = serializer.validated_data
45

  
46
        notification, created = Notification.notify(
47
            user=request.user,
48
            summary=data['summary'],
49
            id=data.get('id'),
50
            body=data.get('body'),
51
            url=data.get('url'),
52
            origin=data.get('origin'),
53
            start_timestamp=data.get('start_timestamp'),
54
            end_timestamp=data.get('end_timestamp'),
55
            duration=data.get('duration')
56
        )
57
        response = {'err': 0, 'data': {'id': notification.public_id, 'created': created}}
58
        return Response(response)
45
        try:
46
            notification, created = Notification.notify(
47
                user=request.user,
48
                summary=data['summary'],
49
                id=data.get('id'),
50
                body=data.get('body'),
51
                url=data.get('url'),
52
                origin=data.get('origin'),
53
                start_timestamp=data.get('start_timestamp'),
54
                end_timestamp=data.get('end_timestamp'),
55
                duration=data.get('duration')
56
            )
57
        except ValueError as e:
58
            response = {'err': 1, 'err_desc': {'id': [unicode(e)]}}
59
            return Response(response, status.HTTP_400_BAD_REQUEST)
60
        else:
61
            response = {'err': 0, 'data': {'id': notification.public_id, 'created': created}}
62
            return Response(response)
59 63

  
60 64
add = Add.as_view()
61 65

  
combo/apps/notifications/models.py
14 14
# You should have received a copy of the GNU Affero General Public License
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17
import re
18

  
17 19
from django.conf import settings
18 20
from django.db import models
19 21
from django.utils.translation import ugettext_lazy as _
......
56 58

  
57 59

  
58 60
class Notification(models.Model):
61
    ID_RE = r'^[\w-]+:[\w]+$'
62

  
59 63
    objects = NotificationQuerySet.as_manager()
60 64

  
61 65
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
......
68 72
    acked = models.BooleanField(_('Acked'), default=False)
69 73
    external_id = models.SlugField(_('External identifier'), null=True)
70 74

  
75

  
71 76
    class Meta:
72 77
        verbose_name = _('Notification')
73 78
        unique_together = (
......
125 130
                id = unicode(id)
126 131
            except Exception as e:
127 132
                raise ValueError('id must be convertible to unicode', e)
133
            if not re.match(cls.ID_RE, id):
134
                raise ValueError('id must match regular expression %s' % cls.ID_RE)
128 135
            notification, created = Notification.objects.update_or_create(
129 136
                user=user, external_id=id,
130 137
                defaults=defaults)
tests/test_notification.py
66 66
    noti = Notification.objects.get()
67 67
    assert noti.end_timestamp - noti.start_timestamp == timedelta(seconds=3600)
68 68

  
69
    notification, created = Notification.notify(user, 'notibar', id='notibar')
69
    notification, created = Notification.notify(user, 'notibar', id='ns:notibar')
70 70
    assert Notification.objects.count() == 2
71
    notification, created = Notification.notify(user, 'notirebar', id='notibar')
71
    notification, created = Notification.notify(user, 'notirebar', id='ns:notibar')
72 72
    assert not created
73 73
    assert Notification.objects.count() == 2
74 74

  
......
153 153
    login()
154 154
    notify({'summary': 'foo'}, '1', 1)
155 155
    notify({'summary': 'bar'}, '2', 2)
156
    notify({'summary': 'bar', 'id': 'noti3'}, 'noti3', 3)
156
    notify({'summary': 'bar', 'id': 'ns:noti3'}, 'ns:noti3', 3)
157 157
    notif = {
158 158
        'summary': 'bar',
159 159
        'url': 'http://www.example.net',
......
233 233
                   kwargs={'notification_id': 'noti1'}) == '/api/notification/ack/noti1/'
234 234
    assert reverse('api-notification-forget',
235 235
                   kwargs={'notification_id': 'noti1'}) == '/api/notification/forget/noti1/'
236

  
237

  
238
def test_notification_id_and_origin(user):
239
    login()
240

  
241
    def notify(data):
242
        resp = client.post(reverse('api-notification-add'), json.dumps(data),
243
                           content_type='application/json')
244

  
245
        return json.loads(resp.content)
246

  
247
    result = notify({'summary': 'foo', 'id': '1'})
248
    assert result['err'] == 1
249

  
250
    notification, created = Notification.notify(user, 'foo')
251

  
252
    result = notify({'summary': 'foo', 'id': str(notification.id)})
253
    assert result['err'] == 0
254

  
255
    result = notify({'summary': 'foo', 'id': 'foo'})
256
    assert result['err'] == 1
257

  
258
    result = notify({'summary': 'foo', 'id': 'foo:foo', 'origin': 'bar'})
259
    assert result['err'] == 0
236
-