changeset 171:bc269696ef42

Reply with the correct error condition on subscription when not subscribed. Author: ralphm. Fixes #7.
author Ralph Meijer <ralphm@ik.nu>
date Thu, 03 Jan 2008 13:10:25 +0000
parents 958e69630e52
children 9bfb00edd0cc
files idavoll/backend.py idavoll/error.py idavoll/memory_storage.py idavoll/pgsql_storage.py idavoll/test/test_backend.py idavoll/test/test_storage.py
diffstat 6 files changed, 67 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/idavoll/backend.py	Tue Oct 09 10:20:25 2007 +0000
+++ b/idavoll/backend.py	Thu Jan 03 13:10:25 2008 +0000
@@ -1,6 +1,6 @@
 # -*- test-case-name: idavoll.test.test_backend -*-
 #
-# Copyright (c) 2003-2007 Ralph Meijer
+# Copyright (c) 2003-2008 Ralph Meijer
 # See LICENSE for details.
 
 import uuid
@@ -24,6 +24,7 @@
     d.addCallback(lambda affiliation: (node, affiliation))
     return d
 
+
 class BackendService(service.Service, utility.EventDispatcher):
 
     implements(iidavoll.IBackendService)
@@ -360,16 +361,13 @@
     _errorMap = {
         error.NodeNotFound: ('item-not-found', None, None),
         error.NodeExists: ('conflict', None, None),
-        error.SubscriptionNotFound: ('not-authorized',
-                                     'not-subscribed',
-                                     None),
         error.Forbidden: ('forbidden', None, None),
         error.ItemForbidden: ('bad-request', 'item-forbidden', None),
         error.ItemRequired: ('bad-request', 'item-required', None),
         error.NoInstantNodes: ('not-acceptable',
                                'unsupported',
                                'instant-nodes'),
-        error.NotSubscribed: ('not-authorized', 'not-subscribed', None),
+        error.NotSubscribed: ('unexpected-request', 'not-subscribed', None),
         error.InvalidConfigurationOption: ('not-acceptable', None, None),
         error.InvalidConfigurationValue: ('not-acceptable', None, None),
         error.NodeNotPersistent: ('feature-not-implemented',
--- a/idavoll/error.py	Tue Oct 09 10:20:25 2007 +0000
+++ b/idavoll/error.py	Thu Jan 03 13:10:25 2008 +0000
@@ -1,4 +1,4 @@
-# Copyright (c) 2003-2007 Ralph Meijer
+# Copyright (c) 2003-2008 Ralph Meijer
 # See LICENSE for details.
 
 class Error(Exception):
@@ -13,8 +13,10 @@
 class NodeExists(Error):
     pass
 
-class SubscriptionNotFound(Error):
-    pass
+class NotSubscribed(Error):
+    """
+    Entity is not subscribed to this node.
+    """
 
 class SubscriptionExists(Error):
     pass
@@ -31,9 +33,6 @@
 class NoInstantNodes(Error):
     pass
 
-class NotSubscribed(Error):
-    pass
-
 class InvalidConfigurationOption(Error):
     msg = 'Invalid configuration option'
 
--- a/idavoll/memory_storage.py	Tue Oct 09 10:20:25 2007 +0000
+++ b/idavoll/memory_storage.py	Thu Jan 03 13:10:25 2008 +0000
@@ -1,4 +1,4 @@
-# Copyright (c) 2003-2007 Ralph Meijer
+# Copyright (c) 2003-2008 Ralph Meijer
 # See LICENSE for details.
 
 import copy
@@ -68,7 +68,8 @@
                                           subscription.state))
 
         return defer.succeed(subscriptions)
-        
+
+
 class Node:
 
     implements(iidavoll.INode)
@@ -84,7 +85,7 @@
 
     def get_configuration(self):
         return self._config
-    
+
     def get_meta_data(self):
         config = copy.copy(self._config)
         config["pubsub#node_type"] = self.type
@@ -96,7 +97,7 @@
                 self._config[option] = options[option]
 
         return defer.succeed(None)
-                
+
     def get_affiliation(self, entity):
         return defer.succeed(self._affiliations.get(entity.full()))
 
@@ -121,7 +122,7 @@
         try:
             del self._subscriptions[subscriber.full()]
         except KeyError:
-            return defer.fail(error.SubscriptionNotFound())
+            return defer.fail(error.NotSubscribed())
 
         return defer.succeed(None)
 
@@ -137,7 +138,7 @@
             if jid.internJID(subscriber).userhost() == entity.userhost() and \
                     subscription.state == 'subscribed':
                 return defer.succeed(True)
-        
+
         return defer.succeed(False)
 
     def get_affiliations(self):
@@ -146,6 +147,7 @@
 
         return defer.succeed(affiliations)
 
+
 class LeafNodeMixin:
 
     type = 'leaf'
@@ -180,7 +182,7 @@
                 self._itemlist.remove(item)
                 del self._items[item_id]
                 deleted.append(item_id)
