mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 22:57:21 +01:00
add population to challenge.group, challenge.leader and group.leader
This commit is contained in:
@@ -27,22 +27,38 @@ describe('GET challenges/group/:groupId', () => {
|
||||
challenge2 = await generateChallenge(user, group);
|
||||
});
|
||||
|
||||
it('should return group challenges for non member', async () => {
|
||||
it('should return group challenges for non member with populated leader', async () => {
|
||||
let challenges = await nonMember.get(`/challenges/groups/${publicGuild._id}`);
|
||||
|
||||
let foundChallenge1 = _.find(challenges, { _id: challenge._id });
|
||||
expect(foundChallenge1).to.exist;
|
||||
expect(foundChallenge1.leader).to.eql({
|
||||
_id: publicGuild.leader._id,
|
||||
profile: {name: user.profile.name},
|
||||
});
|
||||
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
||||
expect(foundChallenge2).to.exist;
|
||||
expect(foundChallenge2.leader).to.eql({
|
||||
_id: publicGuild.leader._id,
|
||||
profile: {name: user.profile.name},
|
||||
});
|
||||
});
|
||||
|
||||
it('should return group challenges for member', async () => {
|
||||
it('should return group challenges for member with populated leader', async () => {
|
||||
let challenges = await user.get(`/challenges/groups/${publicGuild._id}`);
|
||||
|
||||
let foundChallenge1 = _.find(challenges, { _id: challenge._id });
|
||||
expect(foundChallenge1).to.exist;
|
||||
expect(foundChallenge1.leader).to.eql({
|
||||
_id: publicGuild.leader._id,
|
||||
profile: {name: user.profile.name},
|
||||
});
|
||||
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
||||
expect(foundChallenge2).to.exist;
|
||||
expect(foundChallenge2.leader).to.eql({
|
||||
_id: publicGuild.leader._id,
|
||||
profile: {name: user.profile.name},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -76,13 +92,21 @@ describe('GET challenges/group/:groupId', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should return group challenges for member', async () => {
|
||||
it('should return group challenges for member with populated leader', async () => {
|
||||
let challenges = await user.get(`/challenges/groups/${privateGuild._id}`);
|
||||
|
||||
let foundChallenge1 = _.find(challenges, { _id: challenge._id });
|
||||
expect(foundChallenge1).to.exist;
|
||||
expect(foundChallenge1.leader).to.eql({
|
||||
_id: privateGuild.leader._id,
|
||||
profile: {name: user.profile.name},
|
||||
});
|
||||
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
||||
expect(foundChallenge2).to.exist;
|
||||
expect(foundChallenge2.leader).to.eql({
|
||||
_id: privateGuild.leader._id,
|
||||
profile: {name: user.profile.name},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
} from '../../../../helpers/api-v3-integration.helper';
|
||||
|
||||
describe('GET challenges/user', () => {
|
||||
let user, member, nonMember, challenge, challenge2;
|
||||
let user, member, nonMember, challenge, challenge2, publicGuild;
|
||||
|
||||
before(async () => {
|
||||
let { group, groupLeader, members } = await createAndPopulateGroup({
|
||||
@@ -18,7 +18,7 @@ describe('GET challenges/user', () => {
|
||||
});
|
||||
|
||||
user = groupLeader;
|
||||
|
||||
publicGuild = group;
|
||||
member = members[0];
|
||||
nonMember = await generateUser();
|
||||
|
||||
@@ -33,6 +33,16 @@ describe('GET challenges/user', () => {
|
||||
|
||||
let foundChallenge = _.find(challenges, { _id: challenge._id });
|
||||
expect(foundChallenge).to.exist;
|
||||
expect(foundChallenge.leader).to.eql({
|
||||
_id: publicGuild.leader._id,
|
||||
profile: {name: user.profile.name},
|
||||
});
|
||||
expect(foundChallenge.group).to.eql({
|
||||
_id: publicGuild._id,
|
||||
type: publicGuild.type,
|
||||
privacy: publicGuild.privacy,
|
||||
name: publicGuild.name,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return challenges user has created', async () => {
|
||||
@@ -40,8 +50,28 @@ describe('GET challenges/user', () => {
|
||||
|
||||
let foundChallenge1 = _.find(challenges, { _id: challenge._id });
|
||||
expect(foundChallenge1).to.exist;
|
||||
expect(foundChallenge1.leader).to.eql({
|
||||
_id: publicGuild.leader._id,
|
||||
profile: {name: user.profile.name},
|
||||
});
|
||||
expect(foundChallenge1.group).to.eql({
|
||||
_id: publicGuild._id,
|
||||
type: publicGuild.type,
|
||||
privacy: publicGuild.privacy,
|
||||
name: publicGuild.name,
|
||||
});
|
||||
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
||||
expect(foundChallenge2).to.exist;
|
||||
expect(foundChallenge2.leader).to.eql({
|
||||
_id: publicGuild.leader._id,
|
||||
profile: {name: user.profile.name},
|
||||
});
|
||||
expect(foundChallenge2.group).to.eql({
|
||||
_id: publicGuild._id,
|
||||
type: publicGuild.type,
|
||||
privacy: publicGuild.privacy,
|
||||
name: publicGuild.name,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return challenges in user\'s group', async () => {
|
||||
@@ -49,8 +79,28 @@ describe('GET challenges/user', () => {
|
||||
|
||||
let foundChallenge1 = _.find(challenges, { _id: challenge._id });
|
||||
expect(foundChallenge1).to.exist;
|
||||
expect(foundChallenge1.leader).to.eql({
|
||||
_id: publicGuild.leader._id,
|
||||
profile: {name: user.profile.name},
|
||||
});
|
||||
expect(foundChallenge1.group).to.eql({
|
||||
_id: publicGuild._id,
|
||||
type: publicGuild.type,
|
||||
privacy: publicGuild.privacy,
|
||||
name: publicGuild.name,
|
||||
});
|
||||
let foundChallenge2 = _.find(challenges, { _id: challenge2._id });
|
||||
expect(foundChallenge2).to.exist;
|
||||
expect(foundChallenge2.leader).to.eql({
|
||||
_id: publicGuild.leader._id,
|
||||
profile: {name: user.profile.name},
|
||||
});
|
||||
expect(foundChallenge2.group).to.eql({
|
||||
_id: publicGuild._id,
|
||||
type: publicGuild.type,
|
||||
privacy: publicGuild.privacy,
|
||||
name: publicGuild.name,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not return challenges user doesn\'t have access to', async () => {
|
||||
|
||||
@@ -50,7 +50,7 @@ describe('PUT /challenges/:challengeId', () => {
|
||||
let res = await user.put(`/challenges/${challenge._id}`, {
|
||||
// ignored
|
||||
prize: 33,
|
||||
groupId: 'blabla',
|
||||
group: 'blabla',
|
||||
memberCount: 33,
|
||||
tasksOrder: 'new order',
|
||||
official: true,
|
||||
@@ -63,7 +63,7 @@ describe('PUT /challenges/:challengeId', () => {
|
||||
});
|
||||
|
||||
expect(res.prize).to.equal(0);
|
||||
expect(res.groupId).to.equal(privateGuild._id);
|
||||
expect(res.group).to.equal(privateGuild._id);
|
||||
expect(res.memberCount).to.equal(2);
|
||||
expect(res.tasksOrder).not.to.equal('new order');
|
||||
expect(res.official).to.equal(false);
|
||||
|
||||
@@ -43,10 +43,6 @@ describe('GET /groups/:id', () => {
|
||||
|
||||
expect(group.leader._id).to.eql(leader._id);
|
||||
expect(group.leader.profile.name).to.eql(leader.profile.name);
|
||||
expect(group.leader.items).to.exist;
|
||||
expect(group.leader.stats).to.exist;
|
||||
expect(group.leader.achievements).to.exist;
|
||||
expect(group.leader.contributor).to.exist;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32,12 +32,17 @@ describe('POST /group', () => {
|
||||
});
|
||||
|
||||
it('sets the group leader to the user who created the group', async () => {
|
||||
await expect(
|
||||
user.post('/groups', {
|
||||
let group = await user.post('/groups', {
|
||||
name: 'Test Public Guild',
|
||||
type: 'guild',
|
||||
})
|
||||
).to.eventually.have.property('leader', user._id);
|
||||
});
|
||||
|
||||
expect(group.leader).to.eql({
|
||||
_id: user._id,
|
||||
profile: {
|
||||
name: user.profile.name,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -86,6 +91,12 @@ describe('POST /group', () => {
|
||||
expect(publicGuild.type).to.equal(groupType);
|
||||
expect(publicGuild.memberCount).to.equal(1);
|
||||
expect(publicGuild.privacy).to.equal(groupPrivacy);
|
||||
expect(publicGuild.leader).to.eql({
|
||||
_id: user._id,
|
||||
profile: {
|
||||
name: user.profile.name,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -106,6 +117,12 @@ describe('POST /group', () => {
|
||||
expect(privateGuild.type).to.equal(groupType);
|
||||
expect(privateGuild.memberCount).to.equal(1);
|
||||
expect(privateGuild.privacy).to.equal(groupPrivacy);
|
||||
expect(privateGuild.leader).to.eql({
|
||||
_id: user._id,
|
||||
profile: {
|
||||
name: user.profile.name,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('deducts gems from user and adds them to guild bank', async () => {
|
||||
@@ -138,6 +155,12 @@ describe('POST /group', () => {
|
||||
expect(party.name).to.equal(partyName);
|
||||
expect(party.type).to.equal(partyType);
|
||||
expect(party.memberCount).to.equal(1);
|
||||
expect(party.leader).to.eql({
|
||||
_id: user._id,
|
||||
profile: {
|
||||
name: user.profile.name,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('does not require gems to create a party', async () => {
|
||||
|
||||
@@ -113,7 +113,7 @@ export async function createAndPopulateGroup (settings = {}) {
|
||||
// optional details argument for the initial challenge creation and an
|
||||
// optional update argument which will update the challenge via the db
|
||||
export async function generateChallenge (challengeCreator, group, details = {}, update = {}) {
|
||||
details.groupId = group._id;
|
||||
details.group = group._id;
|
||||
details.name = details.name || 'a challenge';
|
||||
details.shortName = details.shortName || 'aChallenge';
|
||||
details.prize = details.prize || 0;
|
||||
|
||||
@@ -2,7 +2,10 @@ import { authWithHeaders } from '../../middlewares/api-v3/auth';
|
||||
import _ from 'lodash';
|
||||
import cron from '../../middlewares/api-v3/cron';
|
||||
import { model as Challenge } from '../../models/challenge';
|
||||
import { model as Group } from '../../models/group';
|
||||
import {
|
||||
model as Group,
|
||||
basicFields as basicGroupFields,
|
||||
} from '../../models/group';
|
||||
import {
|
||||
model as User,
|
||||
nameFields,
|
||||
@@ -35,12 +38,12 @@ api.createChallenge = {
|
||||
async handler (req, res) {
|
||||
let user = res.locals.user;
|
||||
|
||||
req.checkBody('groupId', res.t('groupIdRequired')).notEmpty();
|
||||
req.checkBody('group', res.t('groupIdRequired')).notEmpty();
|
||||
|
||||
let validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
|
||||
let groupId = req.body.groupId;
|
||||
let groupId = req.body.group;
|
||||
let prize = req.body.prize;
|
||||
|
||||
let group = await Group.getGroup({user, groupId, fields: '-chat', mustBeMember: true});
|
||||
@@ -92,6 +95,17 @@ api.createChallenge = {
|
||||
}), group.save()]);
|
||||
|
||||
let savedChal = results[0];
|
||||
// TODO Instead of populate we make a find call manually because of https://github.com/Automattic/mongoose/issues/3833
|
||||
// await Q.ninvoke(savedChal, 'populate', ['leader', nameFields]); // doc.populate doesn't return a promise
|
||||
let response = savedChal.toJSON();
|
||||
response.leader = (await User.findById(response.leader).select(nameFields).exec()).toJSON({minimize: true});
|
||||
response.group = {
|
||||
_id: group._id,
|
||||
name: group.name,
|
||||
type: group.type,
|
||||
privacy: group.privacy,
|
||||
};
|
||||
|
||||
await savedChal.syncToUser(user); // (it also saves the user)
|
||||
res.respond(201, savedChal);
|
||||
},
|
||||
@@ -122,7 +136,7 @@ api.joinChallenge = {
|
||||
if (!challenge) throw new NotFound(res.t('challengeNotFound'));
|
||||
if (challenge.isMember(user)) throw new NotAuthorized(res.t('userAlreadyInChallenge'));
|
||||
|
||||
let group = await Group.getGroup({user, groupId: challenge.groupId, fields: '_id type privacy', optionalMembership: true});
|
||||
let group = await Group.getGroup({user, groupId: challenge.group, fields: '_id type privacy', optionalMembership: true});
|
||||
if (!group || !challenge.hasAccess(user, group)) throw new NotFound(res.t('challengeNotFound'));
|
||||
|
||||
challenge.memberCount += 1;
|
||||
@@ -158,7 +172,7 @@ api.leaveChallenge = {
|
||||
let challenge = await Challenge.findOne({ _id: req.params.challengeId });
|
||||
if (!challenge) throw new NotFound(res.t('challengeNotFound'));
|
||||
|
||||
let group = await Group.getGroup({user, groupId: challenge.groupId, fields: '_id type privacy'});
|
||||
let group = await Group.getGroup({user, groupId: challenge.group, fields: '_id type privacy'});
|
||||
if (!group || !challenge.canView(user, group)) throw new NotFound(res.t('challengeNotFound'));
|
||||
|
||||
if (!challenge.isMember(user)) throw new NotAuthorized(res.t('challengeMemberNotFound'));
|
||||
@@ -186,25 +200,32 @@ api.getUserChallenges = {
|
||||
async handler (req, res) {
|
||||
let user = res.locals.user;
|
||||
|
||||
let groups = user.guilds.slice(0); // slice is used to clone the array so we don't modify it directly
|
||||
if (user.party._id) groups.push(user.party._id);
|
||||
groups.push('habitrpg'); // tavern challenges
|
||||
|
||||
let challenges = await Challenge.find({
|
||||
$or: [
|
||||
{_id: {$in: user.challenges}}, // Challenges where the user is participating
|
||||
{groupId: {$in: groups}}, // Challenges in groups where I'm a member
|
||||
{group: {$in: user.getGroups()}}, // Challenges in groups where I'm a member
|
||||
{leader: user._id}, // Challenges where I'm the leader
|
||||
],
|
||||
_id: {$ne: '95533e05-1ff9-4e46-970b-d77219f199e9'}, // remove the Spread the Word Challenge for now, will revisit when we fix the closing-challenge bug TODO revisit
|
||||
})
|
||||
.sort('-official -timestamp')
|
||||
// TODO populate
|
||||
// .populate('group', '_id name type')
|
||||
// .populate('leader', 'profile.name')
|
||||
// .populate('group', basicGroupFields)
|
||||
// .populate('leader', nameFields)
|
||||
.exec();
|
||||
|
||||
res.respond(200, challenges);
|
||||
let resChals = challenges.map(challenge => challenge.toJSON());
|
||||
// TODO Instead of populate we make a find call manually because of https://github.com/Automattic/mongoose/issues/3833
|
||||
await Q.all(resChals.map((chal, index) => {
|
||||
return Q.all([
|
||||
User.findById(chal.leader).select(nameFields).exec(),
|
||||
Group.findById(chal.group).select(basicGroupFields).exec(),
|
||||
]).then(populatedData => {
|
||||
resChals[index].leader = populatedData[0].toJSON({minimize: true});
|
||||
resChals[index].group = populatedData[1].toJSON({minimize: true});
|
||||
});
|
||||
}));
|
||||
|
||||
res.respond(200, resChals);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -234,14 +255,20 @@ api.getGroupChallenges = {
|
||||
let group = await Group.getGroup({user, groupId});
|
||||
if (!group) throw new NotFound(res.t('groupNotFound'));
|
||||
|
||||
let challenges = await Challenge.find({groupId})
|
||||
let challenges = await Challenge.find({group: groupId})
|
||||
.sort('-official -timestamp')
|
||||
// TODO populate
|
||||
// .populate('group', '_id name type')
|
||||
// .populate('leader', 'profile.name')
|
||||
// .populate('leader', nameFields) // Only populate the leader as the group is implicit
|
||||
.exec();
|
||||
|
||||
res.respond(200, challenges);
|
||||
let resChals = challenges.map(challenge => challenge.toJSON());
|
||||
// TODO Instead of populate we make a find call manually because of https://github.com/Automattic/mongoose/issues/3833
|
||||
await Q.all(resChals.map((chal, index) => {
|
||||
return User.findById(chal.leader).select(nameFields).exec().then(populatedLeader => {
|
||||
resChals[index].leader = populatedLeader.toJSON({minimize: true});
|
||||
});
|
||||
}));
|
||||
|
||||
res.respond(200, resChals);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -268,13 +295,21 @@ api.getChallenge = {
|
||||
let user = res.locals.user;
|
||||
let challengeId = req.params.challengeId;
|
||||
|
||||
let challenge = await Challenge.findById(challengeId).exec();
|
||||
let challenge = await Challenge.findById(challengeId)
|
||||
// .populate('leader', nameFields) // don't populate the group as we'll fetch it manually later
|
||||
.exec();
|
||||
if (!challenge) throw new NotFound(res.t('challengeNotFound'));
|
||||
|
||||
let group = await Group.getGroup({user, groupId: challenge.groupId, fields: '_id type privacy', optionalMembership: true});
|
||||
// Fetching basicGroupFields
|
||||
let group = await Group.getGroup({user, groupId: challenge.group, fields: basicGroupFields, optionalMembership: true});
|
||||
if (!group || !challenge.canView(user, group)) throw new NotFound(res.t('challengeNotFound'));
|
||||
|
||||
res.respond(200, challenge);
|
||||
let chalRes = challenge.toJSON();
|
||||
chalRes.group = group.toJSON({minimize: true});
|
||||
// TODO Instead of populate we make a find call manually because of https://github.com/Automattic/mongoose/issues/3833
|
||||
chalRes.leader = (await User.findById(chalRes.leader).select(nameFields).exec()).toJSON({minimize: true});
|
||||
|
||||
res.respond(200, chalRes);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -301,9 +336,9 @@ api.exportChallengeCsv = {
|
||||
let user = res.locals.user;
|
||||
let challengeId = req.params.challengeId;
|
||||
|
||||
let challenge = await Challenge.findById(challengeId).select('_id groupId leader tasksOrder').exec();
|
||||
let challenge = await Challenge.findById(challengeId).select('_id group leader tasksOrder').exec();
|
||||
if (!challenge) throw new NotFound(res.t('challengeNotFound'));
|
||||
let group = await Group.getGroup({user, groupId: challenge.groupId, fields: '_id type privacy', optionalMembership: true});
|
||||
let group = await Group.getGroup({user, groupId: challenge.group, fields: '_id type privacy', optionalMembership: true});
|
||||
if (!group || !challenge.canView(user, group)) throw new NotFound(res.t('challengeNotFound'));
|
||||
|
||||
// In v2 this used the aggregation framework to run some computation on MongoDB but then iterated through all
|
||||
@@ -377,7 +412,7 @@ api.updateChallenge = {
|
||||
let challenge = await Challenge.findById(challengeId).exec();
|
||||
if (!challenge) throw new NotFound(res.t('challengeNotFound'));
|
||||
|
||||
let group = await Group.getGroup({user, groupId: challenge.groupId, fields: '_id name type privacy', optionalMembership: true});
|
||||
let group = await Group.getGroup({user, groupId: challenge.group, fields: '_id name type privacy', optionalMembership: true});
|
||||
if (!group || !challenge.canView(user, group)) throw new NotFound(res.t('challengeNotFound'));
|
||||
if (!challenge.canModify(user)) throw new NotAuthorized(res.t('onlyLeaderUpdateChal'));
|
||||
|
||||
@@ -398,12 +433,12 @@ async function _closeChal (challenge, broken = {}) {
|
||||
await Challenge.remove({_id: challenge._id}).exec();
|
||||
|
||||
// Refund the leader if the challenge is closed and the group not the tavern
|
||||
if (challenge.groupId !== 'habitrpg' && brokenReason === 'CHALLENGE_DELETED') {
|
||||
if (challenge.group !== 'habitrpg' && brokenReason === 'CHALLENGE_DELETED') {
|
||||
await User.update({_id: challenge.leader}, {$inc: {balance: challenge.prize / 4}}).exec();
|
||||
}
|
||||
|
||||
// Update the challengeCount on the group
|
||||
await Group.update({_id: challenge.groupId}, {$inc: {challengeCount: -1}}).exec();
|
||||
await Group.update({_id: challenge.group}, {$inc: {challengeCount: -1}}).exec();
|
||||
|
||||
// Award prize to winner and notify
|
||||
if (winner) {
|
||||
|
||||
@@ -5,8 +5,12 @@ import cron from '../../middlewares/api-v3/cron';
|
||||
import {
|
||||
INVITES_LIMIT,
|
||||
model as Group,
|
||||
basicFields as basicGroupFields,
|
||||
} from '../../models/group';
|
||||
import { model as User } from '../../models/user';
|
||||
import {
|
||||
model as User,
|
||||
nameFields,
|
||||
} from '../../models/user';
|
||||
import { model as EmailUnsubscription } from '../../models/emailUnsubscription';
|
||||
import {
|
||||
NotFound,
|
||||
@@ -55,11 +59,14 @@ api.createGroup = {
|
||||
|
||||
let results = await Q.all([user.save(), group.save()]);
|
||||
let savedGroup = results[1];
|
||||
// TODO Instead of populate we make a find call manually because of https://github.com/Automattic/mongoose/issues/3833
|
||||
// await Q.ninvoke(savedGroup, 'populate', ['leader', nameFields]); // doc.populate doesn't return a promise
|
||||
let response = savedGroup.toJSON();
|
||||
response.leader = (await User.findById(response.leader).select(nameFields).exec()).toJSON({minimize: true});
|
||||
|
||||
res.respond(201, response);
|
||||
firebase.updateGroupData(savedGroup);
|
||||
firebase.addUserToGroup(savedGroup._id, user._id);
|
||||
|
||||
return res.respond(201, savedGroup); // TODO populate
|
||||
},
|
||||
};
|
||||
|
||||
@@ -87,7 +94,7 @@ api.getGroups = {
|
||||
|
||||
// TODO validate types are acceptable? probably not necessary
|
||||
let types = req.query.type.split(',');
|
||||
let groupFields = 'name description memberCount balance';
|
||||
let groupFields = basicGroupFields.concat('description memberCount balance');
|
||||
let sort = '-memberCount';
|
||||
let queries = [];
|
||||
|
||||
@@ -152,7 +159,7 @@ api.getGroup = {
|
||||
let validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
|
||||
let group = await Group.getGroup({user, groupId: req.params.groupId, populateLeader: true});
|
||||
let group = await Group.getGroup({user, groupId: req.params.groupId, populateLeader: false});
|
||||
if (!group) throw new NotFound(res.t('groupNotFound'));
|
||||
|
||||
if (!user.contributor.admin) {
|
||||
@@ -163,6 +170,8 @@ api.getGroup = {
|
||||
});
|
||||
}
|
||||
|
||||
// TODO Instead of populate we make a find call manually because of https://github.com/Automattic/mongoose/issues/3833
|
||||
group.leader = (await User.findById(group.leader).select(nameFields).exec()).toJSON({minimize: true});
|
||||
res.respond(200, group);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -74,12 +74,12 @@ function _getMembersForItem (type) {
|
||||
let group;
|
||||
|
||||
if (type === 'challenge-members') {
|
||||
challenge = await Challenge.findById(challengeId).select('_id type leader groupId').exec();
|
||||
challenge = await Challenge.findById(challengeId).select('_id type leader group').exec();
|
||||
if (!challenge) throw new NotFound(res.t('challengeNotFound'));
|
||||
|
||||
// optionalMembership is set to true because even if you're not member of the group you may be able to access the challenge
|
||||
// for example if you've been booted from it, are the leader or a site admin
|
||||
group = await Group.getGroup({user, groupId: challenge.groupId, fields: '_id type privacy', optionalMembership: true});
|
||||
group = await Group.getGroup({user, groupId: challenge.group, fields: '_id type privacy', optionalMembership: true});
|
||||
if (!group || !challenge.canView(user, group)) throw new NotFound(res.t('challengeNotFound'));
|
||||
} else {
|
||||
group = await Group.getGroup({user, groupId, fields: '_id type'});
|
||||
@@ -212,7 +212,7 @@ api.getChallengeMemberProgress = {
|
||||
|
||||
// optionalMembership is set to true because even if you're not member of the group you may be able to access the challenge
|
||||
// for example if you've been booted from it, are the leader or a site admin
|
||||
let group = await Group.getGroup({user, groupId: challenge.groupId, fields: '_id type privacy', optionalMembership: true});
|
||||
let group = await Group.getGroup({user, groupId: challenge.group, fields: '_id type privacy', optionalMembership: true});
|
||||
if (!group || !challenge.canView(user, group)) throw new NotFound(res.t('challengeNotFound'));
|
||||
if (!challenge.isMember(member)) throw new NotFound(res.t('challengeMemberNotFound'));
|
||||
|
||||
|
||||
@@ -216,9 +216,9 @@ api.getChallengeTasks = {
|
||||
let user = res.locals.user;
|
||||
let challengeId = req.params.challengeId;
|
||||
|
||||
let challenge = await Challenge.findOne({_id: challengeId}).select('groupId leader tasksOrder').exec();
|
||||
let challenge = await Challenge.findOne({_id: challengeId}).select('group leader tasksOrder').exec();
|
||||
if (!challenge) throw new NotFound(res.t('challengeNotFound'));
|
||||
let group = await Group.getGroup({user, groupId: challenge.groupId, fields: '_id type privacy', optionalMembership: true});
|
||||
let group = await Group.getGroup({user, groupId: challenge.group, fields: '_id type privacy', optionalMembership: true});
|
||||
if (!group || !challenge.canView(user, group)) throw new NotFound(res.t('challengeNotFound'));
|
||||
|
||||
await _getTasks(req, res, res.locals.user, challenge);
|
||||
|
||||
@@ -20,7 +20,7 @@ let schema = new Schema({
|
||||
rewards: [{type: String, ref: 'Task'}],
|
||||
},
|
||||
leader: {type: String, ref: 'User', validate: [validator.isUUID, 'Invalid uuid.'], required: true},
|
||||
groupId: {type: String, ref: 'Group', validate: [validator.isUUID, 'Invalid uuid.'], required: true},
|
||||
group: {type: String, ref: 'Group', validate: [validator.isUUID, 'Invalid uuid.'], required: true},
|
||||
memberCount: {type: Number, default: 1},
|
||||
prize: {type: Number, default: 0, min: 0}, // TODO no update?
|
||||
});
|
||||
@@ -31,7 +31,7 @@ schema.plugin(baseModel, {
|
||||
});
|
||||
|
||||
// A list of additional fields that cannot be updated (but can be set on creation)
|
||||
let noUpdate = ['groupId', 'official', 'shortName', 'prize'];
|
||||
let noUpdate = ['group', 'official', 'shortName', 'prize'];
|
||||
schema.statics.sanitizeUpdate = function sanitizeUpdate (updateObj) {
|
||||
return this.sanitize(updateObj, noUpdate);
|
||||
};
|
||||
@@ -49,10 +49,7 @@ schema.methods.canModify = function canModifyChallenge (user) {
|
||||
// Returns true if user has access to the challenge (can join)
|
||||
schema.methods.hasAccess = function hasAccessToChallenge (user, group) {
|
||||
if (group.type === 'guild' && group.privacy === 'public') return true;
|
||||
let userGroups = user.guilds.slice(0); // clone user.guilds so we don't modify the original
|
||||
if (user.party._id) userGroups.push(user.party._id);
|
||||
userGroups.push('habitrpg'); // tavern
|
||||
return userGroups.indexOf(this.groupId) !== -1;
|
||||
return user.getGroups().indexOf(this.group) !== -1;
|
||||
};
|
||||
|
||||
// Returns true if user can view the challenge
|
||||
|
||||
@@ -84,6 +84,9 @@ schema.statics.sanitizeUpdate = function sanitizeUpdate (updateObj) {
|
||||
return this.sanitize(updateObj, noUpdate);
|
||||
};
|
||||
|
||||
// Basic fields to fetch for populating a group info
|
||||
export let basicFields = 'name type privacy';
|
||||
|
||||
// TODO migration
|
||||
/**
|
||||
* Derby duplicated stuff. This is a temporary solution, once we're completely off derby we'll run an mongo migration
|
||||
@@ -472,7 +475,7 @@ schema.methods.leave = async function leaveGroup (user, keep = 'keep-all') {
|
||||
|
||||
let challenges = await Challenge.find({
|
||||
_id: {$in: user.challenges},
|
||||
groupId: group._id,
|
||||
group: group._id,
|
||||
});
|
||||
|
||||
let challengesToRemoveUserFrom = challenges.map(chal => {
|
||||
|
||||
@@ -654,6 +654,14 @@ schema.methods.isSubscribed = function isSubscribed () {
|
||||
return !!this.purchased.plan.customerId; // eslint-disable-line no-implicit-coercion
|
||||
};
|
||||
|
||||
// Get an array of groups ids the user is member of
|
||||
schema.methods.getGroups = function getUserGroups () {
|
||||
let userGroups = this.guilds.slice(0); // clone user.guilds so we don't modify the original
|
||||
if (this.party._id) userGroups.push(this.party._id);
|
||||
userGroups.push('habitrpg'); // tavern
|
||||
return userGroups;
|
||||
};
|
||||
|
||||
// Unlink challenges tasks (and the challenge itself) from user
|
||||
schema.methods.unlinkChallengeTasks = async function unlinkChallengeTasks (challengeId, keep) {
|
||||
let user = this;
|
||||
|
||||
Reference in New Issue
Block a user