Browse Source

Enable push services for a MUC domain

As soon as a chatroom from that domain is opened and if the MUC supports it.
JC Brand 7 years ago
parent
commit
764686dd19
4 changed files with 217 additions and 148 deletions
  1. 90 62
      dist/converse.js
  2. 44 8
      spec/push.js
  3. 82 77
      src/converse-push.js
  4. 1 1
      tests/utils.js

+ 90 - 62
dist/converse.js

@@ -73489,100 +73489,128 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
         'push_app_servers': []
       });
 
-      function disablePushAppServer(push_app_server) {
+      async function disablePushAppServer(domain, push_app_server) {
         if (!push_app_server.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 app server "${push_app_server.jid}", no disco support from your server.`, Strophe.LogLevel.WARN);
-          }
+        const result = await _converse.api.disco.supports(Strophe.NS.PUSH, domain || _converse.bare_jid);
 
-          const stanza = $iq({
-            'type': 'set'
-          }).c('disable', {
-            'xmlns': Strophe.NS.PUSH,
-            'jid': push_app_server.jid
-          });
+        if (!result.length) {
+          return _converse.log(`Not disabling push app server "${push_app_server.jid}", no disco support from your server.`, Strophe.LogLevel.WARN);
+        }
 
-          if (push_app_server.node) {
-            stanza.attrs({
-              'node': push_app_server.node
-            });
-          }
+        const stanza = $iq({
+          'type': 'set'
+        });
+
+        if (domain !== _converse.bare_jid) {
+          stanza.attrs({
+            'to': domain
+          });
+        }
 
-          _converse.api.sendIQ(stanza).then(() => _converse.session.set('push_enabled', true)).catch(e => {
-            _converse.log(`Could not enable push app server for ${push_app_server.jid}`, Strophe.LogLevel.ERROR);
+        stanza.c('disable', {
+          'xmlns': Strophe.NS.PUSH,
+          'jid': push_app_server.jid
+        });
 
-            _converse.log(e, Strophe.LogLevel.ERROR);
+        if (push_app_server.node) {
+          stanza.attrs({
+            'node': push_app_server.node
           });
-        }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+        }
+
+        _converse.api.sendIQ(stanza).catch(e => {
+          _converse.log(`Could not disable push app server for ${push_app_server.jid}`, Strophe.LogLevel.ERROR);
+
+          _converse.log(e, Strophe.LogLevel.ERROR);
+        });
       }
 
-      function enablePushAppServer(push_app_server) {
+      async function enablePushAppServer(domain, push_app_server) {
         if (!push_app_server.jid || !push_app_server.node) {
           return;
         }
 
-        _converse.api.disco.getIdentity('pubsub', 'push', push_app_server.jid).then(identity => {
-          if (!identity) {
-            return _converse.log(`Not enabling push the service "${push_app_server.jid}", it doesn't have the right disco identtiy.`, Strophe.LogLevel.WARN);
-          }
+        const identity = await _converse.api.disco.getIdentity('pubsub', 'push', push_app_server.jid);
 
-          return Promise.all([_converse.api.disco.supports(Strophe.NS.PUSH, push_app_server.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 app server "${push_app_server.jid}", no disco support from your server.`, Strophe.LogLevel.WARN);
-            }
+        if (!identity) {
+          return _converse.log(`Not enabling push the service "${push_app_server.jid}", it doesn't have the right disco identtiy.`, Strophe.LogLevel.WARN);
+        }
 
-            const stanza = $iq({
-              'type': 'set'
-            }).c('enable', {
-              'xmlns': Strophe.NS.PUSH,
-              'jid': push_app_server.jid,
-              'node': push_app_server.node
-            });
+        const result = await Promise.all([_converse.api.disco.supports(Strophe.NS.PUSH, push_app_server.jid), _converse.api.disco.supports(Strophe.NS.PUSH, domain)]);
 
-            if (push_app_server.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_app_server.secret);
-            }
+        if (!result[0].length && !result[1].length) {
+          return _converse.log(`Not enabling push app server "${push_app_server.jid}", no disco support from your server.`, Strophe.LogLevel.WARN);
+        }
 
-            _converse.api.sendIQ(stanza).then(() => _converse.session.save('push_enabled', true)).catch(e => {
-              _converse.log(`Could not enable push app server for ${push_app_server.jid}`, Strophe.LogLevel.ERROR);
+        const stanza = $iq({
+          'type': 'set'
+        });
 
-              _converse.log(e, Strophe.LogLevel.ERROR);
-            });
-          }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
-        }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+        if (domain !== _converse.bare_jid) {
+          stanza.attrs({
+            'to': domain
+          });
+        }
+
+        stanza.c('enable', {
+          'xmlns': Strophe.NS.PUSH,
+          'jid': push_app_server.jid,
+          'node': push_app_server.node
+        });
+
+        if (push_app_server.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_app_server.secret);
+        }
+
+        return _converse.api.sendIQ(stanza);
       }
 
