Commit a09333f8 authored by JC Brand's avatar JC Brand

Allow multiple push services to be enabled and also allow disabling

parent 5954cd8f
......@@ -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);
}
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('disable', {
'xmlns': Strophe.NS.PUSH,
'jid': push_service.jid
});
const stanza = $iq({
'type': 'set'
}).c('enable', {
'xmlns': Strophe.NS.PUSH,
'jid': _converse.push_service,
'node': _converse.push_service_node
});
if (push_service.node) {
stanza.attrs({
'node': 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 ${push_service.jid}`, Strophe.LogLevel.ERROR);
_converse.log(e, Strophe.LogLevel.ERROR);
});
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
}
_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);
function enablePushService(push_service) {
if (!push_service.jid || !push_service.node) {
return;
}
_converse.log(e, Strophe.LogLevel.ERROR);
});
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
_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);
}
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);
......@@ -1068,38 +1068,38 @@ providers_link
The hyperlink on the registration form which points to a directory of public
XMPP servers.
push_service
------------
* Default: ``undefined``
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>`_).
push_services
-------------
If provided, together with a `push_service_node`_, then Converse will instruct
the user's XMPP server to send push notificatiosn to that URI.
* Default: ``[]``
push_service_node
-----------------
This option lets you enable or disable so-called push notification "App Servers"
(as per `XEP-0357 <https://xmpp.org/extensions/xep-0357.html>`_).
* Default: ``undefined``
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.
This is the PubSub node of the push notifications service (aka "App Server") specified with the
`push_service`_ setting.
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.
Push notifications will be sent to this node. If this value is not set, then
push notifications won't be sent out.
push_service_secret
-------------------
For example:
* Default: ``undefined``
Some push notification services (aka "App Servers") require a secret token to
be used when sending out notifications.
.. code-block:: javascript
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
----
......
......@@ -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 be disabled",
mock.initConverseWithPromises(null,
['rosterGroupsFetched'], {
'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.session.get('push_enabled')).toBeFalsy();
test_utils.waitUntilDiscoConfirmed(
_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,
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',
'secret': 'eruio234vzxc2kla-91'
}]
}, 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.push_services[0].jid,
[{'category': 'pubsub', 'type':'push'}],
['urn:xmpp:push:0'], [], 'info')
.then(() => test_utils.waitUntilDiscoConfirmed(
......
......@@ -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;
}
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;
}
if (_converse.push_service && _converse.push_service_node) {
_converse.api.disco.getIdentity('pubsub', 'push', _converse.push_service)
.then((identity) => {
if (!identity) {
_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);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment