source: ralphm-patches/pubsub-create-configure.patch @ 14:f781923410ee

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

Bunch of patches applied upstream. Added new patch for pubsub create+config.

File size: 14.7 KB
  • wokkel/data_form.py

    diff -r 53bd69434e51 wokkel/data_form.py
    a b  
    251251            field['var'] = self.var
    252252
    253253        for value in self.values:
    254             if self.fieldType == 'boolean':
     254            if isinstance(value, bool):
    255255                value = unicode(value).lower()
    256             elif self.fieldType in ('jid-single', 'jid-multi'):
    257                 value = value.full()
     256            else:
     257                value = unicode(value)
    258258
    259259            field.addElement('value', content=value)
    260260
     
    489489            values[name] = value
    490490
    491491        return values
     492
     493
     494
     495def findForm(element, formNamespace):
     496    """
     497    Find a Data Form.
     498
     499    Look for an element that represents a Data Form with the specified
     500    form namespace as a child element of the given element.
     501    """
     502    if not element:
     503        return None
     504
     505    for child in element.elements():
     506        if (child.uri, child.name) == ((NS_X_DATA, 'x')):
     507            form = Form.fromElement(child)
     508
     509            if (form.formNamespace == formNamespace or
     510                not form.formNamespace and form.formType=='cancel'):
     511                return form
     512
     513    return None
  • wokkel/pubsub.py

    diff -r 53bd69434e51 wokkel/pubsub.py
    a b  
    233233        'optionsSet': ['nodeOrEmpty', 'jid', 'options'],
    234234        'subscriptions': [],
    235235        'affiliations': [],
    236         'create': ['nodeOrNone'],
     236        'create': ['nodeOrNone', 'configureOrNone'],
    237237        'default': ['default'],
    238238        'configureGet': ['nodeOrEmpty'],
    239239        'configureSet': ['nodeOrEmpty', 'configure'],
     
    251251        self.verb = verb
    252252
    253253
    254     @staticmethod
    255     def _findForm(element, formNamespace):
    256         """
    257         Find a Data Form.
    258 
    259         Look for an element that represents a Data Form with the specified
    260         form namespace as a child element of the given element.
    261         """
    262         if not element:
    263             return None
    264 
    265         form = None
    266         for child in element.elements():
    267             try:
    268                 form = data_form.Form.fromElement(child)
    269             except data_form.Error:
    270                 continue
    271 
    272             if form.formNamespace != NS_PUBSUB_NODE_CONFIG:
    273                 continue
    274 
    275         return form
    276 
    277 
    278254    def _parse_node(self, verbElement):
    279255        """
    280256        Parse the required node identifier out of the verbElement.
     
    365341        """
    366342        Parse node type out of a request for the default node configuration.
    367343        """
    368         form = PubSubRequest._findForm(verbElement, NS_PUBSUB_NODE_CONFIG)
     344        form = data_form.findForm(verbElement, NS_PUBSUB_NODE_CONFIG)
    369345        if form and form.formType == 'submit':
    370346            values = form.getValues()
    371347            self.nodeType = values.get('pubsub#node_type', 'leaf')
     
    377353        """
    378354        Parse options out of a request for setting the node configuration.
    379355        """
    380         form = PubSubRequest._findForm(verbElement, NS_PUBSUB_NODE_CONFIG)
     356        form = data_form.findForm(verbElement, NS_PUBSUB_NODE_CONFIG)
    381357        if form:
    382358            if form.formType == 'submit':
    383359                self.options = form.getValues()
     
    389365            raise BadRequest(text="Missing configuration form")
    390366
    391367
     368    def _parse_configureOrNone(self, verbElement):
     369        """
     370        Parse optional node configuration form in create request.
     371        """
     372        for element in verbElement.parent.elements():
     373            if element.uri == NS_PUBSUB and element.name == 'configure':
     374                form = data_form.findForm(element, NS_PUBSUB_NODE_CONFIG)
     375                if form:
     376                    if form.formType == 'submit':
     377                        self.options = form.getValues()
     378                    else:
     379                        raise BadRequest(text="Unexpected form type %r" %
     380                                              form.formType)
     381                else:
     382                    self.options = {}
     383
     384
     385    def _render_configureOrNone(self, verbElement):
     386        """
     387        Render optional node configuration form in create request.
     388        """
     389        def makeFields(values):
     390            fields = []
     391            for name, value in values.iteritems():
     392                option = {'var': name}
     393                if isinstance(value, list):
     394                    option['values'] = value
     395                else:
     396                    option['value'] = value
     397                fields.append(data_form.Field.fromDict(option))
     398            return fields
     399
     400        if self.options is not None:
     401            fields = makeFields(self.options)
     402            form = data_form.Form('submit',
     403                                  formNamespace=NS_PUBSUB_NODE_CONFIG,
     404                                  fields=fields)
     405            configure = verbElement.parent.addElement('configure')
     406            configure.addChild(form.toElement())
     407
    392408
    393409    def _parse_itemIdentifiers(self, verbElement):
    394410        """
     
    436452
    437453
    438454    def _parse_options(self, verbElement):
    439         form = PubSubRequest._findForm(verbElement, NS_PUBSUB_SUBSCRIBE_OPTIONS)
     455        form = data_form.findForm(verbElement, NS_PUBSUB_SUBSCRIBE_OPTIONS)
    440456        if form:
    441457            if form.formType == 'submit':
    442458                self.options = form.getValues()
     
    447463        else:
    448464            raise BadRequest(text="Missing options form")
    449465
     466
    450467    def parseElement(self, element):
    451468        """
    452469        Parse the publish-subscribe verb and parameters out of a request.
     
    630647        pass
    631648
    632649
    633     def createNode(self, service, nodeIdentifier=None, sender=None):
     650    def createNode(self, service, nodeIdentifier=None, options=None,
     651                         sender=None):
    634652        """
    635653        Create a publish subscribe node.
    636654
     
    638656        @type service: L{JID}
    639657        @param nodeIdentifier: Optional suggestion for the id of the node.
    640658        @type nodeIdentifier: C{unicode}
     659        @param options: Optional node configuration options.
     660        @type options: C{dict}
    641661        """
    642662        request = PubSubRequest('create')
    643663        request.recipient = service
    644664        request.nodeIdentifier = nodeIdentifier
    645665        request.sender = sender
     666        request.options = options
    646667
    647668        def cb(iq):
    648669            try:
     
    915936            d = self.getNodes(requestor, target)
    916937        else:
    917938            d = defer.succeed([])
    918            
    919 
    920939
    921940        d.addCallback(lambda nodes: [disco.DiscoItem(target, node)
    922941                                     for node in nodes])
     
    10621081        return processedValues
    10631082
    10641083
     1084    def _preProcess_create(self, resource, request):
     1085        if request.options:
     1086            request.options = self._checkConfiguration(resource,
     1087                                                       request.options)
     1088        return request
     1089
     1090
    10651091    def _preProcess_default(self, resource, request):
    10661092        if request.nodeType not in ('leaf', 'collection'):
    10671093            raise error.StanzaError('not-acceptable')
  • wokkel/test/test_pubsub.py

    diff -r 53bd69434e51 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.assertNotIdentical(None, form)
     302
     303        response = toResponse(iq, 'result')
     304        self.stub.send(response)
     305        return d
     306
     307
    274308    def test_deleteNode(self):
    275309        """
    276310        Test sending delete request.
     
    935969        self.assertEqual(JID('user@example.org'), request.sender)
    936970        self.assertEqual(JID('pubsub.example.org'), request.recipient)
    937971        self.assertEqual('mynode', request.nodeIdentifier)
     972        self.assertIdentical(None, request.options)
    938973
    939974
    940975    def test_fromElementCreateInstant(self):
     
    955990        self.assertIdentical(None, request.nodeIdentifier)
    956991
    957992
     993    def test_fromElementCreateConfigureEmpty(self):
     994        """
     995        Test parsing a request to create a node with an empty configuration.
     996        """
     997
     998        xml = """
     999        <iq type='set' to='pubsub.example.org'
     1000                       from='user@example.org'>
     1001          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1002            <create node='mynode'/>
     1003            <configure/>
     1004          </pubsub>
     1005        </iq>
     1006        """
     1007
     1008        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
     1009        self.assertEqual({}, request.options)
     1010
     1011
     1012    def test_fromElementCreateConfigureEmptyWrongOrder(self):
     1013        """
     1014        Test parsing a request to create a node and configure, wrong order.
     1015
     1016        The C{configure} element should come after the C{create} request,
     1017        but we should accept both orders.
     1018        """
     1019
     1020        xml = """
     1021        <iq type='set' to='pubsub.example.org'
     1022                       from='user@example.org'>
     1023          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1024            <configure/>
     1025            <create node='mynode'/>
     1026          </pubsub>
     1027        </iq>
     1028        """
     1029
     1030        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
     1031        self.assertEqual({}, request.options)
     1032
     1033
     1034    def test_fromElementCreateConfigure(self):
     1035        """
     1036        Test parsing a request to create a node.
     1037        """
     1038
     1039        xml = """
     1040        <iq type='set' to='pubsub.example.org'
     1041                       from='user@example.org'>
     1042          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1043            <create node='mynode'/>
     1044            <configure>
     1045              <x xmlns='jabber:x:data' type='submit'>
     1046                <field var='FORM_TYPE' type='hidden'>
     1047                  <value>http://jabber.org/protocol/pubsub#node_config</value>
     1048                </field>
     1049                <field var='pubsub#access_model'><value>open</value></field>
     1050                <field var='pubsub#persist_items'><value>0</value></field>
     1051              </x>
     1052            </configure>
     1053          </pubsub>
     1054        </iq>
     1055        """
     1056
     1057        request = pubsub.PubSubRequest.fromElement(parseXml(xml))
     1058        self.assertIn('pubsub#access_model', request.options)
     1059        self.assertEqual(u'open', request.options['pubsub#access_model'])
     1060        self.assertIn('pubsub#persist_items', request.options)
     1061        self.assertEqual(u'0', request.options['pubsub#persist_items'])
     1062
     1063
    9581064    def test_fromElementDefault(self):
    9591065        """
    9601066        Test parsing a request for the default node configuration.
     
    17401846        return d
    17411847
    17421848
     1849    def test_on_createWithConfig(self):
     1850        """
     1851        On a node create with configuration request the Data Form is parsed and
     1852        L{PubSubResource.create} is called with the passed options.
     1853        """
     1854
     1855        xml = """
     1856        <iq type='set' to='pubsub.example.org'
     1857                       from='user@example.org'>
     1858          <pubsub xmlns='http://jabber.org/protocol/pubsub'>
     1859            <create node='mynode'/>
     1860            <configure>
     1861              <x xmlns='jabber:x:data' type='submit'>
     1862                <field var='FORM_TYPE' type='hidden'>
     1863                  <value>http://jabber.org/protocol/pubsub#node_config</value>
     1864                </field>
     1865                <field var='pubsub#deliver_payloads'><value>0</value></field>
     1866                <field var='pubsub#persist_items'><value>1</value></field>
     1867              </x>
     1868            </configure>
     1869          </pubsub>
     1870        </iq>
     1871        """
     1872
     1873        def getConfigurationOptions():
     1874            return {
     1875                "pubsub#persist_items":
     1876                    {"type": "boolean",
     1877                     "label": "Persist items to storage"},
     1878                "pubsub#deliver_payloads":
     1879                    {"type": "boolean",
     1880                     "label": "Deliver payloads with event notifications"}
     1881                }
     1882
     1883        def create(request):
     1884            self.assertEqual({'pubsub#deliver_payloads': False,
     1885                              'pubsub#persist_items': True}, request.options)
     1886            return defer.succeed(None)
     1887
     1888        self.resource.getConfigurationOptions = getConfigurationOptions
     1889        self.resource.create = create
     1890        verify.verifyObject(iwokkel.IPubSubResource, self.resource)
     1891        return self.handleRequest(xml)
     1892
     1893
    17431894    def test_on_default(self):
    17441895        """
    17451896        A default request should result in
     
    17731924            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
    17741925            self.assertEqual(NS_PUBSUB_OWNER, element.default.uri)
    17751926            form = data_form.Form.fromElement(element.default.x)
    1776             self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
     1927            self.assertEqual(NS_PUBSUB_NODE_CONFIG, form.formNamespace)
    17771928
    17781929        self.resource.getConfigurationOptions = getConfigurationOptions
    17791930        self.resource.default = default
     
    19022053            self.assertEqual(NS_PUBSUB_OWNER, element.uri)
    19032054            self.assertEqual(NS_PUBSUB_OWNER, element.configure.uri)
    19042055            form = data_form.Form.fromElement(element.configure.x)
    1905             self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace)
     2056            self.assertEqual(NS_PUBSUB_NODE_CONFIG, form.formNamespace)
    19062057            fields = form.fields
    19072058
    19082059            self.assertIn('pubsub#deliver_payloads', fields)
Note: See TracBrowser for help on using the repository browser.