add population to challenge.group, challenge.leader and group.leader
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user