-      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 app server has been set.
-          //
-          // When enabling or disabling multiple push app servers,
-          // we won't wait until we have confirmation that all have been set.
+      async function enablePush(domain) {
+        domain = domain || _converse.bare_jid;
+        const push_enabled = _converse.session.get('push_enabled') || [];
+
+        if (_.includes(push_enabled, domain)) {
           return;
         }
 
         const enabled_services = _.reject(_converse.push_app_servers, 'disable');
 
-        _.each(enabled_services, enablePushAppServer);
+        try {
+          await Promise.all(_.map(enabled_services, _.partial(enablePushAppServer, domain)));
+        } catch (e) {
+          _converse.log('Could not enable push App Server', Strophe.LogLevel.ERROR);
+
+          if (e) _converse.log(e, Strophe.LogLevel.ERROR);
+        } finally {
+          push_enabled.push(domain);
+        }
 
         const disabled_services = _.filter(_converse.push_app_servers, 'disable');
 
-        _.each(disabled_services, disablePushAppServer);
+        _.each(disabled_services, _.partial(disablePushAppServer, domain));
+
+        _converse.session.save('push_enabled', push_enabled);
+      }
+
+      function onChatBoxAdded(model) {
+        if (model.get('type') == _converse.CHATROOMS_TYPE) {
+          enablePush(Strophe.getDomainFromJid(model.get('jid')));
+        }
       }
 
-      _converse.api.listen.on('statusInitialized', enablePush);
+      _converse.api.listen.on('statusInitialized', () => enablePush());
+
+      _converse.api.listen.on('chatBoxesInitialized', () => _converse.chatboxes.on('add', onChatBoxAdded));
     }
 
   });

+ 44 - 8
spec/push.js

@@ -5,6 +5,7 @@
     var $iq = converse.env.$iq;
     var Strophe = converse.env.Strophe;
     var _ = converse.env._;
+    var f = converse.env.f;
 
     describe("XEP-0357 Push Notifications", function () {
 
@@ -53,9 +54,48 @@
                     'id': stanza.getAttribute('id')
                 })));
                 return test_utils.waitUntil(() => _converse.session.get('push_enabled'))
+            }).then(done).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+        }));
+
+        it("can enabled for a MUC domain",
+            mock.initConverseWithPromises(null,
+                ['rosterGroupsFetched'], {
+                    'push_app_servers': [{
+                        'jid': 'push-5@client.example',
+                        'node': 'yxs32uqsflafdk3iuqo'
+                    }]
+                }, function (done, _converse) {
+
+            const IQ_stanzas = _converse.connection.IQ_stanzas,
+                  room_jid = 'coven@chat.shakespeare.lit';
+            expect(_converse.session.get('push_enabled')).toBeFalsy();
+
+            test_utils.openAndEnterChatRoom(_converse, 'coven', 'chat.shakespeare.lit', 'oldhag')
+            .then(() => test_utils.waitUntilDiscoConfirmed(
+                _converse, _converse.push_app_servers[0].jid,
+                [{'category': 'pubsub', 'type':'push'}],
+                ['urn:xmpp:push:0'], [], 'info'))
+            .then(() => {
+                return test_utils.waitUntilDiscoConfirmed(
+                    _converse, 'chat.shakespeare.lit',
+                    [{'category': 'account', 'type':'registered'}],
+                    ['urn:xmpp:push:0'], [], 'info')
             }).then(() => {
-                done();
-            }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                return test_utils.waitUntil(
+                    () => _.filter(IQ_stanzas, (iq) => iq.nodeTree.querySelector('iq[type="set"] enable[xmlns="urn:xmpp:push:0"]')).pop())
+            }).then(stanza => {
+                expect(stanza.nodeTree.outerHTML).toEqual(
+                    `<iq type="set" xmlns="jabber:client" to="chat.shakespeare.lit" id="${stanza.nodeTree.getAttribute('id')}">`+
+                        '<enable 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.nodeTree.getAttribute('id')
+                })));
+                return test_utils.waitUntil(() => f.includes('chat.shakespeare.lit', _converse.session.get('push_enabled')));
+            }).then(done).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
         }));
 
         it("can be disabled",
@@ -100,9 +140,7 @@
                     'id': stanza.getAttribute('id')
                 })));
                 return test_utils.waitUntil(() => _converse.session.get('push_enabled'))
