diff --git a/public/language/en-GB/admin/manage/groups.json b/public/language/en-GB/admin/manage/groups.json index 814eebaa0f..c3d60d4eed 100644 --- a/public/language/en-GB/admin/manage/groups.json +++ b/public/language/en-GB/admin/manage/groups.json @@ -25,7 +25,8 @@ "edit.show-badge": "Show Badge", "edit.private-details": "If enabled, joining of groups requires approval from a group owner.", "edit.private-override": "Warning: Private groups is disabled at system level, which overrides this option.", - "edit.disable-requests": "Disable join requests", + "edit.disable-join": "Disable join requests", + "edit.disable-leave": "Disallow users from leaving the group", "edit.hidden": "Hidden", "edit.hidden-details": "If enabled, this group will not be found in the groups listing, and users will have to be invited manually", "edit.add-user": "Add User to Group", diff --git a/public/language/en-GB/error.json b/public/language/en-GB/error.json index fb2951e188..9fed1f178f 100644 --- a/public/language/en-GB/error.json +++ b/public/language/en-GB/error.json @@ -117,6 +117,8 @@ "group-needs-owner": "This group requires at least one owner", "group-already-invited": "This user has already been invited", "group-already-requested": "Your membership request has already been submitted", + "group-join-disabled": "You are not able to join this group at this time", + "group-leave-disabled": "You are not able to leave this group at this time", "post-already-deleted": "This post has already been deleted", "post-already-restored": "This post has already been restored", diff --git a/public/language/en-GB/groups.json b/public/language/en-GB/groups.json index 9a37255a6b..abb34947cc 100644 --- a/public/language/en-GB/groups.json +++ b/public/language/en-GB/groups.json @@ -30,6 +30,7 @@ "details.latest_posts": "Latest Posts", "details.private": "Private", "details.disableJoinRequests": "Disable join requests", + "details.disableLeave": "Disallow users from leaving the group", "details.grant": "Grant/Rescind Ownership", "details.kick": "Kick", "details.kick_confirm": "Are you sure you want to remove this member from the group?", diff --git a/public/src/modules/helpers.js b/public/src/modules/helpers.js index 286327e10d..68584cc51a 100644 --- a/public/src/modules/helpers.js +++ b/public/src/modules/helpers.js @@ -160,7 +160,7 @@ // Groups helpers function membershipBtn(groupObj) { if (groupObj.isMember && groupObj.name !== 'administrators') { - return ''; + return ''; } if (groupObj.isPending && groupObj.name !== 'administrators') { diff --git a/src/groups/create.js b/src/groups/create.js index 8b8625cf9b..eb90b52ba2 100644 --- a/src/groups/create.js +++ b/src/groups/create.js @@ -13,6 +13,7 @@ module.exports = function (Groups) { if (data.name === 'administrators') { disableJoinRequests = 1; } + const disableLeave = parseInt(data.disableLeave, 10) === 1 ? 1 : 0; const isHidden = parseInt(data.hidden, 10) === 1; validateGroupName(data.name); @@ -36,6 +37,7 @@ module.exports = function (Groups) { system: isSystem ? 1 : 0, private: isPrivate, disableJoinRequests: disableJoinRequests, + disableLeave: disableLeave, }; plugins.fireHook('filter:group.create', { group: groupData, data: data }); diff --git a/src/groups/data.js b/src/groups/data.js index c50d3b263b..f00db8e04b 100644 --- a/src/groups/data.js +++ b/src/groups/data.js @@ -9,7 +9,7 @@ const utils = require('../utils'); const intFields = [ 'createtime', 'memberCount', 'hidden', 'system', 'private', - 'userTitleEnabled', 'disableJoinRequests', + 'userTitleEnabled', 'disableJoinRequests', 'disableLeave', ]; module.exports = function (Groups) { diff --git a/src/groups/update.js b/src/groups/update.js index 81c26c3171..2853ba705c 100644 --- a/src/groups/update.js +++ b/src/groups/update.js @@ -49,6 +49,10 @@ module.exports = function (Groups) { payload.disableJoinRequests = values.disableJoinRequests ? '1' : '0'; } + if (values.hasOwnProperty('disableLeave')) { + payload.disableLeave = values.disableLeave ? '1' : '0'; + } + await checkNameChange(groupName, values.name); if (values.hasOwnProperty('private')) { await updatePrivacy(groupName, values.private); diff --git a/src/socket.io/groups.js b/src/socket.io/groups.js index 71338f9117..b533f8ecba 100644 --- a/src/socket.io/groups.js +++ b/src/socket.io/groups.js @@ -43,7 +43,7 @@ SocketGroups.join = async (socket, data) => { }); if (results.groupData.private && results.groupData.disableJoinRequests) { - throw new Error('[[error:join-requests-disabled]]'); + throw new Error('[[error:group-join-disabled]]'); } if (!results.groupData.private || results.isAdmin) { @@ -68,6 +68,11 @@ SocketGroups.leave = async (socket, data) => { throw new Error('[[error:cant-remove-self-as-admin]]'); } + const groupData = await groups.getGroupData(data.groupName); + if (groupData.disableLeave) { + throw new Error('[[error:group-leave-disabled]]'); + } + await groups.leave(data.groupName, socket.uid); logGroupEvent(socket, 'group-leave', { groupName: data.groupName, diff --git a/src/views/admin/manage/group.tpl b/src/views/admin/manage/group.tpl index 273acde7d3..2e308358a3 100644 --- a/src/views/admin/manage/group.tpl +++ b/src/views/admin/manage/group.tpl @@ -69,7 +69,16 @@