diff sat_pubsub/privilege.py @ 460:607616f9ef5b

backend: new `server_jid` option: Server domain must be known to validate requests, this can be done explicitely by using the `server_jid` option. If this option is not set, the server domain is found: - by using the `from` name of the initial delegation advertising message - or it fallbacks to using the part after initial `.` (`pubsub.example.org` would give `example.org`)
author Goffi <goffi@goffi.org>
date Fri, 15 Oct 2021 09:32:07 +0200
parents 0b5233981671
children a017af61a32b
line wrap: on
line diff
--- a/sat_pubsub/privilege.py	Fri Oct 15 09:32:04 2021 +0200
+++ b/sat_pubsub/privilege.py	Fri Oct 15 09:32:07 2021 +0200
@@ -1,7 +1,6 @@
 #!/usr/bin/env python3
-#-*- coding: utf-8 -*-
 #
-# Copyright (c) 2015 Jérôme Poisson
+# Copyright (c) 2015-2021 Jérôme Poisson
 
 
 # This program is free software: you can redistribute it and/or modify
@@ -17,7 +16,8 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-# ---
+"This module implements XEP-0356 (Privileged Entity) to manage rosters, messages and "
+"presences"
 
 # This module implements XEP-0356 (Privileged Entity) to manage rosters, messages and presences
 
@@ -58,21 +58,17 @@
 
     def __init__(self, service_jid):
         super(PrivilegesHandler, self).__init__()
+        self.backend = None
         self._permissions = {PERM_ROSTER: 'none',
                              PERM_MESSAGE: 'none',
                              PERM_PRESENCE: 'none'}
         self._pubsub_service = None
-        self._backend = None
-        # FIXME: we use a hack supposing that our privilege come from hostname
-        #        and we are a component named [name].hostname
-        #        but we need to manage properly server
-        # TODO: do proper server handling
-        self.server_jid = jid.JID(service_jid.host.split('.', 1)[1])
         self.caps_map = {}  # key: bare jid, value: dict of resources with caps hash
-        self.hash_map = {}  # key: (hash,version), value: dict with DiscoInfo instance (infos) and nodes to notify (notify)
+        # key: (hash,version), value: dict with DiscoInfo instance (infos) and nodes to
+        # notify (notify)
+        self.hash_map = {}
         self.roster_cache = {}  # key: jid, value: dict with "timestamp" and "roster"
         self.presence_map = {}  # inverted roster: key: jid, value: set of entities who has this jid in roster (with presence of "from" or "both")
-        self.server = None
 
     @property
     def permissions(self):
@@ -83,9 +79,9 @@
             if IPubSubService.providedBy(handler):
                 self._pubsub_service = handler
                 break
-        self._backend = self.parent.parent.getServiceNamed('backend')
+        self.backend = self.parent.parent.getServiceNamed('backend')
         self.xmlstream.addObserver(PRIV_ENT_ADV_XPATH, self.onAdvertise)
-        self.xmlstream.addObserver('/presence', self.onPresence)
+        self.xmlstream.addObserver('/presence', self._onPresence)
 
     def onAdvertise(self, message):
         """Managage the <message/> advertising privileges
@@ -175,7 +171,7 @@
 
         main_message = domish.Element((None, "message"))
         if to_jid is None:
-            to_jid = self.server_jid
+            to_jid = self.backend.server_jid
         main_message['to'] = to_jid.full()
         privilege_elt = main_message.addElement((PRIV_ENT_NS, 'privilege'))
         forwarded_elt = privilege_elt.addElement((FORWARDED_NS, 'forwarded'))
@@ -238,18 +234,15 @@
 
     ## presence ##
 
-    @defer.inlineCallbacks
-    def onPresence(self, presence_elt):
-        if self.server is None:
-            # FIXME: we use a hack supposing that our delegation come from hostname
-            #        and we are a component named [name].hostname
-            #        but we need to manage properly allowed servers
-            # TODO: do proper origin security check
-            _, self.server = presence_elt['to'].split('.', 1)
+    def _onPresence(self, presence_elt: domish.Element) -> None:
+        defer.ensureDeferred(self.onPresence(presence_elt))
+
+    async def onPresence(self, presence_elt: domish.Element) -> None:
         from_jid = jid.JID(presence_elt['from'])
         from_jid_bare = from_jid.userhostJID()
-        if from_jid.host == self.server and from_jid_bare not in self.roster_cache:
-            roster = yield self.getRoster(from_jid_bare)
+        if ((jid.JID(from_jid.host) == self.backend.server_jid
+             and from_jid_bare not in self.roster_cache)):
+            roster = await self.getRoster(from_jid_bare)
             timestamp = time.time()
             self.roster_cache[from_jid_bare] = {'timestamp': timestamp,
                                                 'roster': roster,