Mercurial > libervia-pubsub
diff sat_pubsub/schema.py @ 352:efbdca10f0fb
schema: node schema implementation
node schema is an experimental (not standard yet, protoXEP should follow) feature allowing to attach a data schema to a node.
This commit implement it and method needed to retrieve/set a schema.
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 08 Sep 2017 08:02:05 +0200 |
parents | |
children | a92f482ff14f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sat_pubsub/schema.py Fri Sep 08 08:02:05 2017 +0200 @@ -0,0 +1,106 @@ +#!/usr/bin/python +#-*- coding: utf-8 -*- +# +# Copyright (c) 2015 Jérôme Poisson + + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# --- + +# This module implements node schema + +from twisted.words.protocols.jabber import jid +from twisted.words.xish import domish +from wokkel import disco, iwokkel +from wokkel.iwokkel import IPubSubService +from wokkel.subprotocols import XMPPHandler, IQHandlerMixin +from wokkel import data_form, pubsub +from zope.interface import implements +from sat_pubsub import const + +QUERY_SCHEMA = "/pubsub[@xmlns='" + const.NS_SCHEMA + "']" + + +class SchemaHandler(XMPPHandler, IQHandlerMixin): + implements(iwokkel.IDisco) + iqHandlers = {"/iq[@type='get']" + QUERY_SCHEMA: 'onSchemaGet', + "/iq[@type='set']" + QUERY_SCHEMA: 'onSchemaSet'} + + def __init__(self): + super(SchemaHandler, self).__init__() + self.pubsub_service = None + + def connectionInitialized(self): + for handler in self.parent.handlers: + if IPubSubService.providedBy(handler): + self.pubsub_service = handler + break + self.backend = self.parent.parent.getServiceNamed('backend') + self.xmlstream.addObserver("/iq[@type='get' or @type='set']" + QUERY_SCHEMA, self.handleRequest) + + def _getNodeSchemaCb(self, x_elt, nodeIdentifier): + schema_elt = domish.Element((const.NS_SCHEMA, 'schema')) + schema_elt['node'] = nodeIdentifier + if x_elt is not None: + assert x_elt.uri == u'jabber:x:data' + schema_elt.addChild(x_elt) + return schema_elt + + def onSchemaGet(self, iq_elt): + try: + schema_elt = next(iq_elt.pubsub.elements(const.NS_SCHEMA, 'schema')) + nodeIdentifier = schema_elt['node'] + except StopIteration: + raise pubsub.BadRequest(text='missing schema element') + except KeyError: + raise pubsub.BadRequest(text='missing node') + pep = iq_elt.delegated + recipient = jid.JID(iq_elt['to']) + d = self.backend.getNodeSchema(nodeIdentifier, + pep, + recipient) + d.addCallback(self._getNodeSchemaCb, nodeIdentifier) + return d.addErrback(self.pubsub_service.resource._mapErrors) + + def onSchemaSet(self, iq_elt): + try: + schema_elt = next(iq_elt.pubsub.elements(const.NS_SCHEMA, 'schema')) + nodeIdentifier = schema_elt['node'] + except StopIteration: + raise pubsub.BadRequest(text='missing schema element') + except KeyError: + raise pubsub.BadRequest(text='missing node') + requestor = jid.JID(iq_elt['from']) + pep = iq_elt.delegated + recipient = jid.JID(iq_elt['to']) + for x_elt in schema_elt.elements(data_form.NS_X_DATA, u'x'): + schema_form = data_form.Form.fromElement(x_elt) + if schema_form.formNamespace == const.NS_SCHEMA_FORM: + break + else: + # no schema form has been found + x_elt = None + d = self.backend.setNodeSchema(nodeIdentifier, + x_elt, + requestor, + pep, + recipient) + return d.addErrback(self.pubsub_service.resource._mapErrors) + + def getDiscoInfo(self, requestor, service, nodeIdentifier=''): + return [disco.DiscoFeature(const.NS_SCHEMA)] + + def getDiscoItems(self, requestor, service, nodeIdentifier=''): + return []