source: ralphm-patches/pubsub-create-configure.patch @ 27:a9704141033a

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

Ensure all modified code has unittests, add setOptions to PubSubClient?.

File size: 12.4 KB
  • wokkel/pubsub.py

    Add support for configuration options in node creation requests
    
    diff -r 259252e5664b wokkel/pubsub.py
    a b  
    234234        'optionsSet': ['nodeOrEmpty', 'jid', 'options'],
    235235        'subscriptions': [],
    236236        'affiliations': [],
    237         'create': ['nodeOrNone'],
     237        'create': ['nodeOrNone', 'configureOrNone'],
    238238        'default': ['default'],
    239239        'configureGet': ['nodeOrEmpty'],
    240240        'configureSet': ['nodeOrEmpty', 'configure'],
     
    364364            raise BadRequest(text="Missing configuration form")
    365365
    366366
     367    def _parse_configureOrNone(self, verbElement):
     368        """
     369        Parse optional node configuration form in create request.
     370        """
     371        for element in verbElement.parent.elements():
     372            if element.uri == NS_PUBSUB and element.name == 'configure':
     373                form = data_form.findForm(element, NS_PUBSUB_NODE_CONFIG)
     374                if form:
     375                    if form.formType == 'submit':
     376                        self.options = form
     377                    else:
     378                        raise BadRequest(text=u"Unexpected form type '%s'" %
     379                                              form.formType)
     380                else:
     381                    form = data_form.Form('submit',
     382                                          formNamespace=NS_PUBSUB_NODE_CONFIG)
     383                    self.options = form
     384
     385
     386    def _render_configureOrNone(self, verbElement):
     387        """
     388        Render optional node configuration form in create request.
     389        """
     390        if self.options is not None:
     391            configure = verbElement.parent.addElement('configure')
     392            configure.addChild(self.options.toElement())
     393
    367394
    368395    def _parse_itemIdentifiers(self, verbElement):
    369396        """
     
    607634        pass
    608635
    609636
    610     def createNode(self, service, nodeIdentifier=None, sender=None):
     637    def createNode(self, service, nodeIdentifier=None, options=None,
     638                         sender=None):
    611639        """
    612640        Create a publish subscribe node.
    613641
     
    615643        @type service: L{JID}
    616644        @param nodeIdentifier: Optional suggestion for the id of the node.
    617645        @type nodeIdentifier: C{unicode}
     646        @param options: Optional node configuration options.
     647        @type options: C{dict}
    618648        """
    619649        request = PubSubRequest('create')
    620650        request.recipient = service
    621651        request.nodeIdentifier = nodeIdentifier
    622652        request.sender = sender
    623653
     654        if options:
     655            form = data_form.Form(formType='submit',
     656                                  formNamespace=NS_PUBSUB_NODE_CONFIG)
     657            form.makeFields(options)
     658            request.options = form
     659
    624660        def cb(iq):
    625661            try:
    626662                new_node = iq.pubsub.create["node"]
     
    10011037        form.typeCheck(fieldDefs, filterUnknown=True)
    10021038
    10031039
     1040    def _preProcess_create(self, resource, request):
     1041        if request.options:
     1042            self._checkConfiguration(resource, request.options)
     1043        return request
     1044
     1045
    10041046    def _preProcess_default(self, resource, request):
    10051047        if request.nodeType not in ('leaf', 'collection'):
    10061048            raise error.StanzaError('not-acceptable')
  • wokkel/test/test_pubsub.py

    diff -r 259252e5664b wokkel/test/test_pubsub.py
    a b  
    1919from wokkel.test.helpers import TestableRequestHandlerMixin, XmlStreamStub
    2020
    2121NS_PUBSUB = 'http://jabber.org/protocol/pubsub'
    22 NS_PUBSUB_CONFIG = 'http://jabber.org/protocol/pubsub#node_config'
     22NS_PUBSUB_NODE_CONFIG = 'http://jabber.org/protocol/pubsub#node_config'
    2323NS_PUBSUB_ERRORS = 'http://jabber.org/protocol/pubsub#errors'
    2424NS_PUBSUB_EVENT = 'http://jabber.org/protocol/pubsub#event'
    2525NS_PUBSUB_OWNER = 'http://jabber.org/protocol/pubsub#owner'
     
    271271        return d
    272272
    273273
     274    def test_createNodeWithConfig(self):
     275        """
     276        Test sending create request with configuration options
     277        """
     278
     279        options = {
     280            'pubsub#title': 'Princely Musings (Atom)',
     281            'pubsub#deliver_payloads': True,
     282            'pubsub#persist_items': '1',
     283            'pubsub#max_items': '10',
     284            'pubsub#access_model': 'open',
     285            'pubsub#type': 'http://www.w3.org/2005/Atom',
     286        }
     287
     288        d = self.protocol.createNode(JID('pubsub.example.org'), 'test',
     289                                     sender=JID('user@example.org'),
     290                                     options=options)
     291
     292        iq = self.stub.output[-1]
     293
     294        # check if there is exactly one configure element
     295        children = list(domish.generateElementsQNamed(iq.pubsub.children,
     296                                                      'configure', NS_PUBSUB))
     297        self.assertEqual(1, len(children))
     298
     299        # check that it has a configuration form
     300        form = data_form.findForm(children[0], NS_PUBSUB_NODE_CONFIG)
     301        self.assertEqual('submit', form.formType)
     302
     303
     304        response = toResponse(iq, 'result')
     305        self.stub.send(response)
     306        return d
     307
     308
    274309    def test_deleteNode(self):
    275310        """
    276311        Test sending delete request.
     
    936971        self.assertEqual(JID('user@example.org'), request.sender)
    937972        self.assertEqual(JID('pubsub.example.org'), request.recipient)
    938973        self.assertEqual('mynode', request.nodeIdentifier)
     974        self.assertIdentical(None, request.options)
    939975
    940976
    941977    def test_fromElementCreateInstant(self):
     
    956992        self.assertIdentical(None, request.nodeIdentifier)
    957993
    958994
     995    def test_fromElementCreateConfigureEmpty(self):
     996        """
     997        Test parsing a request to create a node with an empty configuration.
     998        """
     999
     1000        xml = """
     1001        <iq type='set' to='pubsub.example.org'
     1002                       from='user@example.org'>
     1003          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1004            <create node='mynode'/>
     1005            <configure/>
     1006          </pubsub>
     1007        </iq>
     1008        """
     1009
     1010        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
     1011        self.assertEqual({}, request.options.getValues())
     1012
     1013
     1014    def test_fromElementCreateConfigureEmptyWrongOrder(self):
     1015        """
     1016        Test parsing a request to create a node and configure, wrong order.
     1017
     1018        The C{configure} element should come after the C{create} request,
     1019        but we should accept both orders.
     1020        """
     1021
     1022        xml = """
     1023        <iq type='set' to='pubsub.example.org'
     1024                       from='user@example.org'>
     1025          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1026            <configure/>
     1027            <create node='mynode'/>
     1028          </pubsub>
     1029        </iq>
     1030        """
     1031
     1032        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
     1033        self.assertEqual({}, request.options.getValues())
     1034
     1035
     1036    def test_fromElementCreateConfigure(self):
     1037        """
     1038        Test parsing a request to create a node.
     1039        """
     1040
     1041        xml = """
     1042        <iq type='set' to='pubsub.example.org'
     1043                       from='user@example.org'>
     1044          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1045            <create node='mynode'/>
     1046            <configure>
     1047              <x xmlns='jabber:x:data' type='submit'>
     1048                <field var='FORM_TYPE' type='hidden'>
     1049                  <value>http://jabber.org/protocol/pubsub#node_config</value>
     1050                </field>
     1051                <field var='pubsub#access_model'><value>open</value></field>
     1052                <field var='pubsub#persist_items'><value>0</value></field>
     1053              </x>
     1054            </configure>
     1055          </pubsub>
     1056        </iq>
     1057        """
     1058
     1059        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
     1060        values = request.options.getValues()
     1061        self.assertIn('pubsub#access_model', values)
     1062        self.assertEqual(u'open', values['pubsub#access_model'])
     1063        self.assertIn('pubsub#persist_items', values)
     1064        self.assertEqual(u'0', values['pubsub#persist_items'])
     1065
     1066
     1067    def test_fromElementCreateConfigureBadFormType(self):
     1068        """
     1069        The form of a node creation request should have the right type.
     1070        """
     1071
     1072        xml = """
     1073        <iq type='set' to='pubsub.example.org'
     1074                       from='user@example.org'>
     1075          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1076            <create node='mynode'/>
     1077            <configure>
     1078              <x xmlns='jabber:x:data' type='result'>
     1079                <field var='FORM_TYPE' type='hidden'>
     1080                  <value>http://jabber.org/protocol/pubsub#node_config</value>
     1081                </field>
     1082                <field var='pubsub#access_model'><value>open</value></field>
     1083                <field var='pubsub#persist_items'><value>0</value></field>
     1084              </x>
     1085            </configure>
     1086          </pubsub>
     1087        </iq>
     1088        """
     1089
     1090        err = self.assertRaises(error.StanzaError,
     1091                                pubsub.PubSubRequest.fromElement,
     1092                                parseXml(xml))
     1093        self.assertEqual('bad-request', err.condition)
     1094        self.assertEqual("Unexpected form type 'result'", err.text)
     1095        self.assertEqual(None, err.appCondition)
     1096
     1097
    9591098    def test_fromElementDefault(self):
    9601099        """
    9611100        Test parsing a request for the default node configuration.
     
    10801219
    10811220    def test_fromElementConfigureSetBadFormType(self):
    10821221        """
    1083         On a node configuration set request unknown fields should be ignored.
     1222        The form of a node configuraton set request should have the right type.
    10841223        """
    10851224
    10861225        xml = """
     
    17431882        return d
    17441883
    17451884
     1885    def test_on_createWithConfig(self):
     1886        """
     1887        On a node create with configuration request the Data Form is parsed and
     1888        L{PubSubResource.create} is called with the passed options.
     1889        """
     1890
     1891        xml = """
     1892        <iq type='set' to='pubsub.example.org'
     1893                       from='user@example.org'>
     1894          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1895            <create node='mynode'/>
     1896            <configure>
     1897              <x xmlns='jabber:x:data' type='submit'>
     1898                <field var='FORM_TYPE' type='hidden'>
     1899                  <value>http://jabber.org/protocol/pubsub#node_config</value>
     1900                </field>
     1901                <field var='pubsub#deliver_payloads'><value>0</value></field>
     1902                <field var='pubsub#persist_items'><value>1</value></field>
     1903              </x>
     1904            </configure>
     1905          </pubsub>
     1906        </iq>
     1907        """
     1908
     1909        def getConfigurationOptions():
     1910            return {
     1911                "pubsub#persist_items":
     1912                    {"type": "boolean",
     1913                     "label": "Persist items to storage"},
     1914                "pubsub#deliver_payloads":
     1915                    {"type": "boolean",
     1916                     "label": "Deliver payloads with event notifications"}
     1917                }
     1918
     1919        def create(request):
     1920            self.assertEqual({'pubsub#deliver_payloads': False,
     1921                              'pubsub#persist_items': True},
     1922                             request.options.getValues())
     1923            return defer.succeed(None)
     1924
     1925        self.resource.getConfigurationOptions = getConfigurationOptions
     1926        self.resource.create = create
     1927        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
     1928        return self.handleRequest(xml)
     1929
     1930
    17461931    def test_on_default(self):
    17471932        """
    17481933        A default request should result in
     
    17761961            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
    17771962            self.assertEqual(NS_PUBSUB_OWNER, element.default.uri)
    17781963            form = data_form.Form.fromElement(element.default.x)
    1779             self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
     1964            self.assertEqual(NS_PUBSUB_NODE_CONFIG, form.formNamespace)
    17801965
    17811966        self.resource.getConfigurationOptions = getConfigurationOptions
    17821967        self.resource.default = default
     
    19052090            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
    19062091            self.assertEqual(NS_PUBSUB_OWNER, element.configure.uri)
    19072092            form = data_form.Form.fromElement(element.configure.x)
    1908             self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
     2093            self.assertEqual(NS_PUBSUB_NODE_CONFIG, form.formNamespace)
    19092094            fields = form.fields
    19102095
    19112096            self.assertIn('pubsub#deliver_payloads', fields)
Note: See TracBrowser for help on using the repository browser.