Răsfoiți Sursa

Initial attempt at adding support for multi-session nicks

updates #1197
JC Brand 6 ani în urmă
părinte
comite
0464060fd4
4 a modificat fișierele cu 102 adăugiri și 99 ștergeri
  1. 34 53
      dist/converse.js
  2. 38 3
      spec/chatroom.js
  3. 3 3
      src/converse-muc-views.js
  4. 27 40
      src/converse-muc.js

+ 34 - 53
dist/converse.js

@@ -68708,7 +68708,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
 
         verifyRoles(roles) {
           const me = this.model.occupants.findWhere({
-            'jid': _converse.bare_jid
+            'bare_jid': _converse.bare_jid
           });
 
           if (!_.includes(roles, me.get('role'))) {
@@ -68721,7 +68721,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
 
         verifyAffiliations(affiliations) {
           const me = this.model.occupants.findWhere({
-            'jid': _converse.bare_jid
+            'bare_jid': _converse.bare_jid
           });
 
           if (!_.includes(affiliations, me.get('affiliation'))) {
@@ -68744,7 +68744,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
           if (!this.model.occupants.findWhere({
             'nick': args[0]
           }) && !this.model.occupants.findWhere({
-            'jid': args[0]
+            'bare_jid': args[0]
           })) {
             this.showErrorMessage(__('Error: couldn\'t find a groupchat participant "%1$s"', args[0]));
             return false;
@@ -70358,10 +70358,8 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
             return null;
           }
 
-          const occupant = this.occupants.findOccupant({
+          const occupant = this.occupants.findWhere({
             'nick': longest_match
-          }) || this.occupants.findOccupant({
-            'jid': longest_match
           });
 
           if (!occupant) {
@@ -70375,8 +70373,8 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
             'type': 'mention'
           };
 
-          if (occupant.get('jid')) {
-            obj.uri = `xmpp:${occupant.get('jid')}`;
+          if (occupant.get('bare_jid')) {
+            obj.uri = `xmpp:${occupant.get('bare_jid')}`;
           }
 
           return obj;
@@ -70980,30 +70978,41 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
             return true;
           }
 
-          const occupant = this.occupants.findOccupant(data);
+          const occupant = this.occupants.findWhere({
+            'nick': data.nick
+          });
 
           if (data.type === 'unavailable' && occupant) {
+            // We only destroy the occupant if this is not a nickname change operation.
+            // and if they're not on the member lists.
             if (!_.includes(data.states, converse.MUC_NICK_CHANGED_CODE) && !occupant.isMember()) {
-              // We only destroy the occupant if this is not a nickname change operation.
-              // and if they're not on the member lists.
               // Before destroying we set the new data, so
               // that we can show the disconnection message.
-              occupant.set(data);
+              // TODO: see whether we need to check for multiple jids
+              const attributes = _.extend(data, {
+                'bare_jid': data.jid ? Strophe.getBareJidFromJid(data.jid) : undefined,
+                'jids': data.jid ? [data.jid] : []
+              });
+
+              occupant.set(attributes);
               occupant.destroy();
               return;
             }
           }
 
-          const jid = Strophe.getBareJidFromJid(data.jid);
-
-          const attributes = _.extend(data, {
-            'jid': jid ? jid : undefined,
-            'resource': data.jid ? Strophe.getResourceFromJid(data.jid) : undefined
-          });
-
           if (occupant) {
+            const attributes = _.extend(data, {
+              'bare_jid': data.jid ? Strophe.getBareJidFromJid(data.jid) : undefined,
+              'jids': data.jid ? _.concat(occupant.get('jids'), data.jid) : []
+            });
+
             occupant.save(attributes);
           } else {
+            const attributes = _.extend(data, {
+              'bare_jid': data.jid ? Strophe.getBareJidFromJid(data.jid) : undefined,
+              'jids': data.jid ? [data.jid] : []
+            });
+
             this.occupants.create(attributes);
           }
         },
@@ -71263,7 +71272,8 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
       });
       _converse.ChatRoomOccupant = Backbone.Model.extend({
         defaults: {
-          'show': 'offline'
+          'show': 'offline',
+          'jids': []
         },
 
         initialize(attributes) {
@@ -71328,7 +71338,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
             });
 
             _.each(removed_members, occupant => {
-              if (occupant.get('jid') === _converse.bare_jid) {
+              if (occupant.get('bare_jid') === _converse.bare_jid) {
                 return;
               }
 
@@ -71338,17 +71348,9 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
             });
 
             _.each(new_members, attrs => {
-              let occupant;
-
-              if (attrs.jid) {
-                occupant = this.findOccupant({
-                  'jid': attrs.jid
-                });
-              } else {
-                occupant = this.findOccupant({
-                  'nick': attrs.nick
-                });
-              }
+              const occupant = this.findWhere({
+                'nick': attrs.nick
+              });
 
               if (occupant) {
                 occupant.save(attrs);
@@ -71357,27 +71359,6 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
               }
             });
           }).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
-        },
-
-        findOccupant(data) {
-          /* Try to find an existing occupant based on the passed in
-           * data object.
-           *
-           * If we have a JID, we use that as lookup variable,
-           * otherwise we use the nick. We don't always have both,
-           * but should have at least one or the other.
-           */
-          const jid = Strophe.getBareJidFromJid(data.jid);
-
-          if (jid !== null) {
-            return this.where({
-              'jid': jid
-            }).pop();
-          } else {
-            return this.where({
-              'nick': data.nick
-            }).pop();
-          }
         }
 
       });

