comparison sat_pubsub/backend.py @ 317:34adc4a8aa64

new container module, with an ItemData container: this simplify item data manipulation and transmission between storage and backend, it's also better if new data need to be used.
author Goffi <goffi@goffi.org>
date Sun, 03 Jan 2016 18:33:22 +0100
parents 720d73e30bf7
children d13526c0eb32
comparison
equal deleted inserted replaced
316:cca47e9977a5 317:34adc4a8aa64
70 from twisted.internet import defer, reactor 70 from twisted.internet import defer, reactor
71 from twisted.words.protocols.jabber.error import StanzaError 71 from twisted.words.protocols.jabber.error import StanzaError
72 # from twisted.words.protocols.jabber.jid import JID, InvalidFormat 72 # from twisted.words.protocols.jabber.jid import JID, InvalidFormat
73 from twisted.words.xish import utility 73 from twisted.words.xish import utility
74 74
75 from wokkel import disco, data_form, rsm 75 from wokkel import disco
76 from wokkel.iwokkel import IPubSubResource 76 from wokkel import data_form
77 from wokkel.pubsub import PubSubResource, PubSubError, Subscription 77 from wokkel import rsm
78 78 from wokkel import iwokkel
79 from sat_pubsub import error, iidavoll, const 79 from wokkel import pubsub
80 from sat_pubsub.iidavoll import IBackendService, ILeafNode 80
81 from sat_pubsub import error
82 from sat_pubsub import iidavoll
83 from sat_pubsub import const
84 from sat_pubsub import container
81 85
82 from copy import deepcopy 86 from copy import deepcopy
83 from collections import namedtuple
84
85
86 ItemData = namedtuple('ItemData', ('item', 'access_model', 'config', 'categories'))
87 87
88 88
89 def _getAffiliation(node, entity): 89 def _getAffiliation(node, entity):
90 d = node.getAffiliation(entity) 90 d = node.getAffiliation(entity)
91 d.addCallback(lambda affiliation: (node, affiliation)) 91 d.addCallback(lambda affiliation: (node, affiliation))
334 item["id"] = str(uuid.uuid4()) 334 item["id"] = str(uuid.uuid4())
335 else: 335 else:
336 check_overwrite = True 336 check_overwrite = True
337 access_model, item_config = self.parseItemConfig(item) 337 access_model, item_config = self.parseItemConfig(item)
338 categories = self.parseCategories(item) 338 categories = self.parseCategories(item)
339 items_data.append(ItemData(item, access_model, item_config, categories)) 339 items_data.append(container.ItemData(item, access_model, item_config, categories))
340 340
341 if persistItems: 341 if persistItems:
342 if check_overwrite and affiliation != 'owner': 342 if check_overwrite and affiliation != 'owner':
343 # we don't want a publisher to overwrite the item 343 # we don't want a publisher to overwrite the item
344 # of an other publisher 344 # of an other publisher
591 return d 591 return d
592 592
593 def _rosterEb(self, failure, owner_jid): 593 def _rosterEb(self, failure, owner_jid):
594 log.msg("Error while getting roster of {}: {}".format(unicode(owner_jid), failure.value)) 594 log.msg("Error while getting roster of {}: {}".format(unicode(owner_jid), failure.value))
595 return {} 595 return {}
596
597 def _tuple2ItemData(self, items_data):
598 # FIXME: workaround for the use of ItemData which doesn't exist in storage
599 # must be done in a cleaner way
600 return [ItemData(item, access_model, access_list, []) for item, access_model, access_list in items_data]
601 596
602 def _doGetItems(self, result, requestor, maxItems, itemIdentifiers, 597 def _doGetItems(self, result, requestor, maxItems, itemIdentifiers,
603 ext_data): 598 ext_data):
604 node, affiliation = result 599 node, affiliation = result
605 600
634 authorized_groups = tuple(roster_item.groups) if roster_item else tuple() 629 authorized_groups = tuple(roster_item.groups) if roster_item else tuple()
635 unrestricted = affiliation == 'owner' 630 unrestricted = affiliation == 'owner'
636 631
637 if itemIdentifiers: 632 if itemIdentifiers:
638 d = node.getItemsById(authorized_groups, unrestricted, itemIdentifiers) 633 d = node.getItemsById(authorized_groups, unrestricted, itemIdentifiers)
639 d.addCallback(self._tuple2ItemData)
640 else: 634 else:
641 d = node.getItems(authorized_groups, unrestricted, maxItems, ext_data) 635 d = node.getItems(authorized_groups, unrestricted, maxItems, ext_data)
642 if unrestricted: 636 if unrestricted:
643 d.addCallback(self._tuple2ItemData)
644 d.addCallback(append_item_config) 637 d.addCallback(append_item_config)
645 638
646 try: 639 try:
647 rsm_data = ext_data['rsm'] 640 rsm_data = ext_data['rsm']
648 except KeyError: 641 except KeyError:
652 d.addCallback(self._items_rsm, node, authorized_groups, 645 d.addCallback(self._items_rsm, node, authorized_groups,
653 unrestricted, maxItems, itemIdentifiers, 646 unrestricted, maxItems, itemIdentifiers,
654 rsm_data) 647 rsm_data)
655 return d 648 return d
656 649
657 if not ILeafNode.providedBy(node): 650 if not iidavoll.ILeafNode.providedBy(node):
658 return [] 651 return []
659 652
660 if affiliation == 'outcast': 653 if affiliation == 'outcast':
661 raise error.Forbidden() 654 raise error.Forbidden()
662 655
778 # we check if he is a publisher for all items he wants to retract 771 # we check if he is a publisher for all items he wants to retract
779 # and forbid the retraction else. 772 # and forbid the retraction else.
780 d = node.getItemsPublishers(itemIdentifiers) 773 d = node.getItemsPublishers(itemIdentifiers)
781 d.addCallback(checkPublishers) 774 d.addCallback(checkPublishers)
782 d.addCallback(lambda dummy: node.getItemsById(None, True, itemIdentifiers)) 775 d.addCallback(lambda dummy: node.getItemsById(None, True, itemIdentifiers))
783 d.addCallback(self._tuple2ItemData)
784 d.addCallback(removeItems) 776 d.addCallback(removeItems)
785 777
786 if notify: 778 if notify:
787 d.addCallback(self._doNotifyRetraction, node, pep, recipient) 779 d.addCallback(self._doNotifyRetraction, node, pep, recipient)
788 return d 780 return d
874 for d in dl: 866 for d in dl:
875 d.callback(None) 867 d.callback(None)
876 868
877 869
878 870
879 class PubSubResourceFromBackend(PubSubResource): 871 class PubSubResourceFromBackend(pubsub.PubSubResource):
880 """ 872 """
881 Adapts a backend to an xmpp publish-subscribe service. 873 Adapts a backend to an xmpp publish-subscribe service.
882 """ 874 """
883 875
884 features = [ 876 features = [
930 'unsupported', 922 'unsupported',
931 'publish'), 923 'publish'),
932 } 924 }
933 925
934 def __init__(self, backend): 926 def __init__(self, backend):
935 PubSubResource.__init__(self) 927 pubsub.PubSubResource.__init__(self)
936 928
937 self.backend = backend 929 self.backend = backend
938 self.hideNodes = False 930 self.hideNodes = False
939 931
940 self.backend.registerPublishNotifier(self._notifyPublish) 932 self.backend.registerPublishNotifier(self._notifyPublish)
991 if item_config: 983 if item_config:
992 new_item.addChild(item_config.toElement()) 984 new_item.addChild(item_config.toElement())
993 return new_item 985 return new_item
994 986
995 notifications_filtered.append((owner_jid, 987 notifications_filtered.append((owner_jid,
996 set([Subscription(node.nodeIdentifier, 988 set([pubsub.Subscription(node.nodeIdentifier,
997 owner_jid, 989 owner_jid,
998 'subscribed')]), 990 'subscribed')]),
999 [getFullItem(item_data) for item_data in items_data])) 991 [getFullItem(item_data) for item_data in items_data]))
1000 992
1001 if pep: 993 if pep:
1023 def afterPrepare(result): 1015 def afterPrepare(result):
1024 owner_jid, notifications_filtered = result 1016 owner_jid, notifications_filtered = result
1025 #we add the owner 1017 #we add the owner
1026 1018
1027 notifications_filtered.append((owner_jid, 1019 notifications_filtered.append((owner_jid,
1028 set([Subscription(node.nodeIdentifier, 1020 set([pubsub.Subscription(node.nodeIdentifier,
1029 owner_jid, 1021 owner_jid,
1030 'subscribed')]), 1022 'subscribed')]),
1031 [item_data.item for item_data in items_data])) 1023 [item_data.item for item_data in items_data]))
1032 1024
1033 if pep: 1025 if pep:
1141 1133
1142 condition, pubsubCondition, feature = self._errorMap[e] 1134 condition, pubsubCondition, feature = self._errorMap[e]
1143 msg = failure.value.msg 1135 msg = failure.value.msg
1144 1136
1145 if pubsubCondition: 1137 if pubsubCondition:
1146 exc = PubSubError(condition, pubsubCondition, feature, msg) 1138 exc = pubsub.PubSubError(condition, pubsubCondition, feature, msg)
1147 else: 1139 else:
1148 exc = StanzaError(condition, text=msg) 1140 exc = StanzaError(condition, text=msg)
1149 1141
1150 raise exc 1142 raise exc
1151 1143
1324 self._isPep(request), 1316 self._isPep(request),
1325 request.recipient) 1317 request.recipient)
1326 return d.addErrback(self._mapErrors) 1318 return d.addErrback(self._mapErrors)
1327 1319
1328 components.registerAdapter(PubSubResourceFromBackend, 1320 components.registerAdapter(PubSubResourceFromBackend,
1329 IBackendService, 1321 iidavoll.IBackendService,
1330 IPubSubResource) 1322 iwokkel.IPubSubResource)