From 40c9366a477a8f2458b244c072a5e81978b97d27 Mon Sep 17 00:00:00 2001 From: Matteo Pagliazzi Date: Tue, 12 Apr 2016 12:59:30 +0200 Subject: [PATCH] v3 adapt v2: misc fixes --- website/src/controllers/api-v2/auth.js | 1 + website/src/controllers/api-v2/challenges.js | 28 +++++++++++--------- website/src/controllers/api-v2/groups.js | 16 ++++++----- website/src/controllers/api-v2/user.js | 15 +++++++---- website/src/middlewares/api-v3/locals.js | 2 +- website/src/models/user.js | 2 ++ 6 files changed, 40 insertions(+), 24 deletions(-) diff --git a/website/src/controllers/api-v2/auth.js b/website/src/controllers/api-v2/auth.js index 6ad3f30412..d5b9aff9e2 100644 --- a/website/src/controllers/api-v2/auth.js +++ b/website/src/controllers/api-v2/auth.js @@ -132,6 +132,7 @@ api.registerUser = function(req, res, next) { analytics.track('register', analyticsData) user.save(function(err, savedUser){ + if (err) return cb(err); // Clean previous email preferences // TODO when emails added to EmailUnsubcription they should use lowercase version EmailUnsubscription.remove({email: savedUser.auth.local.email}, function(){ diff --git a/website/src/controllers/api-v2/challenges.js b/website/src/controllers/api-v2/challenges.js index a6b1a3ae48..877048d211 100644 --- a/website/src/controllers/api-v2/challenges.js +++ b/website/src/controllers/api-v2/challenges.js @@ -9,6 +9,7 @@ import { } from '../../models/user'; import { model as Group, + basicFields as basicGroupFields, } from '../../models/group'; import { model as Challenge, @@ -27,6 +28,8 @@ import v3MembersController from '../api-v3/members'; ------------------------------------------------------------------------ */ +var nameFields = 'profile.name'; + api.list = async function(req, res, next) { try { var user = res.locals.user; @@ -195,7 +198,7 @@ api.create = async function(req, res, next){ chalTasks = chalTasks.map(function(task) { var newTask = new Tasks[task.type](Tasks.Task.sanitizeCreate(task)); - newTask.challenge.id = chal._id; + newTask.challenge.id = challenge._id; return newTask.save(); }); @@ -251,9 +254,7 @@ api.update = function(req, res, next){ }, tasks: function(cb1) { // Convert to map of {id: task} so we can easily match them - var _beforeClonedTasks = _.cloneDeep(_before.tasks.map(function(t) { - return t.toObject(); - })); + var _beforeClonedTasks = _before.tasks; updatedTasks = _.object(_.pluck(_beforeClonedTasks, '_id'), _beforeClonedTasks); var newTasks = req.body.habits.concat(req.body.dailys) .concat(req.body.todos).concat(req.body.rewards); @@ -261,11 +262,11 @@ api.update = function(req, res, next){ var newTasksObj = _.object(_.pluck(newTasks, '_id'), newTasks); async.forEachOf(newTasksObj, function(newTask, taskId, cb2){ // some properties can't be changed - Tasks.Task.sanitize(newTask); + newTask = Tasks.Task.sanitize(newTask); // TODO we have to convert task to an object because otherwise things don't get merged correctly. Bad for performances? // TODO regarding comment above, make sure other models with nested fields are using this trick too - _.assign(updatedTasks[taskId], common.ops.updateTask(task.toObject(), {body: newTask})); - challenge.updateTask(updatedTasks[taskId]); + _.assign(updatedTasks[taskId], shared.ops.updateTask(updatedTasks[taskId].toObject(), {body: newTask})); + _before.chal.updateTask(updatedTasks[taskId]).then(cb2).catch(cb2); }, cb1); } }, cb); @@ -313,8 +314,8 @@ api.selectWinner = async function(req, res, next) { if (!req.query.uid) return res.status(401).json({err: 'Must select a winner'}); let challenge = await Challenge.findOne({_id: req.params.cid}).exec(); - if (!challenge) return next('Challenge ' + cid + ' not found'); - if (!challenge.canModify(user)) return next(shared.i18n.t('noPermissionCloseChallenge')); + if (!challenge) return next('Challenge ' + req.params.cid + ' not found'); + if (!challenge.canModify(res.locals.user)) return next(shared.i18n.t('noPermissionCloseChallenge')); let winner = await User.findOne({_id: req.params.uid}).exec(); if (!winner || winner.challenges.indexOf(challenge._id) === -1) return next('Winner ' + req.query.uid + ' not found.'); @@ -386,29 +387,32 @@ api.leave = async function(req, res, next){ } } +import { removeFromArray } from '../../libs/api-v3/collectionManipulators'; + api.unlink = async function(req, res, next) { try { var user = res.locals.user; var tid = req.params.id; - var cid = user.tasks[tid].challenge.id; + var cid; if (!req.query.keep) return res.status(400).json({err: 'Provide unlink method as ?keep=keep-all (keep, keep-all, remove, remove-all)'}); let keep = req.query.keep; let task = await Tasks.Task.findOne({ - _id: taskId, + _id: tid, userId: user._id, }).exec(); if (!task) return next(shared.i18n.t('taskNotFound')); if (!task.challenge.id) return next(shared.i18n.t('cantOnlyUnlinkChalTask')); + cid = task.challenge.id; if (keep === 'keep') { task.challenge = {}; await task.save(); } else { // remove if (task.type !== 'todo' || !task.completed) { // eslint-disable-line no-lonely-if - removeFromArray(user.tasksOrder[`${task.type}s`], taskId); + removeFromArray(user.tasksOrder[`${task.type}s`], tid); await Q.all([user.save(), task.remove()]); } else { await task.remove(); diff --git a/website/src/controllers/api-v2/groups.js b/website/src/controllers/api-v2/groups.js index 54b08985a1..fded19274e 100644 --- a/website/src/controllers/api-v2/groups.js +++ b/website/src/controllers/api-v2/groups.js @@ -838,7 +838,7 @@ api.removeMember = function(req, res, next){ // Sending an empty 204 because Group.update doesn't return the group // see http://mongoosejs.com/docs/api.html#model_Model.update - sendMessage(invited); + sendMessage(removedUser); group = uuid = null; return res.sendStatus(204); }); @@ -973,19 +973,23 @@ api.questAccept = function(req, res, next) { if (group.quest.key) return res.status(400).json({err: 'Your party is already on a quest. Try again when the current quest has ended.'}); if (!user.items.quests[key]) return res.status(400).json({err: "You don't own that quest scroll"}); + let members; + User.find({ 'party._id': group._id, _id: {$ne: user._id}, }).select('auth.facebook auth.local preferences.emailNotifications profile.name pushDevices') - .exec().then(members => { + .exec().then(membersF => { + members = membersF; + group.markModified('quest'); - group.quest.key = questKey; + group.quest.key = key; group.quest.leader = user._id; group.quest.members = {}; group.quest.members[user._id] = true; user.party.quest.RSVPNeeded = false; - user.party.quest.key = questKey; + user.party.quest.key = key; return User.update({ 'party._id': group._id, @@ -993,7 +997,7 @@ api.questAccept = function(req, res, next) { }, { $set: { 'party.quest.RSVPNeeded': true, - 'party.quest.key': questKey, + 'party.quest.key': key, }, }, {multi: true}).exec(); }).then(() => { @@ -1117,7 +1121,7 @@ api.questCancel = function(req, res, next){ Q.all([ group.save(), User.update( - {'party._id': groupId}, + {'party._id': group._id}, {$set: {'party.quest': Group.cleanQuestProgress()}}, {multi: true} ), diff --git a/website/src/controllers/api-v2/user.js b/website/src/controllers/api-v2/user.js index bfe9662148..2f343c43f6 100644 --- a/website/src/controllers/api-v2/user.js +++ b/website/src/controllers/api-v2/user.js @@ -7,6 +7,9 @@ var shared = require('../../../../common'); import { model as User, } from '../../models/user'; +import { + NotFound, +} from '../../libs/api-v3/errors'; import { model as Tag } from '../../models/tag'; import * as Tasks from '../../models/task'; import Q from 'q'; @@ -32,6 +35,8 @@ var api = module.exports; var firebase = require('../../libs/api-v2/firebase'); var webhook = require('../../libs/api-v2/webhook'); +const partyMembersFields = 'profile.name stats achievements items.special'; + // api.purchase // Shared.ops api.getContent = function(req, res, next) { @@ -610,8 +615,8 @@ api.cast = async function(req, res, next) { let spellId = req.params.spellId; let targetId = req.query.targetId; - let klass = common.content.spells.special[spellId] ? 'special' : user.stats.class; - let spell = common.content.spells[klass][spellId]; + let klass = shared.content.spells.special[spellId] ? 'special' : user.stats.class; + let spell = shared.content.spells[klass][spellId]; if (!spell) return res.status(404).json({err: 'Spell "' + req.params.spell + '" not found.'}); if (spell.mana > user.stats.mp) return res.status(400).json({err: 'Not enough mana to cast spell'}); @@ -893,13 +898,13 @@ _.each(shared.ops, function(op,k){ // If we want to send something other than 500, pass err as {code: 200, message: "Not enough GP"} res.locals.user.save(function(err){ if (err) return next(err); - if (response === user) { // add tasks - user.getTransformedData(function (err, transformedUser) { + if (opResponse === res.locals.user) { // add tasks + res.locals.user.getTransformedData(function (err, transformedUser) { if (err) return next(err); res.status(200).json(transformedUser); }); } else { - res.status(200).json(response); + res.status(200).json(opResponse); } }); } diff --git a/website/src/middlewares/api-v3/locals.js b/website/src/middlewares/api-v3/locals.js index 31e41c44f0..6630902b75 100644 --- a/website/src/middlewares/api-v3/locals.js +++ b/website/src/middlewares/api-v3/locals.js @@ -26,7 +26,7 @@ let env = { mods, Content: shared.content, siteVersion: forceRefresh.siteVersion, - availableLanguages: i18n.available, + availableLanguages: i18n.availableLanguages, AMAZON_PAYMENTS: { SELLER_ID: nconf.get('AMAZON_PAYMENTS:SELLER_ID'), CLIENT_ID: nconf.get('AMAZON_PAYMENTS:CLIENT_ID'), diff --git a/website/src/models/user.js b/website/src/models/user.js index f01ffba265..403134bfd4 100644 --- a/website/src/models/user.js +++ b/website/src/models/user.js @@ -753,6 +753,8 @@ schema.methods.getTasks = function getUserTasks () { // Given user and an array of tasks, return an API compatible user + tasks obj schema.methods.addTasksToUser = function addTasksToUser (tasks) { let obj = this.toJSON(); + + obj.id = obj._id; obj.filters = {}; obj.tags = obj.tags.map(tag => {