352
|
1 #!/usr/bin/python |
|
2 #-*- coding: utf-8 -*- |
|
3 # |
|
4 # Copyright (c) 2015 Jérôme Poisson |
|
5 |
|
6 |
|
7 # This program is free software: you can redistribute it and/or modify |
|
8 # it under the terms of the GNU Affero General Public License as published by |
|
9 # the Free Software Foundation, either version 3 of the License, or |
|
10 # (at your option) any later version. |
|
11 |
|
12 # This program is distributed in the hope that it will be useful, |
|
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
15 # GNU Affero General Public License for more details. |
|
16 |
|
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/>. |
|
19 |
|
20 # --- |
|
21 |
|
22 # This module implements node schema |
|
23 |
|
24 from twisted.words.protocols.jabber import jid |
|
25 from twisted.words.xish import domish |
|
26 from wokkel import disco, iwokkel |
|
27 from wokkel.iwokkel import IPubSubService |
|
28 from wokkel.subprotocols import XMPPHandler, IQHandlerMixin |
|
29 from wokkel import data_form, pubsub |
|
30 from zope.interface import implements |
|
31 from sat_pubsub import const |
|
32 |
|
33 QUERY_SCHEMA = "/pubsub[@xmlns='" + const.NS_SCHEMA + "']" |
|
34 |
|
35 |
|
36 class SchemaHandler(XMPPHandler, IQHandlerMixin): |
|
37 implements(iwokkel.IDisco) |
|
38 iqHandlers = {"/iq[@type='get']" + QUERY_SCHEMA: 'onSchemaGet', |
|
39 "/iq[@type='set']" + QUERY_SCHEMA: 'onSchemaSet'} |
|
40 |
|
41 def __init__(self): |
|
42 super(SchemaHandler, self).__init__() |
|
43 self.pubsub_service = None |
|
44 |
|
45 def connectionInitialized(self): |
|
46 for handler in self.parent.handlers: |
|
47 if IPubSubService.providedBy(handler): |
|
48 self.pubsub_service = handler |
|
49 break |
|
50 self.backend = self.parent.parent.getServiceNamed('backend') |
|
51 self.xmlstream.addObserver("/iq[@type='get' or @type='set']" + QUERY_SCHEMA, self.handleRequest) |
|
52 |
|
53 def _getNodeSchemaCb(self, x_elt, nodeIdentifier): |
|
54 schema_elt = domish.Element((const.NS_SCHEMA, 'schema')) |
|
55 schema_elt['node'] = nodeIdentifier |
|
56 if x_elt is not None: |
|
57 assert x_elt.uri == u'jabber:x:data' |
|
58 schema_elt.addChild(x_elt) |
|
59 return schema_elt |
|
60 |
|
61 def onSchemaGet(self, iq_elt): |
|
62 try: |
|
63 schema_elt = next(iq_elt.pubsub.elements(const.NS_SCHEMA, 'schema')) |
|
64 nodeIdentifier = schema_elt['node'] |
|
65 except StopIteration: |
|
66 raise pubsub.BadRequest(text='missing schema element') |
|
67 except KeyError: |
|
68 raise pubsub.BadRequest(text='missing node') |
|
69 pep = iq_elt.delegated |
|
70 recipient = jid.JID(iq_elt['to']) |
|
71 d = self.backend.getNodeSchema(nodeIdentifier, |
|
72 pep, |
|
73 recipient) |
|
74 d.addCallback(self._getNodeSchemaCb, nodeIdentifier) |
|
75 return d.addErrback(self.pubsub_service.resource._mapErrors) |
|
76 |
|
77 def onSchemaSet(self, iq_elt): |
|
78 try: |
|
79 schema_elt = next(iq_elt.pubsub.elements(const.NS_SCHEMA, 'schema')) |
|
80 nodeIdentifier = schema_elt['node'] |
|
81 except StopIteration: |
|
82 raise pubsub.BadRequest(text='missing schema element') |
|
83 except KeyError: |
|
84 raise pubsub.BadRequest(text='missing node') |
|
85 requestor = jid.JID(iq_elt['from']) |
|
86 pep = iq_elt.delegated |
|
87 recipient = jid.JID(iq_elt['to']) |
|
88 for x_elt in schema_elt.elements(data_form.NS_X_DATA, u'x'): |
|
89 schema_form = data_form.Form.fromElement(x_elt) |
|
90 if schema_form.formNamespace == const.NS_SCHEMA_FORM: |
|
91 break |
|
92 else: |
|
93 # no schema form has been found |
|
94 x_elt = None |
|
95 d = self.backend.setNodeSchema(nodeIdentifier, |
|
96 x_elt, |
|
97 requestor, |
|
98 pep, |
|
99 recipient) |
|
100 return d.addErrback(self.pubsub_service.resource._mapErrors) |
|
101 |
|
102 def getDiscoInfo(self, requestor, service, nodeIdentifier=''): |
|
103 return [disco.DiscoFeature(const.NS_SCHEMA)] |
|
104 |
|
105 def getDiscoItems(self, requestor, service, nodeIdentifier=''): |
|
106 return [] |