Skip to content

Commit

Permalink
Refs #6 - Ensure unsubscribing from services works, and deletes subsc…
Browse files Browse the repository at this point in the history
…ription and data from external service
  • Loading branch information
johan-fvh committed Jan 16, 2020
1 parent 4cceff0 commit 7fcba63
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 1 deletion.
4 changes: 4 additions & 0 deletions backend/core/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ def get_queryset(self):
def get_serializer_class(self):
return self.serializer_classes.get(self.action, self.serializer_class)

def perform_destroy(self, instance):
instance.delete_in_service()
instance.delete()


@api_view(['POST'])
@permission_classes([permissions.AllowAny])
Expand Down
18 changes: 18 additions & 0 deletions backend/core/migrations/0025_service_unsubscribe_url.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.2.8 on 2020-01-16 09:43

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('core', '0024_auto_20200116_0906'),
]

operations = [
migrations.AddField(
model_name='service',
name='unsubscribe_url',
field=models.URLField(default='', help_text='URL to which unsubscribe requests should be POSTed'),
),
]
11 changes: 10 additions & 1 deletion backend/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ class Service(models.Model):
img_service_url = models.CharField(max_length=255, null=True)

subscribe_url = models.URLField(default='', help_text='URL to which new subscriptions should be POSTed')
unsubscribe_url = models.URLField(default='', help_text='URL to which unsubscribe requests should be POSTed')
data_url = models.URLField(default='', help_text='URL to which sensor data should be POSTed')
report_url = models.URLField(default='', help_text='URL to the main page presenting a subscription')
preview_url = models.URLField(
Expand Down Expand Up @@ -196,13 +197,21 @@ def create_in_service(self):
self.registered = timezone.now()
self.save()

def delete_in_service(self):
"""
Delete this subscription in the remote service.
"""
data = {'uuid': str(self.uuid), 'auth_token': str(self.service.auth_token)}
response = self._post(self.service.unsubscribe_url, json=data)
response.raise_for_status() # Raises exception if status code >=400

def send_values(self, values):
"""
Send the passed values to the external service.
"""
data = SubscriptionDataSerializer(self, values=values).data
response = self._post(self.service.data_url, json=data)
response.raise_for_status() # Raises exception if status code >=400
response.raise_for_status() # Raises exception if status code >=400

def submit_history(self):
"""
Expand Down
26 changes: 26 additions & 0 deletions backend/core/tests/test_subscribe.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def setUp(self):
description='temperature', uri='http://urn.fi/URN:NBN:fi:au:ucum:r73')
self.service = models.Service.objects.create(
subscribe_url='https://service.com/api/subscriptions/',
unsubscribe_url='https://service.com/api/unsubscribe/',
data_url='https://service.com/api/measurements/')
self.service.requires.add(self.temperature)

Expand Down Expand Up @@ -146,3 +147,28 @@ def test_subscription_receives_data(self):
'timestamp': serializers.DateTimeField().to_representation(value.updated_at),
'value': str(value.value)}],
'auth_token': str(self.service.auth_token)})

def test_unsubscribe(self):
# Given that there is a subscription for an external service
subscription = self.user.subscriptions.create(service=self.service)

# And given that the subscriber is signed in
self.client.force_login(self.user)

# When requesting to delete the subscription over the ReST API
url = reverse('subscription-detail', kwargs={'pk': subscription.id})
with self.mock_requests:
response = self.client.delete(url)

# Then a 204 response is returned
self.assertEqual(204, response.status_code)

# And the subscription is removed from the db
self.assertEqual(0, models.Subscription.objects.count())

# And the unsubscribe request is submitted to the external service
([url], kwargs) = self.mock_requests.last_request
self.assertEqual(url, self.service.unsubscribe_url)
self.assert_dict_contains(kwargs['json'], {
'uuid': str(subscription.uuid),
'auth_token': str(self.service.auth_token)})

0 comments on commit 7fcba63

Please sign in to comment.