# HG changeset patch # User Ralph Meijer # Date 1199365825 0 # Node ID bc269696ef427de9aa259184b47ed76d23d2b8b8 # Parent 958e69630e52d9aa3a3796945feb8de944d43473 Reply with the correct error condition on subscription when not subscribed. Author: ralphm. Fixes #7. diff -r 958e69630e52 -r bc269696ef42 idavoll/backend.py --- 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', diff -r 958e69630e52 -r bc269696ef42 idavoll/error.py --- 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' diff -r 958e69630e52 -r bc269696ef42 idavoll/memory_storage.py --- 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): diff -r 958e69630e52 -r bc269696ef42 idavoll/pgsql_storage.py --- 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 diff -r 958e69630e52 -r bc269696ef42 idavoll/test/test_backend.py --- 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 diff -r 958e69630e52 -r bc269696ef42 idavoll/test/test_storage.py --- 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)