+ 38 - 3
spec/chatroom.js

@@ -12,7 +12,8 @@
           Backbone = converse.env.Backbone,
           u = converse.env.utils;
 
-    return describe("Chatrooms", function () {
+    describe("Chatrooms", function () {
+
         describe("The \"rooms\" API", function () {
 
             it("has a method 'close' which closes rooms by JID or all rooms when called with no arguments",
@@ -1150,6 +1151,41 @@
                 }).catch(_.partial(console.error, _));
             }));
 
+            it("can handle multi-session nicknames",
+                mock.initConverseWithPromises(null, ['rosterGroupsFetched'], {}, function (done, _converse) {
+
+                test_utils.openAndEnterChatRoom(_converse, 'coven', 'chat.shakespeare.lit', 'oldhag').then(() => {
+                    let presence = $pres({
+                        'to':'dummy@localhost/pda',
+                        'from':"coven@chat.shakespeare.lit/my1stNick"
+                    }).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
+                    .c('item').attrs({
+                        jid: 'someone@localhost/foo',
+                        role: 'moderator',
+                    });
+
+                    _converse.connection._dataRecv(test_utils.createRequest(presence));
+                    const view = _converse.chatboxviews.get('coven@chat.shakespeare.lit');
+                    let occupants = view.el.querySelector('.occupant-list').querySelectorAll('li .occupant-nick');
+                    expect(occupants.length).toBe(2);
+                    expect(occupants.pop().textContent.trim()).toBe("my1stNick");
+
+                    presence = $pres({
+                        'to':'dummy@localhost/pda',
+                        'from':"coven@chat.shakespeare.lit/my2ndNick"
+                    }).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
+                    .c('item').attrs({
+                        jid: 'someone@localhost/bar',
+                        role: 'moderator',
+                    });
+                    _converse.connection._dataRecv(test_utils.createRequest(presence));
+                    occupants = view.el.querySelector('.occupant-list').querySelectorAll('li .occupant-nick');
+                    expect(occupants.length).toBe(3);
+                    expect(occupants.pop().textContent.trim()).toBe("my2ndNick");
+                    done();
+                });
+            }));
+
             it("escapes occupant nicknames when rendering them, to avoid JS-injection attacks",
                 mock.initConverseWithPromises(null, ['rosterGroupsFetched'], {}, function (done, _converse) {
 
@@ -1229,8 +1265,7 @@
                     .c('item').attrs({
                         jid: contact_jid,
                         role: 'visitor',
-                    }).up()
-                    .c('status').attrs({code:'110'}).nodeTree;
+                    });
                     _converse.connection._dataRecv(test_utils.createRequest(presence));
 
                     occupants = view.el.querySelector('.occupant-list').querySelectorAll('li');

+ 3 - 3
src/converse-muc-views.js

@@ -833,7 +833,7 @@
                 },
 
                 verifyRoles (roles) {
-                    const me = this.model.occupants.findWhere({'jid': _converse.bare_jid});
+                    const me = this.model.occupants.findWhere({'bare_jid': _converse.bare_jid});
                     if (!_.includes(roles, me.get('role'))) {
                         this.showErrorMessage(__(`Forbidden: you do not have the necessary role in order to do that.`))
                         return false;
@@ -842,7 +842,7 @@
                 },
 
                 verifyAffiliations (affiliations) {
-                    const me = this.model.occupants.findWhere({'jid': _converse.bare_jid});
+                    const me = this.model.occupants.findWhere({'bare_jid': _converse.bare_jid});
                     if (!_.includes(affiliations, me.get('affiliation'))) {
                         this.showErrorMessage(__(`Forbidden: you do not have the necessary affiliation in order to do that.`))
                         return false;
@@ -860,7 +860,7 @@
                         );
                         return false;
                     }
-                    if (!this.model.occupants.findWhere({'nick': args[0]}) && !this.model.occupants.findWhere({'jid': args[0]})) {
+                    if (!this.model.occupants.findWhere({'nick': args[0]}) && !this.model.occupants.findWhere({'bare_jid': args[0]})) {
                         this.showErrorMessage(__('Error: couldn\'t find a groupchat participant "%1$s"', args[0]));
                         return false;
                     }

+ 27 - 40
src/converse-muc.js

@@ -341,8 +341,7 @@
                         // match.
                         return null;
                     }
-                    const occupant = this.occupants.findOccupant({'nick': longest_match}) ||
-                            this.occupants.findOccupant({'jid': longest_match});
+                    const occupant = this.occupants.findWhere({'nick': longest_match});
                     if (!occupant) {
                         return null;
                     }
@@ -352,8 +351,8 @@
                         'value': longest_match,
                         'type': 'mention'
                     };
-                    if (occupant.get('jid')) {
-                        obj.uri = `xmpp:${occupant.get('jid')}`
+                    if (occupant.get('bare_jid')) {
+                        obj.uri = `xmpp:${occupant.get('bare_jid')}`
                     }
                     return obj;
                 },
@@ -873,26 +872,34 @@
                     if (data.type === 'error' || (!data.jid && !data.nick)) {
                         return true;
                     }
-                    const occupant = this.occupants.findOccupant(data);
+                    const occupant = this.occupants.findWhere({'nick': data.nick});
                     if (data.type === 'unavailable' && occupant) {
+                        // We only destroy the occupant if this is not a nickname change operation.
+                        // and if they're not on the member lists.
                         if (!_.includes(data.states, converse.MUC_NICK_CHANGED_CODE) && !occupant.isMember()) {
-                            // We only destroy the occupant if this is not a nickname change operation.
-                            // and if they're not on the member lists.
                             // Before destroying we set the new data, so
                             // that we can show the disconnection message.
-                            occupant.set(data);
+                            // TODO: see whether we need to check for multiple jids
+                            const attributes = _.extend(data, {
+                                'bare_jid': data.jid ? Strophe.getBareJidFromJid(data.jid) : undefined,
+                                'jids': data.jid ? [data.jid] : []
+                            });
+                            occupant.set(attributes);
                             occupant.destroy();
                             return;
                         }
                     }
-                    const jid = Strophe.getBareJidFromJid(data.jid);
-                    const attributes = _.extend(data, {
-                        'jid': jid ? jid : undefined,
-                        'resource': data.jid ? Strophe.getResourceFromJid(data.jid) : undefined
-                    });
                     if (occupant) {
+                        const attributes = _.extend(data, {
+                            'bare_jid': data.jid ? Strophe.getBareJidFromJid(data.jid) : undefined,
+                            'jids': data.jid ? _.concat(occupant.get('jids'), data.jid) : []
+                        });
                         occupant.save(attributes);
                     } else {
+                        const attributes = _.extend(data, {
+                            'bare_jid': data.jid ? Strophe.getBareJidFromJid(data.jid) : undefined,
+                            'jids': data.jid ? [data.jid] : []
+                        });
                         this.occupants.create(attributes);
                     }
                 },
@@ -1113,7 +1120,8 @@
             _converse.ChatRoomOccupant = Backbone.Model.extend({
 
                 defaults: {
-                    'show': 'offline'
+                    'show': 'offline',
+                    'jids': []
                 },
 
                 initialize (attributes) {
@@ -1175,19 +1183,14 @@
                                         !f.includes(m.get('jid'), new_jids);
                               });
 
-                        _.each(removed_members, (occupant) => {
-                            if (occupant.get('jid') === _converse.bare_jid) { return; }
+                        _.each(removed_members, occupant => {
+                            if (occupant.get('bare_jid') === _converse.bare_jid) { return; }
                             if (occupant.get('show') === 'offline') {
                                 occupant.destroy();
                             }
                         });
-                        _.each(new_members, (attrs) => {
-                            let occupant;
-                            if (attrs.jid) {
-                                occupant = this.findOccupant({'jid': attrs.jid});
-                            } else {
-                                occupant = this.findOccupant({'nick': attrs.nick});
-                            }
+                        _.each(new_members, attrs => {
+                            const occupant = this.findWhere({'nick': attrs.nick});
                             if (occupant) {
                                 occupant.save(attrs);
                             } else {
@@ -1195,22 +1198,6 @@
                             }
                         });
                     }).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
-                },
-
-                findOccupant (data) {
-                    /* Try to find an existing occupant based on the passed in
-                     * data object.
-                     *
-                     * If we have a JID, we use that as lookup variable,
-                     * otherwise we use the nick. We don't always have both,
-                     * but should have at least one or the other.
-                     */
-                    const jid = Strophe.getBareJidFromJid(data.jid);
-                    if (jid !== null) {
-                        return this.where({'jid': jid}).pop();
-                    } else {
-                        return this.where({'nick': data.nick}).pop();
-                    }
                 }
             });
 
@@ -1218,7 +1205,7 @@
             _converse.RoomsPanelModel = Backbone.Model.extend({
                 defaults: {
                     'muc_domain': '',
-                },
+                }
             });