diff sat_pubsub/backend.py @ 422:c21f31355ab9

configuration: "max_items" option: "max_items" is implemented using a text-single field, as it is done in the XEP-0060 example (there is no real formal description). When changing the node configuration, the max_items can't be set to a number lower than the total number of items in the node (the configuration will then be rejected), this is to avoid accidental deletion of items.
author Goffi <goffi@goffi.org>
date Tue, 10 Mar 2020 11:11:38 +0100
parents 794593086517
children 5a0ada3b61ca
line wrap: on
line diff
--- a/sat_pubsub/backend.py	Sat Feb 22 13:06:51 2020 +0100
+++ b/sat_pubsub/backend.py	Tue Mar 10 11:11:38 2020 +0100
@@ -138,6 +138,9 @@
             const.OPT_PERSIST_ITEMS:
                 {"type": "boolean",
                  "label": "Persist items to storage"},
+            const.OPT_MAX_ITEMS:
+                {"type": "text-single",
+                 "label": 'number of items to keep ("max" for unlimited)'},
             const.OPT_DELIVER_PAYLOADS:
                 {"type": "boolean",
                  "label": "Deliver payloads with event notifications"},
@@ -670,16 +673,44 @@
 
         d = self.storage.getNode(nodeIdentifier, pep, recipient)
         d.addCallback(_getAffiliation, requestor)
-        d.addCallback(self._doSetNodeConfiguration, requestor, options)
+        d.addCallback(
+            lambda result: defer.ensureDeferred(
+                self._doSetNodeConfiguration(result, requestor, options))
+        )
         return d
 
-    def _doSetNodeConfiguration(self, result, requestor, options):
+    async def _doSetNodeConfiguration(self, result, requestor, options):
         node, affiliation = result
 
         if affiliation != 'owner' and not self.isAdmin(requestor):
             raise error.Forbidden()
 
-        return node.setConfiguration(options)
+        max_items = options.get(const.OPT_MAX_ITEMS, '').strip().lower()
+        if not max_items:
+            pass
+        elif max_items == 'max':
+            # FIXME: we use "0" for max for now, but as "0" may be used as legal value
+            #   in XEP-0060 ("max" is used otherwise), we should use "None" instead.
+            #   This require a schema update, as NULL is not allowed at the moment
+            options.fields[const.OPT_MAX_ITEMS].value = "0"
+        else:
+            # max_items is a number, we have to check that it's not bigger than the
+            # total number of items on this node
+            try:
+                max_items = int(max_items)
+            except ValueError:
+                raise error.InvalidConfigurationValue('Invalid "max_items" value')
+            else:
+                options.fields[const.OPT_MAX_ITEMS].value = str(max_items)
+            if max_items:
+                items_count = await node.getItemsCount(None, True)
+                if max_items < items_count:
+                    raise error.ConstraintFailed(
+                        "\"max_items\" can't be set to a value lower than the total "
+                        "number of items on this node. Please increase \"max_items\" "
+                        "or delete items from this node")
+
+        return await node.setConfiguration(options)
 
     def getNodeSchema(self, nodeIdentifier, pep, recipient):
         if not nodeIdentifier: