From 2df9b2421150a2a881baf5a76183ff19049061b2 Mon Sep 17 00:00:00 2001 From: JC Brand Date: Tue, 4 Sep 2018 11:39:27 +0200 Subject: [PATCH] Add option to auto-register your nickname to a room See https://xmpp.org/extensions/xep-0045.html#register --- .eslintrc.json | 2 +- CHANGES.md | 35 ++++---- dist/converse.js | 85 ++++++++++++++++++- docs/source/configuration.rst | 10 +++ sass/font-awesome.scss | 2 +- spec/chatroom.js | 7 +- spec/room_registration.js | 44 ++++++++++ src/converse-core.js | 3 +- src/converse-muc-views.js | 8 +- src/converse-muc.js | 73 ++++++++++++++++ .../chatroom_registration_modal.html | 19 +++++ tests/runner.js | 1 + 12 files changed, 258 insertions(+), 31 deletions(-) create mode 100644 spec/room_registration.js create mode 100644 src/templates/chatroom_registration_modal.html diff --git a/.eslintrc.json b/.eslintrc.json index 81ea3cc67..2d75e6ebd 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -111,7 +111,7 @@ "no-bitwise": "off", "no-caller": "error", "no-console": "off", - "no-catch-shadow": "error", + "no-catch-shadow": "off", "no-cond-assign": [ "error", "except-parens" diff --git a/CHANGES.md b/CHANGES.md index f9d0042af..aaad79ad1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,7 @@ ## 4.0.1 (Unreleased) +- New configuration setting [auto_register_muc_nickname](https://conversejs.org/docs/html/configuration.html#auto-register-muc-nickname) - #1182 MUC occupants without nick or JID created - #1184 Notification error when message has no body @@ -30,7 +31,7 @@ If the device is not trusted, sessionStorage is used and all user data is deleted from the browser cache upon logout. If the device is trusted, localStorage is used and user data is cached indefinitely. - Initial support for [XEP-0357 Push Notifications](https://xmpp.org/extensions/xep-0357.html), specifically registering an "App Server". -- Add support for logging in via OAuth (see the [oauth_providers](https://conversejs.org/docs/html/configurations.html#oauth-providers) setting) +- Add support for logging in via OAuth (see the [oauth_providers](https://conversejs.org/docs/html/configuration.html#oauth-providers) setting) ### Bugfixes @@ -61,7 +62,7 @@ ## Configuration changes -- Removed the `storage` configuration setting, use [trusted](https://conversejs.org/docs/html/configurations.html#trusted) instead. +- Removed the `storage` configuration setting, use [trusted](https://conversejs.org/docs/html/configuration.html#trusted) instead. - Removed the `use_vcards` configuration setting, instead VCards are always used. - Removed the `xhr_custom_status` and `xhr_custom_status_url` configuration settings. If you relied on these settings, you can instead listen for the @@ -71,8 +72,8 @@ - `xhr_user_search_url` has to include the `?` character now in favor of more flexibility. See example in the documentation. - The data returned from the `xhr_user_search_url` must now include the user's `jid` instead of just an `id`. -- New configuration settings [nickname](https://conversejs.org/docs/html/configurations.html#nickname) - and [auto_join_private_chats](https://conversejs.org/docs/html/configurations.html#auto-join-private-chats). +- New configuration settings [nickname](https://conversejs.org/docs/html/configuration.html#nickname) + and [auto_join_private_chats](https://conversejs.org/docs/html/configuration.html#auto-join-private-chats). ## Architectural changes @@ -133,7 +134,7 @@ - Listen for new room bookmarks pushed from the user's PEP service. - Simplified the [embedded](https://conversejs.org/demo/embedded.html) usecase. - No need to manually blacklist or whitelist any plugins. - - Relies on the [view_mode](https://conversejs.org/docs/html/configurations.html#view-mode) being set to `'embedded'`. + - Relies on the [view_mode](https://conversejs.org/docs/html/configuration.html#view-mode) being set to `'embedded'`. - The main `converse.js` build can be used for the embedded usecase. - Maintain MUC session upon page reload @@ -142,9 +143,9 @@ ### Configuration settings - `auto_reconnect` is now set to `true` by default. -- New configuration setting [allow_public_bookmarks](https://conversejs.org/docs/html/configurations.html#allow-public-bookmarks) -- New configuration setting [root](https://conversejs.org/docs/html/configurations.html#root) -- The [view_mode](https://conversejs.org/docs/html/configurations.html#view-mode) setting now has a new possible value: `embedded` +- New configuration setting [allow_public_bookmarks](https://conversejs.org/docs/html/configuration.html#allow-public-bookmarks) +- New configuration setting [root](https://conversejs.org/docs/html/configuration.html#root) +- The [view_mode](https://conversejs.org/docs/html/configuration.html#view-mode) setting now has a new possible value: `embedded` ### Translation updates - Chinese (Traditional), French, German, Portuguese (Brazil), Russian, Ukrainian @@ -173,7 +174,7 @@ ### UI/UX changes - Add new configuration option - [show_message_load_animation](https://conversejs.org/docs/html/configurations.html#show-message-load-animation) + [show_message_load_animation](https://conversejs.org/docs/html/configuration.html#show-message-load-animation) with a default value of `false`. The message load animations (added in 3.3.0) cause slowness and performance issues in Firefox, so they're now disabled by default. @@ -210,7 +211,7 @@ and private chats with a URL fragment such as `#converse/chat?jid=user@domain` - #828 Add routing for the `#converse/login` and `#converse/register` URL fragments, which will render the registration and login forms respectively. -- New configuration setting [view_mode](https://conversejs.org/docs/html/configurations.html#view-mode) +- New configuration setting [view_mode](https://conversejs.org/docs/html/configuration.html#view-mode) This removes the need for separate `inverse.js` and `converse-mobile.js` builds. Instead the `converse.js` build is now used with `view_mode` set to `fullscreen` and `mobile` respectively. @@ -248,7 +249,7 @@ - Converse.js no longer includes all the translations in its build. Instead, only the currently relevant translation is requested. This results in a much smaller filesize but means that the translations you want to provide need to - be available. See the [locales_url](https://conversejs.org/docs/html/configurations.html#locales-url) + be available. See the [locales_url](https://conversejs.org/docs/html/configuration.html#locales-url) configuration setting for more info. - The translation machinery has now been moved to a separate module in `src/i18n.js`. - jQuery has been completely removed as a dependency (still used in tests though). @@ -277,10 +278,10 @@ ### New configuration settings * The `visible_toolbar_buttons.emoticons` configuration option is now changed to `visible_toolbar_buttons.emoji`. -* [use_emojione](https://conversejs.org/docs/html/configurations.html#use-emojione) +* [use_emojione](https://conversejs.org/docs/html/configuration.html#use-emojione) is used to determine whether Emojione should be used to render emojis, otherwise rendering falls back to native browser or OS support. -* [emojione_image_path](https://conversejs.org/docs/html/configurations.html#emojione-image-path) +* [emojione_image_path](https://conversejs.org/docs/html/configuration.html#emojione-image-path) is used to specify from where Emojione will load images for rendering emojis. ### New events @@ -334,7 +335,7 @@ More info here: https://github.com/LeaVerou/awesomplete/pull/17082 ### New configuration settings - New setting for `converse-bookmarks`: - [hide_open_bookmarks](https://conversejs.org/docs/html/configurations.html#hide-open-bookmarks) + [hide_open_bookmarks](https://conversejs.org/docs/html/configuration.html#hide-open-bookmarks) It is meant to be set to `true` when using `converse-roomslist` so that open rooms aren't listed twice (in the rooms list and the bookmarks list). [jcbrand] @@ -388,13 +389,13 @@ More info here: https://github.com/LeaVerou/awesomplete/pull/17082 - #628 Fixes the bug in displaying chat status during private chat. [saganshul] - #628 Changes the message displayed while typing from a different resource of the same user. [smitbose] - #675 Time format made configurable. - See [time_format](https://conversejs.org/docs/html/configurations.html#time-format) + See [time_format](https://conversejs.org/docs/html/configuration.html#time-format) [smitbose] - #682 Add "Send" button to input box in chat dialog window. - See [show_send_button](https://conversejs.org/docs/html/configurations.html#show-send-button) + See [show_send_button](https://conversejs.org/docs/html/configuration.html#show-send-button) [saganshul] - #704 Automatic fetching of registration form when - [registration_domain](https://conversejs.org/docs/html/configurations.html#registration-domain) + [registration_domain](https://conversejs.org/docs/html/configuration.html#registration-domain) is set. [smitbose] - #806 The `_converse.listen` API event listeners aren't triggered. [jcbrand] - #807 Error: Plugin "converse-dragresize" tried to override HeadlinesBoxView but it's not found. [jcbrand] diff --git a/dist/converse.js b/dist/converse.js index f121e38ef..ddf96f203 100644 --- a/dist/converse.js +++ b/dist/converse.js @@ -62864,6 +62864,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ Strophe.addNamespace('NICK', 'http://jabber.org/protocol/nick'); Strophe.addNamespace('OUTOFBAND', 'jabber:x:oob'); Strophe.addNamespace('PUBSUB', 'http://jabber.org/protocol/pubsub'); + Strophe.addNamespace('REGISTER', 'jabber:iq:register'); Strophe.addNamespace('ROSTERX', 'http://jabber.org/protocol/rosterx'); Strophe.addNamespace('RSM', 'http://jabber.org/protocol/rsm'); Strophe.addNamespace('SID', 'urn:xmpp:sid:0'); @@ -68982,10 +68983,10 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ * If so, we'll use that, otherwise we render the nickname form. */ this.showSpinner(); - this.model.checkForReservedNick(this.onNickNameFound.bind(this), this.onNickNameNotFound.bind(this)); + this.model.checkForReservedNick(this.onReservedNicknameFound.bind(this), this.onReservedNicknameNotFound.bind(this)); }, - onNickNameFound(iq) { + onReservedNicknameFound(iq) { /* We've received an IQ response from the server which * might contain the user's reserved nickname. * If no nickname is found we either render a form for @@ -69005,7 +69006,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ } }, - onNickNameNotFound(message) { + onReservedNicknameNotFound(message) { const nick = this.getDefaultNickName(); if (nick) { @@ -70032,6 +70033,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } allow_muc_invitations: true, auto_join_on_invite: false, auto_join_rooms: [], + auto_register_muc_nickname: false, muc_domain: undefined, muc_history_max_stanzas: undefined, muc_instant_rooms: true, @@ -70100,12 +70102,24 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } initialize() { this.constructor.__super__.initialize.apply(this, arguments); + this.on('change:connection_status', this.onConnectionStatusChanged, this); this.occupants = new _converse.ChatRoomOccupants(); this.occupants.browserStorage = new Backbone.BrowserStorage.session(b64_sha1(`converse.occupants-${_converse.bare_jid}${this.get('jid')}`)); this.occupants.chatroom = this; this.registerHandlers(); }, + async onConnectionStatusChanged() { + if (this.get('connection_status') === converse.ROOMSTATUS.ENTERED && _converse.auto_register_muc_nickname) { + debugger; + const result = await _converse.api.disco.supports(Strophe.NS.MUC_REGISTER, this.get('jid')); + + if (result.length) { + this.registerNickname(); + } + } + }, + registerHandlers() { /* Register presence and message handlers for this chat * groupchat @@ -70808,6 +70822,53 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } return this; }, + async registerNickname() { + try { + await _converse.api.sendIQ($iq({ + 'from': _converse.bare_jid, + 'to': this.get('jid'), + 'type': 'get' + }).c('query', { + 'xmlns': Strophe.NS.MUC_REGISTER + })); + } catch (e) { + if (sizzle('item-not-found[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', e).length) { + _converse.log(`Can't register nickname ${this.get('nick')} in the groupchat ${this.get('jid')} which does not exist.`); + } else if (sizzle('not-allowed[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', e).length) { + _converse.log(`You're not allowed to register in the groupchat ${this.get('jid')}`); + } + + return _converse.log(e, Strophe.LogLevel.ERROR); + } + + try { + await _converse.api.sendIQ($iq({ + 'from': _converse.bare_jid, + 'to': this.get('jid'), + 'type': 'set' + }).c('query', { + 'xmlns': Strophe.NS.MUC_REGISTER + }).c('x', { + 'xmlns': Strophe.NS.XFORM, + 'type': 'submit' + }).c('field', { + 'var': 'FORM_TYPE' + }).c('value').t('http://jabber.org/protocol/muc#register').up().up().c('field', { + 'var': 'muc#register_roomnick' + }).c('value').t(this.get('nick'))); + } catch (e) { + if (sizzle('conflict[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', e).length) { + _converse.log(`Can't register nickname ${this.get('nick')} in the groupchat ${this.get('jid')}, it's already taken.`); + } else if (sizzle('service-unavailable[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', e).length) { + _converse.log(`Can't register nickname ${this.get('nick')} in the groupchat ${this.get('jid')}, it doesn't support registration.`); + } else if (sizzle('bad-request[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', e).length) { + _converse.log(`Can't register nickname ${this.get('nick')} in the groupchat ${this.get('jid')}, invalid data form supplied.`); + } + + return _converse.log(e, Strophe.LogLevel.ERROR); + } + }, + updateOccupantsOnPresence(pres) { /* Given a presence stanza, update the occupant model * based on its contents. @@ -71330,6 +71391,22 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } } }); } + + function fetchRegistrationForm(room_jid, user_jid) { + _converse.api.sendIQ($iq({ + 'from': user_jid, + 'to': room_jid, + 'type': 'get' + }).c('query', { + 'xmlns': Strophe.NS.REGISTER + })).then(iq => {}).catch(iq => { + if (sizzle('item-not-found[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', iq).length) { + this.feedback.set('error', __(`Error: the groupchat ${this.model.getDisplayName()} does not exist.`)); + } else if (sizzle('not-allowed[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]').length) { + this.feedback.set('error', __(`Sorry, you're not allowed to registerd in this groupchat`)); + } + }); + } /************************ BEGIN Event Handlers ************************/ @@ -78494,6 +78571,8 @@ __e(o.info_configure) + } ; __p += '\n \n \n\n'; return __p }; diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst index 06bc6b298..1de0839d4 100644 --- a/docs/source/configuration.rst +++ b/docs/source/configuration.rst @@ -328,6 +328,16 @@ wiped from memory. This configuration can however still be useful when using Converse in desktop apps, for example those based on `CEF `_ or `electron `_. +auto_register_muc_nickname +-------------------------- + +* Default: ``false`` + +Determines whether Converse should automatically register a user's nickname +when they enter a groupchat. + +See here fore more details: https://xmpp.org/extensions/xep-0045.html#register + auto_subscribe -------------- diff --git a/sass/font-awesome.scss b/sass/font-awesome.scss index 82595c42f..92f55d110 100644 --- a/sass/font-awesome.scss +++ b/sass/font-awesome.scss @@ -10,7 +10,6 @@ url('webfonts/fa-brands-400.svg#fontawesome') format('svg'); } - @font-face { font-family: 'ConverseFontAwesomeRegular'; font-style: normal; @@ -46,6 +45,7 @@ font-family: 'ConverseFontAwesomeSolid' !important; font-weight: 900; } + .fab { font-family: 'ConverseFontAwesomeBrands'; } diff --git a/spec/chatroom.js b/spec/chatroom.js index fee167686..46446888e 100644 --- a/spec/chatroom.js +++ b/spec/chatroom.js @@ -12,7 +12,7 @@ Backbone = converse.env.Backbone, u = converse.env.utils; - return describe("ChatRooms", function () { + return 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", @@ -816,9 +816,8 @@ null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, function (done, _converse) { - var view; - var sent_IQ, IQ_id; - var sendIQ = _converse.connection.sendIQ; + let view, sent_IQ, IQ_id; + const sendIQ = _converse.connection.sendIQ; spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { sent_IQ = iq; IQ_id = sendIQ.bind(this)(iq, callback, errback); diff --git a/spec/room_registration.js b/spec/room_registration.js new file mode 100644 index 000000000..29396ecd3 --- /dev/null +++ b/spec/room_registration.js @@ -0,0 +1,44 @@ +(function (root, factory) { + define(["jasmine", "mock", "test-utils" ], factory); +} (this, function (jasmine, mock, test_utils) { + const _ = converse.env._, + $iq = converse.env.$iq, + Strophe = converse.env.Strophe, + u = converse.env.utils; + + describe("The _converse.api.rooms API", function () { + + it("allows you to register a user with a room", + mock.initConverseWithPromises( + null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, + function (done, _converse) { + + let view; + const room_jid = 'coven@chat.shakespeare.lit'; + test_utils.openAndEnterChatRoom(_converse, 'coven', 'chat.shakespeare.lit', 'romeo') + .then(() => { + view = _converse.chatboxviews.get(room_jid); + _converse.api.rooms.register(room_jid, _converse.bare_jid, 'romeo'); + return test_utils.waitUntil(() => _.get(_.filter( + _converse.connection.IQ_stanzas, + iq => iq.nodeTree.querySelector(`iq[to="coven@chat.shakespeare.lit"] query[xmlns="jabber:iq:register"]`) + ).pop(), 'nodeTree')); + }).then(stanza => { + expect(stanza.outerHTML) + .toBe(``+ + ``); + // Room does not exist + const result = $iq({ + 'from': view.model.get('jid'), + 'id': stanza.getAttribute('id'), + 'to': _converse.bare_jid, + 'type': 'error', + }).c('error', {'type': "cancel"}) + .c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"}) + _converse.connection._dataRecv(test_utils.createRequest(result)); + done(); + }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); + })); + }); +})); diff --git a/src/converse-core.js b/src/converse-core.js index d7fe14fab..56efadac4 100644 --- a/src/converse-core.js +++ b/src/converse-core.js @@ -39,6 +39,7 @@ Strophe.addNamespace('NICK', 'http://jabber.org/protocol/nick'); Strophe.addNamespace('OUTOFBAND', 'jabber:x:oob'); Strophe.addNamespace('PUBSUB', 'http://jabber.org/protocol/pubsub'); + Strophe.addNamespace('REGISTER', 'jabber:iq:register'); Strophe.addNamespace('ROSTERX', 'http://jabber.org/protocol/rosterx'); Strophe.addNamespace('RSM', 'http://jabber.org/protocol/rsm'); Strophe.addNamespace('SID', 'urn:xmpp:sid:0'); @@ -484,7 +485,7 @@ // Waiting time of less then one second means features aren't used. return; } - _converse.idle_seconds = 0; + _converse.idle_seconds = 0 _converse.auto_changed_status = false; // Was the user's status changed by _converse.js? window.addEventListener('click', _converse.onUserActivity); window.addEventListener('focus', _converse.onUserActivity); diff --git a/src/converse-muc-views.js b/src/converse-muc-views.js index 7a7d5b6af..c81eda103 100644 --- a/src/converse-muc-views.js +++ b/src/converse-muc-views.js @@ -1204,12 +1204,12 @@ */ this.showSpinner(); this.model.checkForReservedNick( - this.onNickNameFound.bind(this), - this.onNickNameNotFound.bind(this) + this.onReservedNicknameFound.bind(this), + this.onReservedNicknameNotFound.bind(this) ) }, - onNickNameFound (iq) { + onReservedNicknameFound (iq) { /* We've received an IQ response from the server which * might contain the user's reserved nickname. * If no nickname is found we either render a form for @@ -1228,7 +1228,7 @@ } }, - onNickNameNotFound (message) { + onReservedNicknameNotFound (message) { const nick = this.getDefaultNickName(); if (nick) { this.join(nick); diff --git a/src/converse-muc.js b/src/converse-muc.js index b868cfa2e..7f58f8ad4 100644 --- a/src/converse-muc.js +++ b/src/converse-muc.js @@ -113,6 +113,7 @@ allow_muc_invitations: true, auto_join_on_invite: false, auto_join_rooms: [], + auto_register_muc_nickname: false, muc_domain: undefined, muc_history_max_stanzas: undefined, muc_instant_rooms: true, @@ -184,6 +185,8 @@ initialize() { this.constructor.__super__.initialize.apply(this, arguments); + this.on('change:connection_status', this.onConnectionStatusChanged, this); + this.occupants = new _converse.ChatRoomOccupants(); this.occupants.browserStorage = new Backbone.BrowserStorage.session( b64_sha1(`converse.occupants-${_converse.bare_jid}${this.get('jid')}`) @@ -192,6 +195,18 @@ this.registerHandlers(); }, + async onConnectionStatusChanged () { + if (this.get('connection_status') === converse.ROOMSTATUS.ENTERED && + _converse.auto_register_muc_nickname && + this.get('reserved_nick')) { + + const result = await _converse.api.disco.supports(Strophe.NS.MUC_REGISTER, this.get('jid')); + if (result.length) { + this.registerNickname() + } + } + }, + registerHandlers () { /* Register presence and message handlers for this chat * groupchat @@ -798,6 +813,45 @@ return this; }, + async registerNickname () { + try { + await _converse.api.sendIQ( + $iq({ + 'from': _converse.bare_jid, + 'to': this.get('jid'), + 'type': 'get' + }).c('query', {'xmlns': Strophe.NS.MUC_REGISTER}) + ); + } catch (e) { + if (sizzle('item-not-found[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', e).length) { + _converse.log(`Can't register nickname ${this.get('nick')} in the groupchat ${this.get('jid')} which does not exist.`); + } else if (sizzle('not-allowed[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', e).length) { + _converse.log(`You're not allowed to register in the groupchat ${this.get('jid')}`); + } + return _converse.log(e, Strophe.LogLevel.ERROR); + } + try { + await _converse.api.sendIQ($iq({ + 'from': _converse.bare_jid, + 'to': this.get('jid'), + 'type': 'set' + }).c('query', {'xmlns': Strophe.NS.MUC_REGISTER}) + .c('x', {'xmlns': Strophe.NS.XFORM, 'type': 'submit'}) + .c('field', {'var': 'FORM_TYPE'}).c('value').t('http://jabber.org/protocol/muc#register').up().up() + .c('field', {'var': 'muc#register_roomnick'}).c('value').t(this.get('nick')) + ); + } catch (e) { + if (sizzle('conflict[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', e).length) { + _converse.log(`Can't register nickname ${this.get('nick')} in the groupchat ${this.get('jid')}, it's already taken.`); + } else if (sizzle('service-unavailable[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', e).length) { + _converse.log(`Can't register nickname ${this.get('nick')} in the groupchat ${this.get('jid')}, it doesn't support registration.`); + } else if (sizzle('bad-request[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', e).length) { + _converse.log(`Can't register nickname ${this.get('nick')} in the groupchat ${this.get('jid')}, invalid data form supplied.`); + } + return _converse.log(e, Strophe.LogLevel.ERROR); + } + }, + updateOccupantsOnPresence (pres) { /* Given a presence stanza, update the occupant model * based on its contents. @@ -1259,6 +1313,25 @@ }); } + function fetchRegistrationForm (room_jid, user_jid) { + _converse.api.sendIQ( + $iq({ + 'from': user_jid, + 'to': room_jid, + 'type': 'get' + }).c('query', {'xmlns': Strophe.NS.REGISTER}) + ).then(iq => { + + }).catch(iq => { + if (sizzle('item-not-found[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', iq).length) { + this.feedback.set('error', __(`Error: the groupchat ${this.model.getDisplayName()} does not exist.`)); + } else if (sizzle('not-allowed[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]').length) { + this.feedback.set('error', __(`Sorry, you're not allowed to registerd in this groupchat`)); + } + }); + } + + /************************ BEGIN Event Handlers ************************/ _converse.on('addClientFeatures', () => { if (_converse.allow_muc) { diff --git a/src/templates/chatroom_registration_modal.html b/src/templates/chatroom_registration_modal.html new file mode 100644 index 000000000..e721075a1 --- /dev/null +++ b/src/templates/chatroom_registration_modal.html @@ -0,0 +1,19 @@ + diff --git a/tests/runner.js b/tests/runner.js index bd269de87..31e3a66d6 100644 --- a/tests/runner.js +++ b/tests/runner.js @@ -202,6 +202,7 @@ var specs = [ "spec/user-details-modal", "spec/messages", "spec/chatroom", + "spec/room_registration", "spec/autocomplete", "spec/minchats", "spec/notification",