mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-16 14:17:22 +01:00
Allow guilds edit (#8800)
* test: test that admin users can update guilds * test: test admin removeMember privileges * fix: allow admins to edit guilds * fix: add edit guild options for admins * test: test that admin can't remove current leader * Add error msg for removing current leader * Taskwoods Quest Line (#8156) * feat(content): Gold Quest 2016-10 * chore(news): Bailey * chore(i18n): update locales * chore(sprites): compile * 3.49.0 * chore: update express * Fix for the ReDOS vulnerability habitica is currently affected by the high-severity [ReDOS vulnerability](https://snyk.io/vuln/npm:tough-cookie:20160722). Vulnerable module: `tough-cookie` Introduced through: ` request` This PR fixes the ReDOS vulnerability by upgrading ` request` to version 2.74.0 Check out the [Snyk test report](https://snyk.io/test/github/HabitRPG/habitica) to review other vulnerabilities that affect this repo. [Watch the repo](https://snyk.io/add) to * get alerts if newly disclosed vulnerabilities affect this repo in the future. * generate pull requests with the fixes you want, or let us do the work: when a newly disclosed vulnerability affects you, we'll submit a fix to you right away. Stay secure, The Snyk team * Documentation - coupon closes #8109 * fix(client): Allow member hp to be clickable fixes #8016 closes #8155 * chore(npm): shrinkwrap * test: test isAbleToEditGroup * Add isAbleToEditGroup to groupsCtrl * Remove unnecessary ternary * Fix linting * Move edit permission logic out to groupsCtrl * fix: change ternary to boolean * Fix linting * Fixed merge issues
This commit is contained in:
@@ -397,7 +397,7 @@ api.getGroup = {
|
||||
* @apiUse groupIdRequired
|
||||
* @apiUse GroupNotFound
|
||||
*
|
||||
* @apiPermission GroupLeader
|
||||
* @apiPermission GroupLeader, Admin
|
||||
*/
|
||||
api.updateGroup = {
|
||||
method: 'PUT',
|
||||
@@ -410,11 +410,13 @@ api.updateGroup = {
|
||||
|
||||
let validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
let optionalMembership = Boolean(user.contributor.admin);
|
||||
let group = await Group.getGroup({user, groupId: req.params.groupId, optionalMembership});
|
||||
|
||||
let group = await Group.getGroup({user, groupId: req.params.groupId});
|
||||
if (!group) throw new NotFound(res.t('groupNotFound'));
|
||||
|
||||
if (group.leader !== user._id) throw new NotAuthorized(res.t('messageGroupOnlyLeaderCanUpdate'));
|
||||
if (group.leader !== user._id && group.type === 'party') throw new NotAuthorized(res.t('messageGroupOnlyLeaderCanUpdate'));
|
||||
else if (group.leader !== user._id && !user.contributor.admin) throw new NotAuthorized(res.t('messageGroupOnlyLeaderCanUpdate'));
|
||||
|
||||
if (req.body.leader !== user._id && group.hasNotCancelled()) throw new NotAuthorized(res.t('cannotChangeLeaderWithActiveGroupPlan'));
|
||||
|
||||
@@ -473,7 +475,7 @@ api.joinGroup = {
|
||||
let validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
|
||||
// Works even if the user is not yet a member of the group
|
||||
// Works even if the user is not yet a member of the group
|
||||
let group = await Group.getGroup({user, groupId: req.params.groupId, optionalMembership: true}); // Do not fetch chat and work even if the user is not yet a member of the group
|
||||
if (!group) throw new NotFound(res.t('groupNotFound'));
|
||||
|
||||
@@ -761,7 +763,7 @@ function _sendMessageToRemoved (group, removedUser, message, isInGroup) {
|
||||
*
|
||||
* @apiSuccess {Object} data An empty object
|
||||
*
|
||||
* @apiPermission GroupLeader
|
||||
* @apiPermission GroupLeader, Admin
|
||||
*
|
||||
* @apiUse groupIdRequired
|
||||
* @apiUse GroupNotFound
|
||||
@@ -778,13 +780,18 @@ api.removeGroupMember = {
|
||||
|
||||
let validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
let optionalMembership = Boolean(user.contributor.admin);
|
||||
let group = await Group.getGroup({user, groupId: req.params.groupId, optionalMembership, fields: '-chat'}); // Do not fetch chat
|
||||
|
||||
let group = await Group.getGroup({user, groupId: req.params.groupId, fields: '-chat'}); // Do not fetch chat
|
||||
if (!group) throw new NotFound(res.t('groupNotFound'));
|
||||
|
||||
let uuid = req.params.memberId;
|
||||
|
||||
if (group.leader !== user._id) throw new NotAuthorized(res.t('onlyLeaderCanRemoveMember'));
|
||||
if (group.leader !== user._id && group.type === 'party') throw new NotAuthorized(res.t('onlyLeaderCanRemoveMember'));
|
||||
if (group.leader !== user._id && !user.contributor.admin) throw new NotAuthorized(res.t('onlyLeaderCanRemoveMember'));
|
||||
|
||||
if (group.leader === uuid && user.contributor.admin) throw new NotAuthorized(res.t('cannotRemoveCurrentLeader'));
|
||||
|
||||
if (user._id === uuid) throw new NotAuthorized(res.t('memberCannotRemoveYourself'));
|
||||
|
||||
let member = await User.findOne({_id: uuid}).exec();
|
||||
@@ -947,12 +954,12 @@ async function _inviteByEmail (invite, group, inviter, req, res) {
|
||||
if (!invite.email) throw new BadRequest(res.t('inviteMissingEmail'));
|
||||
|
||||
let userToContact = await User.findOne({$or: [
|
||||
{'auth.local.email': invite.email},
|
||||
{'auth.facebook.emails.value': invite.email},
|
||||
{'auth.google.emails.value': invite.email},
|
||||
{'auth.local.email': invite.email},
|
||||
{'auth.facebook.emails.value': invite.email},
|
||||
{'auth.google.emails.value': invite.email},
|
||||
]})
|
||||
.select({_id: true, 'preferences.emailNotifications': true})
|
||||
.exec();
|
||||
.select({_id: true, 'preferences.emailNotifications': true})
|
||||
.exec();
|
||||
|
||||
if (userToContact) {
|
||||
userReturnInfo = await _inviteByUUID(userToContact._id, group, inviter, req, res);
|
||||
|
||||
Reference in New Issue
Block a user