-            }).then(() => {
-                done();
-            }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+            }).then(done).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
         }));
 
 
@@ -156,9 +194,7 @@
                     'id': stanza.getAttribute('id')
                 })));
                 return test_utils.waitUntil(() => _converse.session.get('push_enabled'))
-            }).then(() => {
-                done();
-            }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+            }).then(done).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
         }));
     });
 }));

+ 82 - 77
src/converse-push.js

@@ -30,98 +30,103 @@
                 'push_app_servers': [],
             });
 
-            function disablePushAppServer (push_app_server) {
+            async function disablePushAppServer (domain, push_app_server) {
                 if (!push_app_server.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 app server "${push_app_server.jid}", no disco support from your server.`,
-                            Strophe.LogLevel.WARN
-                        );
-                    }
-                    const stanza = $iq({'type': 'set'})
-                        .c('disable', {
-                            'xmlns': Strophe.NS.PUSH,
-                            'jid': push_app_server.jid,
-                        });
-                    if (push_app_server.node) {
-                        stanza.attrs({'node': push_app_server.node});
-                    }
-
-                    _converse.api.sendIQ(stanza)
-                        .then(() => _converse.session.set('push_enabled', true))
-                        .catch((e) => {
-                            _converse.log(`Could not enable push app server for ${push_app_server.jid}`, Strophe.LogLevel.ERROR);
-                            _converse.log(e, Strophe.LogLevel.ERROR);
-                        });
-                }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                const result = await _converse.api.disco.supports(Strophe.NS.PUSH, domain || _converse.bare_jid)
+                if (!result.length) {
+                    return _converse.log(
+                        `Not disabling push app server "${push_app_server.jid}", no disco support from your server.`,
+                        Strophe.LogLevel.WARN
+                    );
+                }
+                const stanza = $iq({'type': 'set'});
+                if (domain !== _converse.bare_jid) {
+                    stanza.attrs({'to': domain});
+                }
+                stanza.c('disable', {
+                    'xmlns': Strophe.NS.PUSH,
+                    'jid': push_app_server.jid,
+                });
+                if (push_app_server.node) {
+                    stanza.attrs({'node': push_app_server.node});
+                }
+                _converse.api.sendIQ(stanza)
+                .catch(e => {
+                    _converse.log(`Could not disable push app server for ${push_app_server.jid}`, Strophe.LogLevel.ERROR);
+                    _converse.log(e, Strophe.LogLevel.ERROR);
+                });
             }
 
-            function enablePushAppServer (push_app_server) {
+            async function enablePushAppServer (domain, push_app_server) {
                 if (!push_app_server.jid || !push_app_server.node) {
                     return;
                 }
-                _converse.api.disco.getIdentity('pubsub', 'push', push_app_server.jid)
-                .then(identity => {
-                    if (!identity) {
-                        return _converse.log(
-                            `Not enabling push the service "${push_app_server.jid}", it doesn't have the right disco identtiy.`,
-                            Strophe.LogLevel.WARN
-                        );
-                    }
-                    return Promise.all([
-                        _converse.api.disco.supports(Strophe.NS.PUSH, push_app_server.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 app server "${push_app_server.jid}", no disco support from your server.`,
-                                Strophe.LogLevel.WARN
-                            );
-                        }
-                        const stanza = $iq({'type': 'set'})
-                            .c('enable', {
-                                'xmlns': Strophe.NS.PUSH,
-                                'jid': push_app_server.jid,
-                                'node': push_app_server.node
-                            });
-                        if (push_app_server.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_app_server.secret);
-                        }
-                        _converse.api.sendIQ(stanza)
-                            .then(() => _converse.session.save('push_enabled', true))
-                            .catch((e) => {
-                                _converse.log(`Could not enable push app server for ${push_app_server.jid}`, Strophe.LogLevel.ERROR);
-                                _converse.log(e, Strophe.LogLevel.ERROR);
-                            });
-                    }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
-                }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
+                const identity = await _converse.api.disco.getIdentity('pubsub', 'push', push_app_server.jid);
+                if (!identity) {
+                    return _converse.log(
+                        `Not enabling push the service "${push_app_server.jid}", it doesn't have the right disco identtiy.`,
+                        Strophe.LogLevel.WARN
+                    );
+                }
+                const result = await Promise.all([
+                    _converse.api.disco.supports(Strophe.NS.PUSH, push_app_server.jid),
+                    _converse.api.disco.supports(Strophe.NS.PUSH, domain)
+                ]);
+                if (!result[0].length && !result[1].length) {
+                    return _converse.log(
+                        `Not enabling push app server "${push_app_server.jid}", no disco support from your server.`,
+                        Strophe.LogLevel.WARN
+                    );
+                }
+                const stanza = $iq({'type': 'set'});
+                if (domain !== _converse.bare_jid) {
+                    stanza.attrs({'to': domain});
+                }
+                stanza.c('enable', {
+                    'xmlns': Strophe.NS.PUSH,
+                    'jid': push_app_server.jid,
+                    'node': push_app_server.node
+                });
+                if (push_app_server.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_app_server.secret);
+                }
+                return _converse.api.sendIQ(stanza);
             }
 