-        
+
         return defer.succeed(deleted)
 
     def get_items(self, max_items=None):
@@ -189,7 +191,7 @@
         else:
             list = self._itemlist
         return defer.succeed([item[0] for item in list])
-    
+
     def get_items_by_id(self, item_ids):
         items = []
         for item_id in item_ids:
@@ -207,6 +209,7 @@
 
         return defer.succeed(None)
 
+
 class LeafNode(Node, LeafNodeMixin):
 
     implements(iidavoll.ILeafNode)
@@ -215,6 +218,7 @@
         Node.__init__(self, node_id, owner, config)
         LeafNodeMixin.__init__(self)
 
+
 class Subscription:
 
     def __init__(self, state):
--- a/idavoll/pgsql_storage.py	Tue Oct 09 10:20:25 2007 +0000
+++ b/idavoll/pgsql_storage.py	Thu Jan 03 13:10:25 2008 +0000
@@ -1,4 +1,4 @@
-# Copyright (c) 2003-2007 Ralph Meijer
+# Copyright (c) 2003-2008 Ralph Meijer
 # See LICENSE for details.
 
 import copy
@@ -111,6 +111,7 @@
                  subscription)
                 for node, subscriber, resource, subscription in subscriptions]
 
+
 class Node:
 
     implements(iidavoll.INode)
@@ -245,7 +246,7 @@
                         userhost,
                         resource))
         if cursor.rowcount != 1:
-            raise error.SubscriptionNotFound()
+            raise error.NotSubscribed()
 
         return None
 
--- a/idavoll/test/test_backend.py	Tue Oct 09 10:20:25 2007 +0000
+++ b/idavoll/test/test_backend.py	Thu Jan 03 13:10:25 2008 +0000
@@ -1,19 +1,18 @@
-# Copyright (c) 2003-2007 Ralph Meijer
+# Copyright (c) 2003-2008 Ralph Meijer
 # See LICENSE for details.
 
 """
 Tests for L{idavoll.backend}.
 """
 
-from zope.interface import implements
-
 from twisted.internet import defer
 from twisted.trial import unittest
 from twisted.words.protocols.jabber import jid
+from twisted.words.protocols.jabber.error import StanzaError
 
 from wokkel import pubsub
 
-from idavoll import backend, error, iidavoll
+from idavoll import backend, error
 
 OWNER = jid.JID('owner@example.com')
 
@@ -106,3 +105,39 @@
         items = [pubsub.Item()]
         d = self.backend.publish('node', items, OWNER)
         return d
+
+
+class PubSubServiceFromBackendTest(unittest.TestCase):
+
+    def test_unsubscribeNotSubscribed(self):
+        """
+        Test unsubscription request when not subscribed.
+        """
+
+        class TestBackend(object):
+            def supports_publisher_affiliation(self):
+                return True
+
+            def supports_outcast_affiliation(self):
+                return True
+
+            def supports_persistent_items(self):
+                return True
+
+            def supports_instant_nodes(self):
+                return True
+
+            def register_notifier(self, observerfn, *args, **kwargs):
+                return
+
+            def unsubscribe(self, nodeIdentifier, subscriber, requestor):
+                return defer.fail(error.NotSubscribed())
+
+        def cb(e):
+            self.assertEquals('unexpected-request', e.condition)
+
+        s = backend.PubSubServiceFromBackend(TestBackend())
+        d = s.unsubscribe(OWNER, 'test.example.org', 'test', OWNER)
+        self.assertFailure(d, StanzaError)
+        d.addCallback(cb)
+        return d
--- a/idavoll/test/test_storage.py	Tue Oct 09 10:20:25 2007 +0000
+++ b/idavoll/test/test_storage.py	Thu Jan 03 13:10:25 2008 +0000
@@ -1,4 +1,4 @@
-# Copyright (c) 2003-2007 Ralph Meijer
+# Copyright (c) 2003-2008 Ralph Meijer
 # See LICENSE for details.
 
 """
@@ -39,6 +39,7 @@
         object = object.decode('utf-8')
     return object
 
+
 class StorageTests:
 
     def _assignTestNode(self, node):
@@ -203,7 +204,7 @@
 
     def testRemoveNonExistingSubscription(self):
         d = self.node.remove_subscription(OWNER)
-        self.assertFailure(d, error.SubscriptionNotFound)
+        self.assertFailure(d, error.NotSubscribed)
         return d
 
     def testGetSubscribers(self):
@@ -338,6 +339,7 @@
         d.addCallback(cb2)
         return d
 
+
 class MemoryStorageStorageTestCase(unittest.TestCase, StorageTests):
 
     def setUp(self):
@@ -371,6 +373,7 @@
 
         return StorageTests.setUp(self)
 
+
 class PgsqlStorageStorageTestCase(unittest.TestCase, StorageTests):
     def _callSuperSetUp(self, void):
         return StorageTests.setUp(self)