Browse Source

config option for roomid validation

Christoph Scholz 5 years ago
parent
commit
e2d744ddc4

+ 2 - 0
CHANGES.md

@@ -4,6 +4,8 @@
 - #1793: Send button doesn't appear in Firefox in 1:1 chats
 - #1822: Don't log error if user has no bookmarks
 - #1820: Set focus on jid field after controlbox is loaded
+- #1823: New config options [muc_roomid_policy](https://conversejs.org/docs/html/configuration.html#muc-roomid-policy)
+  and [muc_roomid_policy_hint](https://conversejs.org/docs/html/configuration.html#muc-roomid-policy-hint)
 
 ## 6.0.0 (2020-01-09)
 

+ 44 - 0
docs/source/configuration.rst

@@ -1150,6 +1150,50 @@ all MUCs with set autojoin flag in their respective bookmarks will be joined on
 startup of Converse. When set to ``false`` no MUCs are automatically joined based on
 their bookmarks.
 
+muc_roomid_policy
+-----------------
+
+* Default: ``null``
+
+This option defines the regular expression that a room id must satisfy to allow the
+room creation. Server administrators may want to impose restrictions on the minimum
+and maximum length and the allowed character set allowed for room ids. Otherwise
+users might create rooms which are difficult to handle.
+
+However, restricting that on the server only leads to bad UX as users might learn of
+the servers policy only after they have tried to create a room. Furthermore error
+messages from XMPP-servers might not be self-explanatory.
+
+Therefore this option allows converse to already check the policy and disallow the
+user from even trying to entering/creating such a room.
+
+As this only makes sense on your own server, the check is applied only if the domain
+part equals `muc_domain`_. If `muc_domain`_ is unset, then this check is disabled
+completely.
+
+Example:
+
+.. code-block:: javascript
+
+    muc_roomid_policy: /^[a-z0-9._-]{5,40}$/,
+
+See also: `muc_roomid_policy_hint`_
+
+muc_roomid_policy_hint
+----------------------
+
+* Default: ``null``
+
+This option can be used in conjuction with `muc_roomid_policy`_ in order to give
+a written explanation of the imposed room id policy. You can use the html-tags
+``<br>``, ``<b>``, and ``<em>`` to allow some basic styling.
+
+Example:
+
+.. code-block:: javascript
+
+    muc_roomid_policy_hint: '<br><b>Policy for groupchat id:</b><br>- between 5 and 40 characters,<br>- lowercase from a to z (no special characters) or<br>- digits or<br>- dots (.) or<br>- underlines (_) or<br>- hyphens (-),<br>- no spaces<br>',
+
 muc_show_join_leave
 -------------------
 

+ 3 - 0
locale/converse.pot

@@ -181,6 +181,9 @@ msgstr ""
 msgid "Groupchat address (JID)"
 msgstr ""
 
+msgid "Groupchat id is invalid."
+msgstr ""
+
 #: dist/converse-no-dependencies.js:8955
 msgid "Description"
 msgstr ""

+ 5 - 0
sass/_modal.scss

@@ -22,6 +22,11 @@
             .modal-footer {
                 justify-content: flex-start;
             }
+            .roomid-policy-error {
+                color: var(--error-color);
+                font-size: var(--font-size-small);
+                float: right;
+            }
         }
 
         .scrollable-container {

+ 27 - 2
src/converse-muc-views.js

@@ -110,6 +110,8 @@ converse.plugins.add('converse-muc-views', {
             'muc_mention_autocomplete_filter': 'contains',
             'muc_mention_autocomplete_show_avatar': true,
             'roomconfig_whitelist': [],
+            'muc_roomid_policy': null,
+            'muc_roomid_policy_hint': null,
             'visible_toolbar_buttons': {
                 'toggle_occupants': true
             }
@@ -519,12 +521,15 @@ converse.plugins.add('converse-muc-views', {
         _converse.AddChatRoomModal = _converse.BootstrapModal.extend({
 
             events: {
-                'submit form.add-chatroom': 'openChatRoom'
+                'submit form.add-chatroom': 'openChatRoom',
+                'keyup .roomjid-input': 'checkRoomidPolicy',
+                'change .roomjid-input': 'checkRoomidPolicy'
             },
 
             initialize () {
                 _converse.BootstrapModal.prototype.initialize.apply(this, arguments);
                 this.listenTo(this.model, 'change:muc_domain', this.render);
+                this.muc_roomid_policy_error_msg = null;
             },
 
             toHTML () {
@@ -537,7 +542,9 @@ converse.plugins.add('converse-muc-views', {
                     '__': _converse.__,
                     '_converse': _converse,
                     'label_room_address': _converse.muc_domain ? __('Groupchat name') :  __('Groupchat address'),
-                    'chatroom_placeholder': placeholder
+                    'chatroom_placeholder': placeholder,
+                    'muc_roomid_policy_error_msg': this.muc_roomid_policy_error_msg,
+                    'muc_roomid_policy_hint': xss.filterXSS(_converse.muc_roomid_policy_hint, {'whiteList': {b: [], br: [], em: []}})
                 }));
             },
 
@@ -582,6 +589,24 @@ converse.plugins.add('converse-muc-views', {
                 _converse.api.rooms.open(jid, Object.assign(data, {jid}));
                 this.modal.hide();
                 ev.target.reset();
+            },
+
+            checkRoomidPolicy () {
+                if (_converse.muc_roomid_policy && _converse.muc_domain) {
+                    let jid = this.el.querySelector('.roomjid-input').value;
+                    if (converse.locked_muc_domain || !u.isValidJID(jid)) {
+                        jid = `${Strophe.escapeNode(jid)}@${_converse.muc_domain}`;
+                    }
+                    const roomid = Strophe.getNodeFromJid(jid);
+                    const roomdomain = Strophe.getDomainFromJid(jid);
+                    if (_converse.muc_domain !== roomdomain ||
+                        _converse.muc_roomid_policy.test(roomid)) {
+                        this.muc_roomid_policy_error_msg = null;
+                    } else {
+                        this.muc_roomid_policy_error_msg = __('Groupchat id is invalid.');
+                    }
+                    this.render();
+                }
             }
         });
 

+ 10 - 2
src/templates/add_chatroom_modal.html

@@ -12,15 +12,23 @@
                 <form class="converse-form add-chatroom">
                     <div class="form-group">
                         <label for="chatroom">{{{o.label_room_address}}}:</label>
-                        <input type="text" required="required" name="chatroom" class="form-control" placeholder="{{{o.chatroom_placeholder}}}"/>
+                        {[ if (o.muc_roomid_policy_error_msg) { ]}
+                            <label class="roomid-policy-error">{{{o.muc_roomid_policy_error_msg}}}</label>
+                        {[ } ]}
+                        <input type="text" required="required" name="chatroom" class="form-control roomjid-input" placeholder="{{{o.chatroom_placeholder}}}"/>
                     </div>
+                    {[ if (o.muc_roomid_policy_hint) { ]}
+                        <div class="form-group">
+                            {{o.muc_roomid_policy_hint}}
+                        </div>
+                    {[ } ]}
                     {[ if (!o._converse.locked_muc_nickname) { ]}
                     <div class="form-group" >
                         <label for="nickname">{{{o.__('Nickname')}}}:</label>
                         <input type="text" pattern=".*\S+.*" title="{{{o.__('This field is required')}}}" required="required" name="nickname" value="{{{o.nick}}}" class="form-control"/>
                     </div>
                     {[ } ]}
-                    <input type="submit" class="btn btn-primary" name="join" value="{{{o.__('Join')}}}"/>
+                    <input type="submit" class="btn btn-primary" name="join" value="{{{o.__('Join')}}}" {[ if (o.muc_roomid_policy_error_msg) { ]} disabled=true {[ } ]}/>
                 </form>
             </div>
         </div>