-            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 app server has been set.
-                    //
-                    // When enabling or disabling multiple push app servers,
-                    // we won't wait until we have confirmation that all have been set.
+            async function enablePush (domain) {
+                domain = domain || _converse.bare_jid;
+                const push_enabled = _converse.session.get('push_enabled') || [];
+                if (_.includes(push_enabled, domain)) {
                     return;
                 }
                 const enabled_services = _.reject(_converse.push_app_servers, 'disable');
-                _.each(enabled_services, enablePushAppServer);
-
+                try {
+                    await Promise.all(_.map(enabled_services, _.partial(enablePushAppServer, domain)))
+                } catch (e) {
+                    _converse.log('Could not enable push App Server', Strophe.LogLevel.ERROR);
+                    if (e) _converse.log(e, Strophe.LogLevel.ERROR);
+                } finally {
+                    push_enabled.push(domain);
+                }
                 const disabled_services = _.filter(_converse.push_app_servers, 'disable');
-                _.each(disabled_services, disablePushAppServer);
+                _.each(disabled_services, _.partial(disablePushAppServer, domain));
+                _converse.session.save('push_enabled', push_enabled);
             }
-            _converse.api.listen.on('statusInitialized', enablePush);
+
+            function onChatBoxAdded (model) {
+                if (model.get('type') == _converse.CHATROOMS_TYPE) {
+                    enablePush(Strophe.getDomainFromJid(model.get('jid')));
+                }
+            }
+
+            _converse.api.listen.on('statusInitialized', () => enablePush());
+            _converse.api.listen.on('chatBoxesInitialized',  () => _converse.chatboxes.on('add', onChatBoxAdded));
         }
     });
 }));

+ 1 - 1
tests/utils.js

@@ -117,7 +117,7 @@
                 modal.el.querySelector('input[name="nickname"]').value = nick;
                 modal.el.querySelector('form input[type="submit"]').click();
                 resolve();
-            }).catch(_.partial(console.error, _));
+            });
         }).catch(_.partial(console.error, _));
     };