source: ralphm-patches/pubsub-create-configure.patch @ 21:6e73325a5473

Last change on this file since 21:6e73325a5473 was 21:6e73325a5473, checked in by Ralph Meijer <ralphm@…>, 11 years ago

Split off data forms changes.

File size: 11.2 KB
RevLine 
[21]1diff -r d64e96596c50 -r 8425a88d49f5 wokkel/pubsub.py
2--- a/wokkel/pubsub.py  Wed Dec 30 21:41:55 2009 +0100
3+++ b/wokkel/pubsub.py  Wed Dec 30 21:42:27 2009 +0100
[19]4@@ -234,7 +234,7 @@
[14]5         'optionsSet': ['nodeOrEmpty', 'jid', 'options'],
6         'subscriptions': [],
7         'affiliations': [],
8-        'create': ['nodeOrNone'],
9+        'create': ['nodeOrNone', 'configureOrNone'],
10         'default': ['default'],
11         'configureGet': ['nodeOrEmpty'],
12         'configureSet': ['nodeOrEmpty', 'configure'],
[21]13@@ -364,6 +364,33 @@
[14]14             raise BadRequest(text="Missing configuration form")
15 
16 
17+    def _parse_configureOrNone(self, verbElement):
18+        """
19+        Parse optional node configuration form in create request.
20+        """
21+        for element in verbElement.parent.elements():
22+            if element.uri == NS_PUBSUB and element.name == 'configure':
23+                form = data_form.findForm(element, NS_PUBSUB_NODE_CONFIG)
24+                if form:
25+                    if form.formType == 'submit':
[20]26+                        self.options = form
[14]27+                    else:
28+                        raise BadRequest(text="Unexpected form type %r" %
29+                                              form.formType)
30+                else:
[20]31+                    form = data_form.Form('submit',
32+                                          formNamespace=NS_PUBSUB_NODE_CONFIG)
33+                    self.options = form
[14]34+
35+
36+    def _render_configureOrNone(self, verbElement):
37+        """
38+        Render optional node configuration form in create request.
39+        """
40+        if self.options is not None:
41+            configure = verbElement.parent.addElement('configure')
[20]42+            configure.addChild(self.options.toElement())
[14]43+
44 
45     def _parse_itemIdentifiers(self, verbElement):
46         """
[21]47@@ -602,7 +629,8 @@
[14]48         pass
49 
50 
51-    def createNode(self, service, nodeIdentifier=None, sender=None):
52+    def createNode(self, service, nodeIdentifier=None, options=None,
53+                         sender=None):
54         """
55         Create a publish subscribe node.
56 
[21]57@@ -610,12 +638,20 @@
[14]58         @type service: L{JID}
59         @param nodeIdentifier: Optional suggestion for the id of the node.
60         @type nodeIdentifier: C{unicode}
61+        @param options: Optional node configuration options.
62+        @type options: C{dict}
63         """
64         request = PubSubRequest('create')
65         request.recipient = service
66         request.nodeIdentifier = nodeIdentifier
67         request.sender = sender
68 
[20]69+        if options:
70+            form = data_form.Form(formType='result',
71+                                  formNamespace=NS_PUBSUB_NODE_CONFIG)
72+            form.makeFields(options)
73+            request.options = form
74+
[14]75         def cb(iq):
76             try:
[20]77                 new_node = iq.pubsub.create["node"]
[21]78@@ -887,8 +923,6 @@
[14]79             d = self.getNodes(requestor, target)
80         else:
81             d = defer.succeed([])
82-           
83-
84 
85         d.addCallback(lambda nodes: [disco.DiscoItem(target, node)
86                                      for node in nodes])
[21]87@@ -998,6 +1032,12 @@
[20]88         form.typeCheck(fieldDefs, filterUnknown=True)
[14]89 
90 
91+    def _preProcess_create(self, resource, request):
92+        if request.options:
[20]93+            self._checkConfiguration(resource, request.options)
[14]94+        return request
95+
96+
97     def _preProcess_default(self, resource, request):
98         if request.nodeType not in ('leaf', 'collection'):
99             raise error.StanzaError('not-acceptable')
[21]100diff -r d64e96596c50 -r 8425a88d49f5 wokkel/test/test_pubsub.py
101--- a/wokkel/test/test_pubsub.py        Wed Dec 30 21:41:55 2009 +0100
102+++ b/wokkel/test/test_pubsub.py        Wed Dec 30 21:42:27 2009 +0100
[14]103@@ -19,7 +19,7 @@
104 from wokkel.test.helpers import TestableRequestHandlerMixin, XmlStreamStub
105 
106 NS_PUBSUB = 'http://jabber.org/protocol/pubsub'
107-NS_PUBSUB_CONFIG = 'http://jabber.org/protocol/pubsub#node_config'
108+NS_PUBSUB_NODE_CONFIG = 'http://jabber.org/protocol/pubsub#node_config'
109 NS_PUBSUB_ERRORS = 'http://jabber.org/protocol/pubsub#errors'
110 NS_PUBSUB_EVENT = 'http://jabber.org/protocol/pubsub#event'
111 NS_PUBSUB_OWNER = 'http://jabber.org/protocol/pubsub#owner'
112@@ -271,6 +271,40 @@
113         return d
114 
115 
116+    def test_createNodeWithConfig(self):
117+        """
118+        Test sending create request with configuration options
119+        """
120+
121+        options = {
122+            'pubsub#title': 'Princely Musings (Atom)',
123+            'pubsub#deliver_payloads': True,
124+            'pubsub#persist_items': '1',
125+            'pubsub#max_items': '10',
126+            'pubsub#access_model': 'open',
127+            'pubsub#type': 'http://www.w3.org/2005/Atom',
128+        }
129+
130+        d = self.protocol.createNode(JID('pubsub.example.org'), 'test',
131+                                     sender=JID('user@example.org'),
132+                                     options=options)
133+
134+        iq = self.stub.output[-1]
135+
136+        # check if there is exactly one configure element
137+        children = list(domish.generateElementsQNamed(iq.pubsub.children,
138+                                                      'configure', NS_PUBSUB))
139+        self.assertEqual(1, len(children))
140+
141+        # check that it has a configuration form
142+        form = data_form.findForm(children[0], NS_PUBSUB_NODE_CONFIG)
143+        self.assertNotIdentical(None, form)
144+
145+        response = toResponse(iq, 'result')
146+        self.stub.send(response)
147+        return d
148+
149+
150     def test_deleteNode(self):
151         """
152         Test sending delete request.
[21]153@@ -935,6 +969,7 @@
[14]154         self.assertEqual(JID('user@example.org'), request.sender)
155         self.assertEqual(JID('pubsub.example.org'), request.recipient)
156         self.assertEqual('mynode', request.nodeIdentifier)
157+        self.assertIdentical(None, request.options)
158 
159 
160     def test_fromElementCreateInstant(self):
[21]161@@ -955,6 +990,78 @@
[14]162         self.assertIdentical(None, request.nodeIdentifier)
163 
164 
165+    def test_fromElementCreateConfigureEmpty(self):
166+        """
167+        Test parsing a request to create a node with an empty configuration.
168+        """
169+
170+        xml = """
171+        <iq type='set' to='pubsub.example.org'
172+                       from='user@example.org'>
173+          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
174+            <create node='mynode'/>
175+            <configure/>
176+          </pubsub>
177+        </iq>
178+        """
179+
180+        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
[20]181+        self.assertEqual({}, request.options.getValues())
[14]182+
183+
184+    def test_fromElementCreateConfigureEmptyWrongOrder(self):
185+        """
186+        Test parsing a request to create a node and configure, wrong order.
187+
188+        The C{configure} element should come after the C{create} request,
189+        but we should accept both orders.
190+        """
191+
192+        xml = """
193+        <iq type='set' to='pubsub.example.org'
194+                       from='user@example.org'>
195+          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
196+            <configure/>
197+            <create node='mynode'/>
198+          </pubsub>
199+        </iq>
200+        """
201+
202+        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
[20]203+        self.assertEqual({}, request.options.getValues())
[14]204+
205+
206+    def test_fromElementCreateConfigure(self):
207+        """
208+        Test parsing a request to create a node.
209+        """
210+
211+        xml = """
212+        <iq type='set' to='pubsub.example.org'
213+                       from='user@example.org'>
214+          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
215+            <create node='mynode'/>
216+            <configure>
217+              <x xmlns='jabber:x:data' type='submit'>
218+                <field var='FORM_TYPE' type='hidden'>
219+                  <value>http://jabber.org/protocol/pubsub#node_config</value>
220+                </field>
221+                <field var='pubsub#access_model'><value>open</value></field>
222+                <field var='pubsub#persist_items'><value>0</value></field>
223+              </x>
224+            </configure>
225+          </pubsub>
226+        </iq>
227+        """
228+
229+        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
[20]230+        values = request.options.getValues()
231+        self.assertIn('pubsub#access_model', values)
232+        self.assertEqual(u'open', values['pubsub#access_model'])
233+        self.assertIn('pubsub#persist_items', values)
234+        self.assertEqual(u'0', values['pubsub#persist_items'])
[14]235+
236+
237     def test_fromElementDefault(self):
238         """
239         Test parsing a request for the default node configuration.
[21]240@@ -1741,6 +1848,52 @@
[14]241         return d
242 
243 
244+    def test_on_createWithConfig(self):
245+        """
246+        On a node create with configuration request the Data Form is parsed and
247+        L{PubSubResource.create} is called with the passed options.
248+        """
249+
250+        xml = """
251+        <iq type='set' to='pubsub.example.org'
252+                       from='user@example.org'>
253+          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
254+            <create node='mynode'/>
255+            <configure>
256+              <x xmlns='jabber:x:data' type='submit'>
257+                <field var='FORM_TYPE' type='hidden'>
258+                  <value>http://jabber.org/protocol/pubsub#node_config</value>
259+                </field>
260+                <field var='pubsub#deliver_payloads'><value>0</value></field>
261+                <field var='pubsub#persist_items'><value>1</value></field>
262+              </x>
263+            </configure>
264+          </pubsub>
265+        </iq>
266+        """
267+
268+        def getConfigurationOptions():
269+            return {
270+                "pubsub#persist_items":
271+                    {"type": "boolean",
272+                     "label": "Persist items to storage"},
273+                "pubsub#deliver_payloads":
274+                    {"type": "boolean",
275+                     "label": "Deliver payloads with event notifications"}
276+                }
277+
278+        def create(request):
279+            self.assertEqual({'pubsub#deliver_payloads': False,
[20]280+                              'pubsub#persist_items': True},
281+                             request.options.getValues())
[14]282+            return defer.succeed(None)
283+
284+        self.resource.getConfigurationOptions = getConfigurationOptions
285+        self.resource.create = create
286+        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
287+        return self.handleRequest(xml)
288+
289+
290     def test_on_default(self):
291         """
292         A default request should result in
[21]293@@ -1774,7 +1927,7 @@
[14]294             self.assertEqual(NS_PUBSUB_OWNER, element.uri)
295             self.assertEqual(NS_PUBSUB_OWNER, element.default.uri)
296             form = data_form.Form.fromElement(element.default.x)
297-            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
298+            self.assertEqual(NS_PUBSUB_NODE_CONFIG, form.formNamespace)
299 
300         self.resource.getConfigurationOptions = getConfigurationOptions
301         self.resource.default = default
[21]302@@ -1903,7 +2056,7 @@
[14]303             self.assertEqual(NS_PUBSUB_OWNER, element.uri)
304             self.assertEqual(NS_PUBSUB_OWNER, element.configure.uri)
305             form = data_form.Form.fromElement(element.configure.x)
306-            self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
307+            self.assertEqual(NS_PUBSUB_NODE_CONFIG, form.formNamespace)
308             fields = form.fields
309 
310             self.assertIn('pubsub#deliver_payloads', fields)
Note: See TracBrowser for help on using the repository browser.