changeset 260:f0cd02c032b3

publish model management
author Goffi <goffi@goffi.org>
date Mon, 06 May 2013 00:26:37 +0200
parents 6fe7da6b4b32
children 65d4fed44edf
files db/pubsub.sql sat_pubsub/backend.py sat_pubsub/const.py sat_pubsub/pgsql_storage.py
diffstat 4 files changed, 59 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/db/pubsub.sql	Mon May 06 00:11:44 2013 +0200
+++ b/db/pubsub.sql	Mon May 06 00:26:37 2013 +0200
@@ -13,7 +13,9 @@
     persist_items boolean,
     deliver_payloads boolean NOT NULL DEFAULT TRUE,
     send_last_published_item text NOT NULL DEFAULT 'on_sub'
-        CHECK (send_last_published_item IN ('never', 'on_sub'))
+        CHECK (send_last_published_item IN ('never', 'on_sub')),
+    publish_model text NOT NULL DEFAULT 'publishers'
+        CHECK (publish_model IN ('publishers', 'subscribers', 'open'))
 );
 
 INSERT INTO nodes (node, node_type) values ('', 'collection');
--- a/sat_pubsub/backend.py	Mon May 06 00:11:44 2013 +0200
+++ b/sat_pubsub/backend.py	Mon May 06 00:26:37 2013 +0200
@@ -129,6 +129,15 @@
                 {"type": "list-multi",
                  "label": "Groups of the roster allowed to access the node",
                 },
+            const.OPT_PUBLISH_MODEL:
+                {"type": "list-single",
+                 "label": "Who can publish to this node",
+                 "options": {
+                     const.VAL_PMODEL_OPEN: "Everybody can publish",
+                     const.VAL_PMODEL_PUBLISHERS: "Only owner and publishers can publish",
+                     const.VAL_PMODEL_SUBSCRIBERS: "Everybody which subscribed to the node",
+                     }
+                },
             }
 
     subscriptionOptions = {
@@ -168,6 +177,10 @@
         return True
 
 
+    def supportsPublishModel(self):
+        return True
+
+
     def getNodeType(self, nodeIdentifier):
         d = self.storage.getNode(nodeIdentifier)
         d.addCallback(lambda node: node.getType())
@@ -198,13 +211,35 @@
 
 
     def _checkAuth(self, node, requestor):
-        def check(affiliation, node):
-            if affiliation not in ['owner', 'publisher']:
-                raise error.Forbidden()
-            return node
+        """ Check authorisation of publishing in node for requestor """
+
+        def check(affiliation):
+            d = defer.succeed(node)
+            configuration = node.getConfiguration()
+            publish_model = configuration[const.OPT_PUBLISH_MODEL]
+
+            if (publish_model == const.VAL_PMODEL_PUBLISHERS):
+                if affiliation not in ['owner', 'publisher']:
+                    raise error.Forbidden()
+            elif (publish_model == const.VAL_PMODEL_SUBSCRIBERS):
+                if affiliation not in ['owner', 'publisher']:
+                    # we are in subscribers publish model, we must check that
+                    # the requestor is a subscriber to allow him to publish
+
+                    def checkSubscription(subscribed):
+                        if not subscribed:
+                            raise error.Forbidden()
+                        return node
+
+                    d.addCallback(lambda ignore: node.isSubscribed(requestor))
+                    d.addCallback(checkSubscription)
+            elif publish_model != const.VAL_PMODEL_OPEN:
+                raise Exception('Unexpected value') # publish_model must be publishers (default), subscribers or open.
+
+            return d
 
         d = node.getAffiliation(requestor)
-        d.addCallback(check, node)
+        d.addCallback(check)
         return d
 
     def parseItemConfig(self, item):
@@ -747,6 +782,9 @@
         if self.backend.supportsGroupBlog():
             self.features.append("groupblog")
 
+        # if self.backend.supportsPublishModel():       #XXX: this feature is not really described in XEP-0060, we just can see it in examples
+        #     self.features.append("publish_model")     #     but it's necessary for microblogging comments (see XEP-0277)
+
     def _notify(self, data):
         items = data['items']
         node = data['node']
--- a/sat_pubsub/const.py	Mon May 06 00:11:44 2013 +0200
+++ b/sat_pubsub/const.py	Mon May 06 00:26:37 2013 +0200
@@ -57,7 +57,12 @@
 NS_ITEM_CONFIG = "http://jabber.org/protocol/pubsub#item-config"
 OPT_ACCESS_MODEL = 'pubsub#access_model'
 OPT_ROSTER_GROUPS_ALLOWED = 'pubsub#roster_groups_allowed'
+OPT_PUBLISH_MODEL = 'pubsub#publish_model'
 VAL_AMODEL_OPEN = 'open'
 VAL_AMODEL_ROSTER = 'roster'
 VAL_AMODEL_JID = 'jid'
 VAL_AMODEL_DEFAULT = VAL_AMODEL_OPEN
+VAL_PMODEL_PUBLISHERS = 'publishers'
+VAL_PMODEL_SUBSCRIBERS = 'subscribers'
+VAL_PMODEL_OPEN = 'open'
+VAL_PMODEL_DEFAULT = VAL_PMODEL_PUBLISHERS
--- a/sat_pubsub/pgsql_storage.py	Mon May 06 00:11:44 2013 +0200
+++ b/sat_pubsub/pgsql_storage.py	Mon May 06 00:26:37 2013 +0200
@@ -74,11 +74,13 @@
                 "pubsub#deliver_payloads": True,
                 "pubsub#send_last_published_item": 'on_sub',
                 const.OPT_ACCESS_MODEL: const.VAL_AMODEL_DEFAULT,
+                const.OPT_PUBLISH_MODEL: const.VAL_PMODEL_DEFAULT,
             },
             'collection': {
                 "pubsub#deliver_payloads": True,
                 "pubsub#send_last_published_item": 'on_sub',
                 const.OPT_ACCESS_MODEL: const.VAL_AMODEL_DEFAULT,
+                const.OPT_PUBLISH_MODEL: const.VAL_PMODEL_DEFAULT,
             }
     }
 
