changeset 387:04e7dcc436ca

backend: admins can delete node, change schema, change config or delete items even if they are not owner of a node
author Goffi <goffi@goffi.org>
date Tue, 12 Feb 2019 21:10:00 +0100
parents 0fedfb5cd7c7
children 1c13ba86a421
files CHANGELOG src/backend.py
diffstat 2 files changed, 26 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG	Wed Feb 06 09:26:46 2019 +0100
+++ b/CHANGELOG	Tue Feb 12 21:10:00 2019 +0100
@@ -13,6 +13,7 @@
     - pubsub admin experimental feature (publish item and specify the publisher, only for admin users)
     - SàT Pubsub can now be configured using the same config file as SàT itself, i.e. "sat.conf"
     - new "admins_jids_list" setting, to specify a comma separated list of admin bare jids.
+    - admins can delete node, change schema, change config or delete items even if they are not owner of a node
     - MAM: filtering by categories
     - MAM and RSM various improvments
     - replaced sat.tmp by new independent sat_tmp module, so now SàT Pubsub can be used independently of SàT
--- a/src/backend.py	Wed Feb 06 09:26:46 2019 +0100
+++ b/src/backend.py	Tue Feb 12 21:10:00 2019 +0100
@@ -168,6 +168,11 @@
         self.storage = storage
         self._callbackList = []
         self.config = config
+        self.admins = config[u'admins_jids_list']
+
+    def isAdmin(self, entity_jid):
+        """Return True if an entity is an administrator"""
+        return entity_jid.userhostJID() in self.admins
 
     def supportsPublishOptions(self):
         return True
@@ -615,13 +620,13 @@
 
         d = self.storage.getNode(nodeIdentifier, pep, recipient)
         d.addCallback(_getAffiliation, requestor)
-        d.addCallback(self._doSetNodeConfiguration, options)
+        d.addCallback(self._doSetNodeConfiguration, requestor, options)
         return d
 
-    def _doSetNodeConfiguration(self, result, options):
+    def _doSetNodeConfiguration(self, result, requestor, options):
         node, affiliation = result
 
-        if affiliation != 'owner':
+        if affiliation != 'owner' and not self.isAdmin(requestor):
             raise error.Forbidden()
 
         return node.setConfiguration(options)
@@ -650,13 +655,13 @@
 
         d = self.storage.getNode(nodeIdentifier, pep, recipient)
         d.addCallback(_getAffiliation, requestor)
-        d.addCallback(self._doSetNodeSchema, schema)
+        d.addCallback(self._doSetNodeSchema, requestor, schema)
         return d
 
-    def _doSetNodeSchema(self, result, schema):
+    def _doSetNodeSchema(self, result, requestor, schema):
         node, affiliation = result
 
-        if affiliation != 'owner':
+        if affiliation != 'owner' and not self.isAdmin(requestor):
             raise error.Forbidden()
 
         return node.setSchema(schema)
@@ -667,13 +672,13 @@
     def getAffiliationsOwner(self, nodeIdentifier, requestor, pep, recipient):
         d = self.storage.getNode(nodeIdentifier, pep, recipient)
         d.addCallback(_getAffiliation, requestor)
-        d.addCallback(self._doGetAffiliationsOwner)
+        d.addCallback(self._doGetAffiliationsOwner, requestor)
         return d
 
-    def _doGetAffiliationsOwner(self, result):
+    def _doGetAffiliationsOwner(self, result, requestor):
         node, affiliation = result
 
-        if affiliation != 'owner':
+        if affiliation != 'owner' and not self.isAdmin(requestor):
             raise error.Forbidden()
         return node.getAffiliations()
 
@@ -690,7 +695,7 @@
         # TODO: return error with failed affiliations in case of failure
         node, requestor_affiliation = result
 
-        if requestor_affiliation != 'owner':
+        if requestor_affiliation != 'owner' and not self.isAdmin(requestor):
             raise error.Forbidden()
 
         # we don't allow requestor to change its own affiliation
@@ -716,13 +721,13 @@
     def getSubscriptionsOwner(self, nodeIdentifier, requestor, pep, recipient):
         d = self.storage.getNode(nodeIdentifier, pep, recipient)
         d.addCallback(_getAffiliation, requestor)
-        d.addCallback(self._doGetSubscriptionsOwner)
+        d.addCallback(self._doGetSubscriptionsOwner, requestor)
         return d
 
-    def _doGetSubscriptionsOwner(self, result):
+    def _doGetSubscriptionsOwner(self, result, requestor):
         node, affiliation = result
 
-        if affiliation != 'owner':
+        if affiliation != 'owner' and not self.isAdmin(requestor):
             raise error.Forbidden()
         return node.getSubscriptions()
 
@@ -743,7 +748,7 @@
         # TODO: return error with failed subscriptions in case of failure
         node, requestor_affiliation = result
 
-        if requestor_affiliation != 'owner':
+        if requestor_affiliation != 'owner' and not self.isAdmin(requestor):
             raise error.Forbidden()
 
         d_list = []
@@ -1121,14 +1126,14 @@
     def purgeNode(self, nodeIdentifier, requestor, pep, recipient):
         d = self.storage.getNode(nodeIdentifier, pep, recipient)
         d.addCallback(_getAffiliation, requestor)
-        d.addCallback(self._doPurge)
+        d.addCallback(self._doPurge, requestor)
         return d
 
-    def _doPurge(self, result):
+    def _doPurge(self, result, requestor):
         node, affiliation = result
         persistItems = node.getConfiguration()[const.OPT_PERSIST_ITEMS]
 
-        if affiliation != 'owner':
+        if affiliation != 'owner' and not self.isAdmin(requestor):
             raise error.Forbidden()
 
         if not persistItems:
@@ -1156,13 +1161,13 @@
     def deleteNode(self, nodeIdentifier, requestor, pep, recipient, redirectURI=None):
         d = self.storage.getNode(nodeIdentifier, pep, recipient)
         d.addCallback(_getAffiliation, requestor)
-        d.addCallback(self._doPreDelete, redirectURI, pep, recipient)
+        d.addCallback(self._doPreDelete, requestor, redirectURI, pep, recipient)
         return d
 
-    def _doPreDelete(self, result, redirectURI, pep, recipient):
+    def _doPreDelete(self, result, requestor, redirectURI, pep, recipient):
         node, affiliation = result
 
-        if affiliation != 'owner':
+        if affiliation != 'owner' and not self.isAdmin(requestor):
             raise error.Forbidden()
 
         data = {'node': node,