# HG changeset patch # User Goffi # Date 1560369110 -7200 # Node ID 1dc606612405d82fc4c8b03675959221505912da # Parent 724e39d596a967fe15cbb1f114b375f7f4c95aef implemented experimental "consistent_publisher" option: /!\ pgsql schema needs to be updated /!\ New "consistent_publisher" option has been implemented to allow node owners + admins to modify an item while preserving the original publisher. This way, original publisher can still edit the item. In addition to `consistent_publisher`, `max_items` has been added to PGQSL schema to prepare for future implementation. diff -r 724e39d596a9 -r 1dc606612405 db/pubsub.sql --- a/db/pubsub.sql Thu May 23 08:58:29 2019 +0200 +++ b/db/pubsub.sql Wed Jun 12 21:51:50 2019 +0200 @@ -13,7 +13,10 @@ CHECK (access_model IN ('open', 'presence', 'publisher-roster', 'whitelist', 'publish-only', 'self-publisher')), persist_items boolean, deliver_payloads boolean NOT NULL DEFAULT TRUE, + max_items integer NOT NULL DEFAULT 0 + CHECK (max_items >= 0), serial_ids boolean NOT NULL DEFAULT FALSE, + consistent_publisher boolean NOT NULL DEFAULT FALSE, send_last_published_item text NOT NULL DEFAULT 'on_sub' CHECK (send_last_published_item IN ('never', 'on_sub')), publish_model text NOT NULL DEFAULT 'publishers' @@ -102,4 +105,4 @@ value text ); -INSERT INTO metadata VALUES ('version', '4'); +INSERT INTO metadata VALUES ('version', '5'); diff -r 724e39d596a9 -r 1dc606612405 db/sat_pubsub_update_0_1.sql --- a/db/sat_pubsub_update_0_1.sql Thu May 23 08:58:29 2019 +0200 +++ b/db/sat_pubsub_update_0_1.sql Wed Jun 12 21:51:50 2019 +0200 @@ -6,7 +6,7 @@ BEGIN SELECT value INTO ver FROM metadata WHERE key='version'; IF FOUND THEN - RAISE EXCEPTION 'This update file need to be applied on older database, you don''t have to use it'; + RAISE EXCEPTION 'This update file needs to be applied on older database, you don''t have to use it'; END IF; END$$; \unset ON_ERROR_STOP diff -r 724e39d596a9 -r 1dc606612405 db/sat_pubsub_update_1_2.sql --- a/db/sat_pubsub_update_1_2.sql Thu May 23 08:58:29 2019 +0200 +++ b/db/sat_pubsub_update_1_2.sql Wed Jun 12 21:51:50 2019 +0200 @@ -6,7 +6,7 @@ BEGIN SELECT value INTO ver FROM metadata WHERE key='version'; IF NOT FOUND OR ver!='1' THEN - RAISE EXCEPTION 'This update file need to be applied on database schema version 1, you use version %',ver; + RAISE EXCEPTION 'This update file needs to be applied on database schema version 1, you use version %',ver; END IF; END$$; \unset ON_ERROR_STOP diff -r 724e39d596a9 -r 1dc606612405 db/sat_pubsub_update_2_3.sql --- a/db/sat_pubsub_update_2_3.sql Thu May 23 08:58:29 2019 +0200 +++ b/db/sat_pubsub_update_2_3.sql Wed Jun 12 21:51:50 2019 +0200 @@ -6,7 +6,7 @@ BEGIN SELECT value INTO ver FROM metadata WHERE key='version'; IF NOT FOUND OR ver!='2' THEN - RAISE EXCEPTION 'This update file need to be applied on database schema version 2, you use version %',ver; + RAISE EXCEPTION 'This update file needs to be applied on database schema version 2, you use version %',ver; END IF; END$$; \unset ON_ERROR_STOP diff -r 724e39d596a9 -r 1dc606612405 db/sat_pubsub_update_3_4.sql --- a/db/sat_pubsub_update_3_4.sql Thu May 23 08:58:29 2019 +0200 +++ b/db/sat_pubsub_update_3_4.sql Wed Jun 12 21:51:50 2019 +0200 @@ -6,7 +6,7 @@ BEGIN SELECT value INTO ver FROM metadata WHERE key='version'; IF NOT FOUND OR ver!='3' THEN - RAISE EXCEPTION 'This update file need to be applied on database schema version 3, you use version %',ver; + RAISE EXCEPTION 'This update file needs to be applied on database schema version 3, you use version %',ver; END IF; END$$; \unset ON_ERROR_STOP diff -r 724e39d596a9 -r 1dc606612405 db/sat_pubsub_update_4_5.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/db/sat_pubsub_update_4_5.sql Wed Jun 12 21:51:50 2019 +0200 @@ -0,0 +1,20 @@ +-- we check version of the database before doing anything +-- and stop execution if not good +\set ON_ERROR_STOP +DO $$ +DECLARE ver text; +BEGIN + SELECT value INTO ver FROM metadata WHERE key='version'; + IF NOT FOUND OR ver!='4' THEN + RAISE EXCEPTION 'This update file needs to be applied on database schema version 4, you use version %',ver; + END IF; +END$$; +\unset ON_ERROR_STOP +-- end of version check + +/* new "max_items" and "consistent publisher" options */ +ALTER TABLE nodes ADD COLUMN max_items integer NOT NULL DEFAULT 0 + CHECK (max_items >= 0); +ALTER TABLE nodes ADD COLUMN consistent_publisher boolean NOT NULL DEFAULT FALSE; + +UPDATE metadata SET value='5' WHERE key='version'; diff -r 724e39d596a9 -r 1dc606612405 src/backend.py --- a/src/backend.py Thu May 23 08:58:29 2019 +0200 +++ b/src/backend.py Wed Jun 12 21:51:50 2019 +0200 @@ -176,6 +176,9 @@ const.OPT_SERIAL_IDS: {"type": "boolean", "label": "Use serial ids"}, + const.OPT_CONSISTENT_PUBLISHER: + {"type": "boolean", + "label": "Keep publisher on update"}, } subscriptionOptions = { @@ -379,8 +382,10 @@ item_elt.addChild(item_form.toElement()) def _checkOverwrite(self, node, itemIdentifiers, publisher): - """Check that the itemIdentifiers correspond to items published - by the current publisher""" + """Check that publisher can overwrite items + + current publisher must correspond to each item publisher + """ def doCheck(item_pub_map): for item_publisher in item_pub_map.itervalues(): if item_publisher.userhost() != publisher.userhost(): @@ -445,10 +450,30 @@ if persistItems: - if check_overwrite and affiliation != 'owner' and not self.isAdmin(requestor): - # we don't want a publisher to overwrite the item - # of an other publisher - yield self._checkOverwrite(node, [item['id'] for item in items if item.getAttribute('id')], requestor) + if check_overwrite: + itemIdentifiers = [item['id'] for item in items + if item.getAttribute('id')] + + if affiliation == 'owner' or self.isAdmin(requestor): + if configuration[const.OPT_CONSISTENT_PUBLISHER]: + pub_map = yield node.getItemsPublishers(itemIdentifiers) + publishers = set(pub_map.values()) + if len(publishers) != 1: + # TODO: handle multiple items publishing (from several + # publishers) + raise error.NoPublishing( + u"consistent_publisher is currently only possible when " + u"publishing items from a single publisher. Try to " + u"publish one item at a time") + # we replace requestor and new payload's publisher by original + # item publisher to keep publisher consistent + requestor = publishers.pop() + for item in items: + item['publisher'] = requestor.full() + else: + # we don't want a publisher to overwrite the item + # of an other publisher + yield self._checkOverwrite(node, itemIdentifiers, requestor) # TODO: check conflict and recalculate max id if serial_ids is set yield node.storeItems(items_data, requestor) diff -r 724e39d596a9 -r 1dc606612405 src/const.py --- a/src/const.py Thu May 23 08:58:29 2019 +0200 +++ b/src/const.py Wed Jun 12 21:51:50 2019 +0200 @@ -66,6 +66,7 @@ OPT_SEND_LAST_PUBLISHED_ITEM = "pubsub#send_last_published_item" OPT_PUBLISH_MODEL = 'pubsub#publish_model' OPT_SERIAL_IDS = 'pubsub#serial_ids' +OPT_CONSISTENT_PUBLISHER = 'pubsub#consistent_publisher' VAL_AMODEL_OPEN = 'open' VAL_AMODEL_PRESENCE = 'presence' VAL_AMODEL_PUBLISHER_ROSTER = 'publisher-roster' diff -r 724e39d596a9 -r 1dc606612405 src/pgsql_storage.py --- a/src/pgsql_storage.py Thu May 23 08:58:29 2019 +0200 +++ b/src/pgsql_storage.py Wed Jun 12 21:51:50 2019 +0200 @@ -79,7 +79,7 @@ parseXml = lambda unicode_data: generic.parseXml(unicode_data.encode('utf-8')) ITEMS_SEQ_NAME = u'node_{node_id}_seq' PEP_COL_NAME = 'pep' -CURRENT_VERSION = '4' +CURRENT_VERSION = '5' # retrieve the maximum integer item id + 1 NEXT_ITEM_ID_QUERY = r"SELECT COALESCE(max(item::integer)+1,1) as val from items where node_id={node_id} and item ~ E'^\\d+$'" @@ -114,6 +114,7 @@ const.OPT_ACCESS_MODEL: const.VAL_AMODEL_DEFAULT, const.OPT_PUBLISH_MODEL: const.VAL_PMODEL_DEFAULT, const.OPT_SERIAL_IDS: False, + const.OPT_CONSISTENT_PUBLISHER: False, }, 'collection': { const.OPT_DELIVER_PAYLOADS: True, @@ -154,8 +155,9 @@ const.OPT_ACCESS_MODEL:row[6], const.OPT_PUBLISH_MODEL:row[7], const.OPT_SERIAL_IDS:row[8], + const.OPT_CONSISTENT_PUBLISHER:row[9], } - schema = row[9] + schema = row[10] if schema is not None: schema = parseXml(schema) node = LeafNode(row[0], row[1], configuration, schema) @@ -191,6 +193,7 @@ access_model, publish_model, serial_ids, + consistent_publisher, schema::text, pep FROM nodes @@ -212,6 +215,7 @@ access_model, publish_model, serial_ids, + consistent_publisher, schema::text, pep FROM nodes @@ -265,10 +269,11 @@ access_model, publish_model, serial_ids, + consistent_publisher, schema, pep) VALUES - (%s, 'leaf', %s, %s, %s, %s, %s, %s, %s, %s)""", + (%s, 'leaf', %s, %s, %s, %s, %s, %s, %s, %s, %s)""", (nodeIdentifier, config['pubsub#persist_items'], config['pubsub#deliver_payloads'], @@ -276,6 +281,7 @@ config[const.OPT_ACCESS_MODEL], config[const.OPT_PUBLISH_MODEL], config[const.OPT_SERIAL_IDS], + config[const.OPT_CONSISTENT_PUBLISHER], schema, recipient.userhost() if pep else None ) @@ -535,7 +541,8 @@ send_last_published_item=%s, access_model=%s, publish_model=%s, - serial_ids=%s + serial_ids=%s, + consistent_publisher=%s WHERE node_id=%s""", (config[const.OPT_PERSIST_ITEMS], config[const.OPT_DELIVER_PAYLOADS], @@ -543,6 +550,7 @@ config[const.OPT_ACCESS_MODEL], config[const.OPT_PUBLISH_MODEL], config[const.OPT_SERIAL_IDS], + config[const.OPT_CONSISTENT_PUBLISHER], self.nodeDbId)) def _setCachedConfiguration(self, void, config):