# HG changeset patch # User Goffi # Date 1550002200 -3600 # Node ID 04e7dcc436cade256cf48fefcf4f5d804198043a # Parent 0fedfb5cd7c7cdff4fb276bd238ed1c8090035ec backend: admins can delete node, change schema, change config or delete items even if they are not owner of a node diff -r 0fedfb5cd7c7 -r 04e7dcc436ca CHANGELOG --- 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 diff -r 0fedfb5cd7c7 -r 04e7dcc436ca src/backend.py --- 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,