comparison sat_pubsub/backend.py @ 354:18b983fe9e1b

backend: added "presence" access_model: - move presence checking method in separated method so they can be use for get and subscriptions - added VAL_AMODEL_PRESENCE constant
author Goffi <goffi@goffi.org>
date Fri, 08 Sep 2017 08:02:05 +0200
parents 7c5d85c6fb3a
children c72fcbdcdab7
comparison
equal deleted inserted replaced
353:7c5d85c6fb3a 354:18b983fe9e1b
122 const.OPT_ACCESS_MODEL: 122 const.OPT_ACCESS_MODEL:
123 {"type": "list-single", 123 {"type": "list-single",
124 "label": "Who can subscribe to this node", 124 "label": "Who can subscribe to this node",
125 "options": { 125 "options": {
126 const.VAL_AMODEL_OPEN: "Public node", 126 const.VAL_AMODEL_OPEN: "Public node",
127 const.VAL_AMODEL_PRESENCE: "Node restricted to entites subscribed to owner presence",
127 const.VAL_AMODEL_PUBLISHER_ROSTER: "Node restricted to some groups of publisher's roster", 128 const.VAL_AMODEL_PUBLISHER_ROSTER: "Node restricted to some groups of publisher's roster",
128 const.VAL_AMODEL_WHITELIST: "Node restricted to some jids", 129 const.VAL_AMODEL_WHITELIST: "Node restricted to some jids",
129 } 130 }
130 }, 131 },
131 const.OPT_ROSTER_GROUPS_ALLOWED: 132 const.OPT_ROSTER_GROUPS_ALLOWED:
469 if affiliation == 'outcast': 470 if affiliation == 'outcast':
470 raise error.Forbidden() 471 raise error.Forbidden()
471 472
472 access_model = node.getAccessModel() 473 access_model = node.getAccessModel()
473 474
474 if access_model != const.VAL_AMODEL_OPEN: 475 if access_model == const.VAL_AMODEL_OPEN:
476 d = defer.succeed(None)
477 elif access_model == const.VAL_AMODEL_PRESENCE:
478 d = self.checkPresenceSubscription(node, subscriber)
479 elif access_model == const.VAL_AMODEL_PUBLISHER_ROSTER:
480 d = self.checkRosterGroups(node, subscriber)
481 elif access_model == const.VAL_AMODEL_WHITELIST:
482 d = self.checkNodeAffiliations(node, subscriber)
483 else:
475 raise NotImplementedError 484 raise NotImplementedError
476 485
477 def trapExists(failure): 486 def trapExists(failure):
478 failure.trap(error.SubscriptionExists) 487 failure.trap(error.SubscriptionExists)
479 return False 488 return False
764 item_elt.addChild(form.toElement()) 773 item_elt.addChild(form.toElement())
765 774
766 for item_data in items_to_remove: 775 for item_data in items_to_remove:
767 items_data.remove(item_data) 776 items_data.remove(item_data)
768 777
778 def checkPresenceSubscription(self, node, requestor):
779 """check if requestor has presence subscription from node owner
780
781 @param node(Node): node to check
782 @param requestor(jid.JID): entity who want to access node
783 """
784 def gotRoster(roster):
785 if roster is None:
786 raise error.Forbidden()
787
788 if requestor not in roster:
789 raise error.Forbidden()
790
791 if not roster[requestor].subscriptionFrom:
792 raise error.Forbidden()
793
794 d = self.getOwnerRoster(node)
795 d.addCallback(gotRoster)
796 return d
797
798 @defer.inlineCallbacks
799 def checkRosterGroups(self, node, requestor):
800 """check if requestor is in allowed groups of a node
801
802 @param node(Node): node to check
803 @param requestor(jid.JID): entity who want to access node
804 """
805 roster = yield self.getOwnerRoster(node)
806
807 if roster is None:
808 raise error.Forbidden()
809
810 if requestor not in roster:
811 raise error.Forbidden()
812
813 authorized_groups = yield node.getAuthorizedGroups()
814
815 if not roster[requestor].groups.intersection(authorized_groups):
816 # requestor is in roster but not in one of the allowed groups
817 raise error.Forbidden()
818
819 @defer.inlineCallbacks
820 def checkNodeAffiliations(self, node, requestor):
821 """check if requestor is in white list of a node
822
823 @param node(Node): node to check
824 @param requestor(jid.JID): entity who want to access node
825 """
826 def gotAffiliations(affiliations):
827 try:
828 affiliation = affiliations[requestor.userhostJID()]
829 except KeyError:
830 raise error.Forbidden()
831 else:
832 if affiliation not in ('owner', 'publisher', 'member'):
833 raise error.Forbidden()
834
835 d = node.getAffiliations()
836 d.addCallback(gotAffiliations)
837 return d
838
769 @defer.inlineCallbacks 839 @defer.inlineCallbacks
770 def checkNodeAccess(self, node, requestor): 840 def checkNodeAccess(self, node, requestor):
771 """check if a requestor can access data of a node 841 """check if a requestor can access data of a node
772 842
773 @param node(Node): node to check 843 @param node(Node): node to check
793 access_model = node.getAccessModel() 863 access_model = node.getAccessModel()
794 roster = None 864 roster = None
795 865
796 if access_model == const.VAL_AMODEL_OPEN or owner: 866 if access_model == const.VAL_AMODEL_OPEN or owner:
797 pass 867 pass
868 elif access_model == const.VAL_AMODEL_PRESENCE:
869 yield self.checkPresenceSubscription(node, requestor)
798 elif access_model == const.VAL_AMODEL_PUBLISHER_ROSTER: 870 elif access_model == const.VAL_AMODEL_PUBLISHER_ROSTER:
799 # FIXME: publisher roster should be used, not owner 871 # FIXME: for node, access should be renamed owner-roster, not publisher
800 roster = yield self.getOwnerRoster(node) 872 yield self.checkRosterGroups(node, requestor)
801
802 if roster is None:
803 raise error.Forbidden()
804
805 if requestor not in roster:
806 raise error.Forbidden()
807
808 authorized_groups = yield node.getAuthorizedGroups()
809
810 if not roster[requestor].groups.intersection(authorized_groups):
811 # requestor is in roster but not in one of the allowed groups
812 raise error.Forbidden()
813 elif access_model == const.VAL_AMODEL_WHITELIST: 873 elif access_model == const.VAL_AMODEL_WHITELIST:
814 affiliations = yield node.getAffiliations() 874 yield self.checkNodeAffiliations(node, requestor)
815 try:
816 affiliation = affiliations[requestor.userhostJID()]
817 except KeyError:
818 raise error.Forbidden()
819 else:
820 if affiliation not in ('owner', 'publisher', 'member'):
821 raise error.Forbidden()
822 else: 875 else:
823 raise Exception(u"Unknown access_model") 876 raise Exception(u"Unknown access_model")
824 877
825 defer.returnValue((affiliation, owner, roster, access_model)) 878 defer.returnValue((affiliation, owner, roster, access_model))
826 879
1499 self._isPep(request), 1552 self._isPep(request),
1500 request.recipient) 1553 request.recipient)
1501 return d.addErrback(self._mapErrors) 1554 return d.addErrback(self._mapErrors)
1502 1555
1503 def subscriptions(self, request): 1556 def subscriptions(self, request):
1504 d = self.backend.getSubscriptions(self._isPep(request), 1557 d = self.backend.getSubscriptions(request.sender,
1505 request.sender) 1558 self._isPep(request),
1559 request.recipient)
1506 return d.addErrback(self._mapErrors) 1560 return d.addErrback(self._mapErrors)
1507 1561
1508 def affiliations(self, request): 1562 def affiliations(self, request):
1509 """Retrieve affiliation for normal entity (cf. XEP-0060 §5.7) 1563 """Retrieve affiliation for normal entity (cf. XEP-0060 §5.7)
1510 1564