Mercurial > libervia-backend
comparison sat/plugins/plugin_exp_pubsub_schema.py @ 2959:989b622faff6
plugins schema, tickets, merge_requests: use serialised data for extra dict + some cosmetic changes
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 14 Jun 2019 12:37:34 +0200 |
parents | e2cb04b381bb |
children | ab2696e34d29 |
comparison
equal
deleted
inserted
replaced
2958:e2cb04b381bb | 2959:989b622faff6 |
---|---|
15 # GNU Affero General Public License for more details. | 15 # GNU Affero General Public License for more details. |
16 | 16 |
17 # You should have received a copy of the GNU Affero General Public License | 17 # You should have received a copy of the GNU Affero General Public License |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | 19 |
20 from collections import Iterable | |
21 import copy | |
22 import itertools | |
23 from zope.interface import implements | |
24 from twisted.words.protocols.jabber import jid | |
25 from twisted.words.protocols.jabber.xmlstream import XMPPHandler | |
26 from twisted.internet import defer | |
27 from wokkel import disco, iwokkel | |
28 from wokkel import data_form | |
29 from wokkel import generic | |
20 from sat.core.i18n import _ | 30 from sat.core.i18n import _ |
21 from sat.core import exceptions | 31 from sat.core import exceptions |
22 from sat.core.constants import Const as C | 32 from sat.core.constants import Const as C |
23 from sat.tools import xml_tools | 33 from sat.tools import xml_tools |
24 from sat.tools import utils | 34 from sat.tools import utils |
25 from sat.tools.common import date_utils | 35 from sat.tools.common import date_utils |
26 from twisted.words.protocols.jabber import jid | 36 from sat.tools.common import data_format |
27 from twisted.words.protocols.jabber.xmlstream import XMPPHandler | |
28 from twisted.internet import defer | |
29 from sat.core.log import getLogger | 37 from sat.core.log import getLogger |
30 | 38 |
31 log = getLogger(__name__) | 39 log = getLogger(__name__) |
32 from wokkel import disco, iwokkel | 40 |
33 from wokkel import data_form | 41 NS_SCHEMA = u"https://salut-a-toi/protocol/schema:0" |
34 from wokkel import generic | |
35 from zope.interface import implements | |
36 from collections import Iterable | |
37 import copy | |
38 import itertools | |
39 | |
40 NS_SCHEMA = "https://salut-a-toi/protocol/schema:0" | |
41 | 42 |
42 PLUGIN_INFO = { | 43 PLUGIN_INFO = { |
43 C.PI_NAME: "PubSub Schema", | 44 C.PI_NAME: u"PubSub Schema", |
44 C.PI_IMPORT_NAME: "PUBSUB_SCHEMA", | 45 C.PI_IMPORT_NAME: u"PUBSUB_SCHEMA", |
45 C.PI_TYPE: "EXP", | 46 C.PI_TYPE: u"EXP", |
46 C.PI_PROTOCOLS: [], | 47 C.PI_PROTOCOLS: [], |
47 C.PI_DEPENDENCIES: ["XEP-0060", "IDENTITY"], | 48 C.PI_DEPENDENCIES: [u"XEP-0060", u"IDENTITY"], |
48 C.PI_MAIN: "PubsubSchema", | 49 C.PI_MAIN: u"PubsubSchema", |
49 C.PI_HANDLER: "yes", | 50 C.PI_HANDLER: u"yes", |
50 C.PI_DESCRIPTION: _("""Handle Pubsub data schemas"""), | 51 C.PI_DESCRIPTION: _(u"""Handle Pubsub data schemas"""), |
51 } | 52 } |
52 | 53 |
53 | 54 |
54 class PubsubSchema(object): | 55 class PubsubSchema(object): |
55 def __init__(self, host): | 56 def __init__(self, host): |
508 service = None if not service else jid.JID(service) | 509 service = None if not service else jid.JID(service) |
509 if schema: | 510 if schema: |
510 schema = generic.parseXml(schema.encode("utf-8")) | 511 schema = generic.parseXml(schema.encode("utf-8")) |
511 else: | 512 else: |
512 schema = None | 513 schema = None |
513 if extra and u"update" in extra: | 514 extra = data_format.deserialise(extra) |
514 extra[u"update"] = C.bool(extra[u"update"]) | |
515 return client, service, node or None, schema, item_id or None, extra | 515 return client, service, node or None, schema, item_id or None, extra |
516 | |
517 @defer.inlineCallbacks | |
518 def copyMissingValues(self, client, service, node, item_id, form_ns, values): | |
519 """Retrieve values existing in original item and missing in update | |
520 | |
521 Existing item will be retrieve, and values not already specified in values will | |
522 be filled | |
523 @param service: same as for [XEP_0060.getItems] | |
524 @param node: same as for [XEP_0060.getItems] | |
525 @param item_id(unicode): id of the item to retrieve | |
526 @param form_ns (unicode, None): namespace of the form | |
527 @param values(dict): values to fill | |
528 This dict will be modified *in place* to fill value present in existing | |
529 item and missing in the dict. | |
530 """ | |
531 try: | |
532 # we get previous item | |
533 items_data = yield self._p.getItems( | |
534 client, service, node, item_ids=[item_id] | |
535 ) | |
536 item_elt = items_data[0][0] | |
537 except Exception as e: | |
538 log.warning( | |
539 _(u"Can't get previous item, update ignored: {reason}").format( | |
540 reason=e | |
541 ) | |
542 ) | |
543 else: | |
544 # and parse it | |
545 form = data_form.findForm(item_elt, form_ns) | |
546 if form is None: | |
547 log.warning( | |
548 _( | |
549 u"Can't parse previous item, update ignored: data form not found" | |
550 ).format(reason=e) | |
551 ) | |
552 else: | |
553 for name, field in form.fields.iteritems(): | |
554 if name not in values: | |
555 values[name] = u"\n".join(unicode(v) for v in field.values) | |
516 | 556 |
517 def _set(self, service, node, values, schema=None, item_id=None, extra=None, | 557 def _set(self, service, node, values, schema=None, item_id=None, extra=None, |
518 default_node=None, form_ns=None, fill_author=True, | 558 default_node=None, form_ns=None, fill_author=True, |
519 profile_key=C.PROF_KEY_NONE): | 559 profile_key=C.PROF_KEY_NONE): |
520 """Bridge method to set item in node with schema | 560 """Bridge method to set item in node with schema |
559 needed when an update is done | 599 needed when an update is done |
560 @param default_node(unicode, None): value to use if node is not set | 600 @param default_node(unicode, None): value to use if node is not set |
561 other arguments are same as for [self._s.sendDataFormItem] | 601 other arguments are same as for [self._s.sendDataFormItem] |
562 @return (unicode): id of the created item | 602 @return (unicode): id of the created item |
563 """ | 603 """ |
604 if extra is None: | |
605 extra = {} | |
564 if not node: | 606 if not node: |
565 if default_node is None: | 607 if default_node is None: |
566 raise ValueError(_(u"default_node must be set if node is not set")) | 608 raise ValueError(_(u"default_node must be set if node is not set")) |
567 node = default_node | 609 node = default_node |
568 now = utils.xmpp_date() | 610 now = utils.xmpp_date() |
571 elif extra.get(u"update", False): | 613 elif extra.get(u"update", False): |
572 if item_id is None: | 614 if item_id is None: |
573 raise exceptions.DataError( | 615 raise exceptions.DataError( |
574 _(u'if extra["update"] is set, item_id must be set too') | 616 _(u'if extra["update"] is set, item_id must be set too') |
575 ) | 617 ) |
576 try: | 618 yield self.copyMissingValues(client, service, node, item_id, form_ns, values) |
577 # we get previous item | |
578 items_data = yield self._p.getItems( | |
579 client, service, node, item_ids=[item_id] | |
580 ) | |
581 item_elt = items_data[0][0] | |
582 except Exception as e: | |
583 log.warning( | |
584 _(u"Can't get previous item, update ignored: {reason}").format( | |
585 reason=e | |
586 ) | |
587 ) | |
588 else: | |
589 # and parse it | |
590 form = data_form.findForm(item_elt, form_ns) | |
591 if form is None: | |
592 log.warning( | |
593 _( | |
594 u"Can't parse previous item, update ignored: data form not found" | |
595 ).format(reason=e) | |
596 ) | |
597 else: | |
598 for name, field in form.fields.iteritems(): | |
599 if name not in values: | |
600 values[name] = u"\n".join(unicode(v) for v in field.values) | |
601 | 619 |
602 values["updated"] = now | 620 values["updated"] = now |
603 if fill_author: | 621 if fill_author: |
604 if not values.get("author"): | 622 if not values.get("author"): |
605 identity = yield self._i.getIdentity(client, client.jid) | 623 identity = yield self._i.getIdentity(client, client.jid) |