Allow multiple push services to be enabled and also allow disabling

This commit is contained in:
JC Brand 2018-06-07 16:25:59 +02:00
parent 5954cd8f29
commit a09333f82c
4 changed files with 252 additions and 118 deletions

118
dist/converse.js vendored
View File

@ -73353,54 +73353,100 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
__ = _converse.__;
_converse.api.settings.update({
'push_service': undefined,
'push_service_node': undefined,
'push_service_secret': undefined
'push_services': []
});
function enablePush() {
if (_converse.session.get('push_enabled')) {
function disablePushService(push_service) {
if (!push_service.jid) {
return;
}
if (_converse.push_service && _converse.push_service_node) {
_converse.api.disco.getIdentity('pubsub', 'push', _converse.push_service).then(identity => {
if (!identity) {
return _converse.log(`Not enabling push the service "${_converse.push_service}", it doesn't have the right disco identtiy.`, Strophe.LogLevel.WARN);
Promise.all([_converse.api.disco.supports(Strophe.NS.PUSH, _converse.bare_jid)]).then(result => {
if (!result[0].length && !result[1].length) {
return _converse.log(`Not disabling push service "${push_service.jid}", no disco support from your server.`, Strophe.LogLevel.WARN);
}
const stanza = $iq({
'type': 'set'
}).c('disable', {
'xmlns': Strophe.NS.PUSH,
'jid': push_service.jid
});
if (push_service.node) {
stanza.attrs({
'node': push_service.node
});
}
_converse.api.sendIQ(stanza).then(() => _converse.session.set('push_enabled', true)).catch(e => {
_converse.log(`Could not enable push service for ${push_service.jid}`, Strophe.LogLevel.ERROR);
_converse.log(e, Strophe.LogLevel.ERROR);
});
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}
function enablePushService(push_service) {
if (!push_service.jid || !push_service.node) {
return;
}
_converse.api.disco.getIdentity('pubsub', 'push', push_service.jid).then(identity => {
if (!identity) {
return _converse.log(`Not enabling push the service "${push_service.jid}", it doesn't have the right disco identtiy.`, Strophe.LogLevel.WARN);
}
return Promise.all([_converse.api.disco.supports(Strophe.NS.PUSH, push_service.jid), _converse.api.disco.supports(Strophe.NS.PUSH, _converse.bare_jid)]).then(result => {
if (!result[0].length && !result[1].length) {
return _converse.log(`Not enabling push service "${push_service.jid}", no disco support from your server.`, Strophe.LogLevel.WARN);
}
return Promise.all([_converse.api.disco.supports(Strophe.NS.PUSH, _converse.push_service), _converse.api.disco.supports(Strophe.NS.PUSH, _converse.bare_jid)]).then(result => {
if (!result[0].length && !result[1].length) {
return _converse.log(`Not enabling push service "${_converse.push_service}", no disco support`, Strophe.LogLevel.WARN);
}
const stanza = $iq({
'type': 'set'
}).c('enable', {
'xmlns': Strophe.NS.PUSH,
'jid': push_service.jid,
'node': push_service.node
});
const stanza = $iq({
'type': 'set'
}).c('enable', {
'xmlns': Strophe.NS.PUSH,
'jid': _converse.push_service,
'node': _converse.push_service_node
});
if (push_service.secret) {
stanza.c('x', {
'xmlns': Strophe.NS.XFORM,
'type': 'submit'
}).c('field', {
'var': 'FORM_TYPE'
}).c('value').t(`${Strophe.NS.PUBSUB}#publish-options`).up().up().c('field', {
'var': 'secret'
}).c('value').t(push_service.secret);
}
if (_converse.push_service_secret) {
stanza.c('x', {
'xmlns': Strophe.NS.XFORM,
'type': 'submit'
}).c('field', {
'var': 'FORM_TYPE'
}).c('value').t(`${Strophe.NS.PUBSUB}#publish-options`).up().up().c('field', {
'var': 'secret'
}).c('value').t(_converse.push_service_secret);
}
_converse.api.sendIQ(stanza).then(() => _converse.session.set('push_enabled', true)).catch(e => {
_converse.log(`Could not enable push service for ${push_service.jid}`, Strophe.LogLevel.ERROR);
_converse.api.sendIQ(stanza).then(() => _converse.session.set('push_enabled', true)).catch(e => {
_converse.log(`Could not enable push service for ${_converse.push_service}`, Strophe.LogLevel.ERROR);
_converse.log(e, Strophe.LogLevel.ERROR);
});
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
_converse.log(e, Strophe.LogLevel.ERROR);
});
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}
function enablePush() {
if (_converse.session.get('push_enabled')) {
// XXX: this code is still a bit naive. We set push_enabled
// to true as soon as the first push service has been set.
//
// When enabling or disabling multiple push services,
// we won't wait until we have confirmation that all have been set.
return;
}
const enabled_services = _.reject(_converse.push_services, 'disable');
_.each(enabled_services, enablePushService);
const disabled_services = _.filter(_converse.push_services, 'disable');
_.each(disabled_services, disablePushService);
}
_converse.api.listen.on('statusInitialized', enablePush);

View File

@ -1068,38 +1068,38 @@ providers_link
The hyperlink on the registration form which points to a directory of public
XMPP servers.
push_service
------------
push_services
-------------
* Default: ``undefined``
* Default: ``[]``
This option allows you to specify a URI for the push notifications service
(called an "App Server" by `XEP-0357 <https://xmpp.org/extensions/xep-0357.html>`_).
This option lets you enable or disable so-called push notification "App Servers"
(as per `XEP-0357 <https://xmpp.org/extensions/xep-0357.html>`_).
If provided, together with a `push_service_node`_, then Converse will instruct
the user's XMPP server to send push notificatiosn to that URI.
For each "App Server" an object needs to be passed in. When enabling, you need
to specify ``jid`` and ``node`` values. You can also provide a
``secret``, if required by your App Server.
push_service_node
-----------------
When disabling, you need to specify at least a ``jid`` and set ``disabled`` to
``true``. This will disable notifications to all pubsub nodes on that "App
Server". If you want to disable only a particular node, then specify a ``node``
value as well.
* Default: ``undefined``
For example:
This is the PubSub node of the push notifications service (aka "App Server") specified with the
`push_service`_ setting.
Push notifications will be sent to this node. If this value is not set, then
push notifications won't be sent out.
.. code-block:: javascript
push_service_secret
-------------------
* Default: ``undefined``
Some push notification services (aka "App Servers") require a secret token to
be used when sending out notifications.
This setting enables you to provide such a secret to Converse which will
forward it to your XMPP server to be included in push notifications.
converse.initialize({
'push_services': [{
'jid': 'push-4@client.example',
'node': 'yxs32uqsflafdk3iuqo',
'disable': true
}, {
'jid': 'push-5@client.example',
'node': 'yxs32uqsflafdk3iuqo',
}]
});
root
----

View File

@ -8,22 +8,22 @@
describe("XEP-0357 Push Notifications", function () {
it("can be enabled by specifying a push_service and push_service_node",
mock.initConverseWithPromises(null,
it("can be enabled",
mock.initConverseWithPromises(null,
['rosterGroupsFetched'], {
'push_service': 'push-5@client.example',
'push_service_node': 'yxs32uqsflafdk3iuqo'
'push_services': [{
'jid': 'push-5@client.example',
'node': 'yxs32uqsflafdk3iuqo'
}]
}, function (done, _converse) {
const IQ_stanzas = _converse.connection.IQ_stanzas;
let stanza;
expect(_converse.push_service).toBe('push-5@client.example');
expect(_converse.push_service_node).toBe('yxs32uqsflafdk3iuqo');
expect(_converse.session.get('push_enabled')).toBeFalsy();
test_utils.waitUntilDiscoConfirmed(
_converse, _converse.push_service,
_converse, _converse.push_services[0].jid,
[{'category': 'pubsub', 'type':'push'}],
['urn:xmpp:push:0'], [], 'info')
.then(() => test_utils.waitUntilDiscoConfirmed(
@ -58,25 +58,70 @@
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}));
it("can require a secret token to be included",
mock.initConverseWithPromises(null,
it("can be disabled",
mock.initConverseWithPromises(null,
['rosterGroupsFetched'], {
'push_service': 'push-5@client.example',
'push_service_node': 'yxs32uqsflafdk3iuqo',
'push_service_secret': 'eruio234vzxc2kla-91'
'push_services': [{
'jid': 'push-5@client.example',
'node': 'yxs32uqsflafdk3iuqo',
'disable': true
}]
}, function (done, _converse) {
const IQ_stanzas = _converse.connection.IQ_stanzas;
let stanza;
expect(_converse.push_service).toBe('push-5@client.example');
expect(_converse.push_service_node).toBe('yxs32uqsflafdk3iuqo');
expect(_converse.push_service_secret).toBe('eruio234vzxc2kla-91');
expect(_converse.session.get('push_enabled')).toBeFalsy();
test_utils.waitUntilDiscoConfirmed(
_converse, _converse.push_service,
_converse,
_converse.bare_jid,
[{'category': 'account', 'type':'registered'}],
['urn:xmpp:push:0'], [], 'info')
.then(() => {
return test_utils.waitUntil(() => {
const node = _.filter(IQ_stanzas, function (iq) {
return iq.nodeTree.querySelector('iq[type="set"] disable[xmlns="urn:xmpp:push:0"]');
}).pop();
if (node) {
stanza = node.nodeTree;
return true;
}
})
}).then(() => {
expect(stanza.outerHTML).toEqual(
`<iq type="set" xmlns="jabber:client" id="${stanza.getAttribute('id')}">`+
'<disable xmlns="urn:xmpp:push:0" jid="push-5@client.example" node="yxs32uqsflafdk3iuqo"/>'+
'</iq>'
)
_converse.connection._dataRecv(test_utils.createRequest($iq({
'to': _converse.connection.jid,
'type': 'result',
'id': stanza.getAttribute('id')
})));
return test_utils.waitUntil(() => _converse.session.get('push_enabled'))
}).then(() => {
done();
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}));
it("can require a secret token to be included",
mock.initConverseWithPromises(null,
['rosterGroupsFetched'], {
'push_services': [{
'jid': 'push-5@client.example',
'node': 'yxs32uqsflafdk3iuqo',
'secret': 'eruio234vzxc2kla-91'
}]
}, function (done, _converse) {
const IQ_stanzas = _converse.connection.IQ_stanzas;
let stanza;
expect(_converse.session.get('push_enabled')).toBeFalsy();
test_utils.waitUntilDiscoConfirmed(
_converse, _converse.push_services[0].jid,
[{'category': 'pubsub', 'type':'push'}],
['urn:xmpp:push:0'], [], 'info')
.then(() => test_utils.waitUntilDiscoConfirmed(

View File

@ -16,7 +16,7 @@
Strophe.addNamespace('PUSH', 'urn:xmpp:push:0');
converse.plugins.add('converse-push', {
initialize () {
@ -27,56 +27,99 @@
{ __ } = _converse;
_converse.api.settings.update({
'push_service': undefined,
'push_service_node': undefined,
'push_service_secret': undefined
'push_services': [],
});
function enablePush() {
if (_converse.session.get('push_enabled')) {
function disablePushService (push_service) {
if (!push_service.jid) {
return;
}
if (_converse.push_service && _converse.push_service_node) {
_converse.api.disco.getIdentity('pubsub', 'push', _converse.push_service)
.then((identity) => {
if (!identity) {
Promise.all([
_converse.api.disco.supports(Strophe.NS.PUSH, _converse.bare_jid)
]).then((result) => {
if (!result[0].length && !result[1].length) {
return _converse.log(
`Not disabling push service "${push_service.jid}", no disco support from your server.`,
Strophe.LogLevel.WARN
);
}
const stanza = $iq({'type': 'set'})
.c('disable', {
'xmlns': Strophe.NS.PUSH,
'jid': push_service.jid,
});
if (push_service.node) {
stanza.attrs({'node': push_service.node});
}
_converse.api.sendIQ(stanza)
.then(() => _converse.session.set('push_enabled', true))
.catch((e) => {
_converse.log(`Could not enable push service for ${push_service.jid}`, Strophe.LogLevel.ERROR);
_converse.log(e, Strophe.LogLevel.ERROR);
});
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}
function enablePushService (push_service) {
if (!push_service.jid || !push_service.node) {
return;
}
_converse.api.disco.getIdentity('pubsub', 'push', push_service.jid)
.then((identity) => {
if (!identity) {
return _converse.log(
`Not enabling push the service "${push_service.jid}", it doesn't have the right disco identtiy.`,
Strophe.LogLevel.WARN
);
}
return Promise.all([
_converse.api.disco.supports(Strophe.NS.PUSH, push_service.jid),
_converse.api.disco.supports(Strophe.NS.PUSH, _converse.bare_jid)
]).then((result) => {
if (!result[0].length && !result[1].length) {
return _converse.log(
`Not enabling push the service "${_converse.push_service}", it doesn't have the right disco identtiy.`,
`Not enabling push service "${push_service.jid}", no disco support from your server.`,
Strophe.LogLevel.WARN
);
}
return Promise.all([
_converse.api.disco.supports(Strophe.NS.PUSH, _converse.push_service),
_converse.api.disco.supports(Strophe.NS.PUSH, _converse.bare_jid)
]).then((result) => {
if (!result[0].length && !result[1].length) {
return _converse.log(
`Not enabling push service "${_converse.push_service}", no disco support`,
Strophe.LogLevel.WARN
);
}
const stanza = $iq({'type': 'set'})
.c('enable', {
'xmlns': Strophe.NS.PUSH,
'jid': _converse.push_service,
'node': _converse.push_service_node
});
if (_converse.push_service_secret) {
stanza.c('x', {'xmlns': Strophe.NS.XFORM, 'type': 'submit'})
.c('field', {'var': 'FORM_TYPE'})
.c('value').t(`${Strophe.NS.PUBSUB}#publish-options`).up().up()
.c('field', {'var': 'secret'})
.c('value').t(_converse.push_service_secret);
}
_converse.api.sendIQ(stanza)
.then(() => _converse.session.set('push_enabled', true))
.catch((e) => {
_converse.log(`Could not enable push service for ${_converse.push_service}`, Strophe.LogLevel.ERROR);
_converse.log(e, Strophe.LogLevel.ERROR);
});
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
const stanza = $iq({'type': 'set'})
.c('enable', {
'xmlns': Strophe.NS.PUSH,
'jid': push_service.jid,
'node': push_service.node
});
if (push_service.secret) {
stanza.c('x', {'xmlns': Strophe.NS.XFORM, 'type': 'submit'})
.c('field', {'var': 'FORM_TYPE'})
.c('value').t(`${Strophe.NS.PUBSUB}#publish-options`).up().up()
.c('field', {'var': 'secret'})
.c('value').t(push_service.secret);
}
_converse.api.sendIQ(stanza)
.then(() => _converse.session.set('push_enabled', true))
.catch((e) => {
_converse.log(`Could not enable push service for ${push_service.jid}`, Strophe.LogLevel.ERROR);
_converse.log(e, Strophe.LogLevel.ERROR);
});
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}
function enablePush () {
if (_converse.session.get('push_enabled')) {
// XXX: this code is still a bit naive. We set push_enabled
// to true as soon as the first push service has been set.
//
// When enabling or disabling multiple push services,
// we won't wait until we have confirmation that all have been set.
return;
}
const enabled_services = _.reject(_converse.push_services, 'disable');
_.each(enabled_services, enablePushService);
const disabled_services = _.filter(_converse.push_services, 'disable');
_.each(disabled_services, disablePushService);
}
_converse.api.listen.on('statusInitialized', enablePush);
}