@@ -96,6 +98,7 @@
                                  deliver_payloads,
                                  send_last_published_item,
                                  access_model,
+                                 publish_model
                           FROM nodes
                           WHERE node=%s""",
                        (nodeIdentifier,))
@@ -110,6 +113,7 @@
                     'pubsub#deliver_payloads': row[2],
                     'pubsub#send_last_published_item': row[3],
                     const.OPT_ACCESS_MODEL:row[4],
+                    const.OPT_PUBLISH_MODEL:row[5],
                     }
             node = LeafNode(nodeIdentifier, configuration)
             node.dbpool = self.dbpool
@@ -119,6 +123,7 @@
                     'pubsub#deliver_payloads': row[2],
                     'pubsub#send_last_published_item': row[3],
                     const.OPT_ACCESS_MODEL: row[4],
+                    const.OPT_PUBLISH_MODEL:row[5],
                     }
             node = CollectionNode(nodeIdentifier, configuration)
             node.dbpool = self.dbpool
@@ -145,14 +150,15 @@
         try:
             cursor.execute("""INSERT INTO nodes
                               (node, node_type, persist_items,
-                               deliver_payloads, send_last_published_item, access_model)
+                               deliver_payloads, send_last_published_item, access_model, publish_model)
                               VALUES
-                              (%s, 'leaf', %s, %s, %s, %s)""",
+                              (%s, 'leaf', %s, %s, %s, %s, %s)""",
                            (nodeIdentifier,
                             config['pubsub#persist_items'],
                             config['pubsub#deliver_payloads'],
                             config['pubsub#send_last_published_item'],
                             config[const.OPT_ACCESS_MODEL],
+                            config[const.OPT_PUBLISH_MODEL],
                             )
                            )
         except cursor._pool.dbapi.IntegrityError: