Commit e2d744dd authored by Christoph Scholz's avatar Christoph Scholz Committed by JC Brand

config option for roomid validation

parent 496e5ba4
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
- #1793: Send button doesn't appear in Firefox in 1:1 chats - #1793: Send button doesn't appear in Firefox in 1:1 chats
- #1822: Don't log error if user has no bookmarks - #1822: Don't log error if user has no bookmarks
- #1820: Set focus on jid field after controlbox is loaded - #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) ## 6.0.0 (2020-01-09)
......
...@@ -1150,6 +1150,50 @@ all MUCs with set autojoin flag in their respective bookmarks will be joined on ...@@ -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 startup of Converse. When set to ``false`` no MUCs are automatically joined based on
their bookmarks. 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 muc_show_join_leave
------------------- -------------------
......
...@@ -181,6 +181,9 @@ msgstr "" ...@@ -181,6 +181,9 @@ msgstr ""
msgid "Groupchat address (JID)" msgid "Groupchat address (JID)"
msgstr "" msgstr ""
msgid "Groupchat id is invalid."
msgstr ""
#: dist/converse-no-dependencies.js:8955 #: dist/converse-no-dependencies.js:8955
msgid "Description" msgid "Description"
msgstr "" msgstr ""
......
...@@ -22,6 +22,11 @@ ...@@ -22,6 +22,11 @@
.modal-footer { .modal-footer {
justify-content: flex-start; justify-content: flex-start;
} }
.roomid-policy-error {
color: var(--error-color);
font-size: var(--font-size-small);
float: right;
}
} }
.scrollable-container { .scrollable-container {
......
...@@ -110,6 +110,8 @@ converse.plugins.add('converse-muc-views', { ...@@ -110,6 +110,8 @@ converse.plugins.add('converse-muc-views', {
'muc_mention_autocomplete_filter': 'contains', 'muc_mention_autocomplete_filter': 'contains',
'muc_mention_autocomplete_show_avatar': true, 'muc_mention_autocomplete_show_avatar': true,
'roomconfig_whitelist': [], 'roomconfig_whitelist': [],
'muc_roomid_policy': null,
'muc_roomid_policy_hint': null,
'visible_toolbar_buttons': { 'visible_toolbar_buttons': {
'toggle_occupants': true 'toggle_occupants': true
} }
...@@ -519,12 +521,15 @@ converse.plugins.add('converse-muc-views', { ...@@ -519,12 +521,15 @@ converse.plugins.add('converse-muc-views', {
_converse.AddChatRoomModal = _converse.BootstrapModal.extend({ _converse.AddChatRoomModal = _converse.BootstrapModal.extend({
events: { events: {
'submit form.add-chatroom': 'openChatRoom' 'submit form.add-chatroom': 'openChatRoom',
'keyup .roomjid-input': 'checkRoomidPolicy',
'change .roomjid-input': 'checkRoomidPolicy'
}, },
initialize () { initialize () {
_converse.BootstrapModal.prototype.initialize.apply(this, arguments); _converse.BootstrapModal.prototype.initialize.apply(this, arguments);
this.listenTo(this.model, 'change:muc_domain', this.render); this.listenTo(this.model, 'change:muc_domain', this.render);
this.muc_roomid_policy_error_msg = null;
}, },
toHTML () { toHTML () {
...@@ -537,7 +542,9 @@ converse.plugins.add('converse-muc-views', { ...@@ -537,7 +542,9 @@ converse.plugins.add('converse-muc-views', {
'__': _converse.__, '__': _converse.__,
'_converse': _converse, '_converse': _converse,
'label_room_address': _converse.muc_domain ? __('Groupchat name') : __('Groupchat address'), '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', { ...@@ -582,6 +589,24 @@ converse.plugins.add('converse-muc-views', {
_converse.api.rooms.open(jid, Object.assign(data, {jid})); _converse.api.rooms.open(jid, Object.assign(data, {jid}));
this.modal.hide(); this.modal.hide();
ev.target.reset(); 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();
}
} }
}); });
......
...@@ -12,15 +12,23 @@ ...@@ -12,15 +12,23 @@
<form class="converse-form add-chatroom"> <form class="converse-form add-chatroom">
<div class="form-group"> <div class="form-group">
<label for="chatroom">{{{o.label_room_address}}}:</label> <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> </div>
{[ if (o.muc_roomid_policy_hint) { ]}
<div class="form-group">
{{o.muc_roomid_policy_hint}}
</div>
{[ } ]}
{[ if (!o._converse.locked_muc_nickname) { ]} {[ if (!o._converse.locked_muc_nickname) { ]}
<div class="form-group" > <div class="form-group" >
<label for="nickname">{{{o.__('Nickname')}}}:</label> <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"/> <input type="text" pattern=".*\S+.*" title="{{{o.__('This field is required')}}}" required="required" name="nickname" value="{{{o.nick}}}" class="form-control"/>
</div> </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> </form>
</div> </div>
</div> </div>
......
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