mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 23:27:26 +01:00
adapt v2: getTask, getTasks, clearCompleted, addTask, deleteTask, getUser, getUserAnonymized, scoreTask (challenge part missing)
This commit is contained in:
@@ -2,7 +2,7 @@ import {
|
|||||||
generateUser,
|
generateUser,
|
||||||
} from '../../../helpers/api-integration/v2';
|
} from '../../../helpers/api-integration/v2';
|
||||||
|
|
||||||
xdescribe('GET /user', () => {
|
describe('GET /user', () => {
|
||||||
let user;
|
let user;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
} from '../../../../helpers/api-integration/v2';
|
} from '../../../../helpers/api-integration/v2';
|
||||||
import { each } from 'lodash';
|
import { each } from 'lodash';
|
||||||
|
|
||||||
xdescribe('GET /user/anonymized', () => {
|
describe('GET /user/anonymized', () => {
|
||||||
let user, anonymizedUser;
|
let user, anonymizedUser;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
translate as t,
|
translate as t,
|
||||||
} from '../../../../helpers/api-integration/v2';
|
} from '../../../../helpers/api-integration/v2';
|
||||||
|
|
||||||
xdescribe('DELETE /user/tasks/:id', () => {
|
describe('DELETE /user/tasks/:id', () => {
|
||||||
let user, task;
|
let user, task;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|||||||
@@ -2,18 +2,11 @@ import {
|
|||||||
generateUser,
|
generateUser,
|
||||||
} from '../../../../helpers/api-integration/v2';
|
} from '../../../../helpers/api-integration/v2';
|
||||||
|
|
||||||
xdescribe('GET /user/tasks/', () => {
|
describe('GET /user/tasks/', () => {
|
||||||
let user;
|
let user;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
return generateUser({
|
return generateUser().then((_user) => {
|
||||||
dailys: [
|
|
||||||
{text: 'daily', type: 'daily'},
|
|
||||||
{text: 'daily', type: 'daily'},
|
|
||||||
{text: 'daily', type: 'daily'},
|
|
||||||
{text: 'daily', type: 'daily'},
|
|
||||||
],
|
|
||||||
}).then((_user) => {
|
|
||||||
user = _user;
|
user = _user;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -21,7 +14,7 @@ xdescribe('GET /user/tasks/', () => {
|
|||||||
it('gets all tasks', async () => {
|
it('gets all tasks', async () => {
|
||||||
return user.get(`/user/tasks/`).then((tasks) => {
|
return user.get(`/user/tasks/`).then((tasks) => {
|
||||||
expect(tasks).to.be.an('array');
|
expect(tasks).to.be.an('array');
|
||||||
expect(tasks.length).to.be.greaterThan(3);
|
expect(tasks.length).to.equal(1)
|
||||||
|
|
||||||
let task = tasks[0];
|
let task = tasks[0];
|
||||||
expect(task.id).to.exist;
|
expect(task.id).to.exist;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
translate as t,
|
translate as t,
|
||||||
} from '../../../../helpers/api-integration/v2';
|
} from '../../../../helpers/api-integration/v2';
|
||||||
|
|
||||||
xdescribe('GET /user/tasks/:id', () => {
|
describe('GET /user/tasks/:id', () => {
|
||||||
let user, task;
|
let user, task;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|||||||
26
test/api/v2/user/tasks/POST-clear-completed.test.js
Normal file
26
test/api/v2/user/tasks/POST-clear-completed.test.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
} from '../../../../helpers/api-integration/v2';
|
||||||
|
|
||||||
|
describe.only('POST /user/tasks/clear-completed', () => {
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
return generateUser().then((_user) => {
|
||||||
|
user = _user;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removes all completed todos', async () => {
|
||||||
|
let toComplete = await user.post('/user/tasks', {
|
||||||
|
type: 'todo',
|
||||||
|
text: 'done',
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(`/user/tasks/${toComplete._id}/up`)
|
||||||
|
|
||||||
|
let todos = await user.get(`/user/tasks?type=todo`);
|
||||||
|
let uncomplete = await user.post(`/user/tasks/clear-completed`);
|
||||||
|
expect(todos.length).to.equal(uncomplete.length + 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
translate as t,
|
translate as t,
|
||||||
} from '../../../../helpers/api-integration/v2';
|
} from '../../../../helpers/api-integration/v2';
|
||||||
|
|
||||||
xdescribe('POST /user/tasks', () => {
|
describe('POST /user/tasks', () => {
|
||||||
let user;
|
let user;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@@ -35,7 +35,7 @@ xdescribe('POST /user/tasks', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not create a task with an id that already exists', async () => {
|
xit('does not create a task with an id that already exists', async () => {
|
||||||
let todo = user.todos[0];
|
let todo = user.todos[0];
|
||||||
|
|
||||||
return expect(user.post('/user/tasks', {
|
return expect(user.post('/user/tasks', {
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ var nconf = require('nconf');
|
|||||||
var async = require('async');
|
var async = require('async');
|
||||||
var shared = require('../../../../common');
|
var shared = require('../../../../common');
|
||||||
var User = require('./../../models/user').model;
|
var User = require('./../../models/user').model;
|
||||||
|
import * as Tasks from '../../models/task';
|
||||||
|
import Q from 'q';
|
||||||
|
import {removeFromArray} from './../../libs/api-v3/collectionManipulators';
|
||||||
var utils = require('./../../libs/api-v2/utils');
|
var utils = require('./../../libs/api-v2/utils');
|
||||||
var analytics = utils.analytics;
|
var analytics = utils.analytics;
|
||||||
var Group = require('./../../models/group').model;
|
var Group = require('./../../models/group').model;
|
||||||
@@ -69,78 +72,104 @@ api.score = function(req, res, next) {
|
|||||||
var id = req.params.id,
|
var id = req.params.id,
|
||||||
direction = req.params.direction,
|
direction = req.params.direction,
|
||||||
user = res.locals.user,
|
user = res.locals.user,
|
||||||
|
body = req.body || {},
|
||||||
task;
|
task;
|
||||||
|
|
||||||
var clearMemory = function(){user = task = id = direction = null;}
|
|
||||||
|
|
||||||
// Send error responses for improper API call
|
// Send error responses for improper API call
|
||||||
if (!id) return res.status(400).json({err: ':id required'});
|
if (!id) return res.json(400, {err: ':id required'});
|
||||||
if (direction !== 'up' && direction !== 'down') {
|
if (direction !== 'up' && direction !== 'down') {
|
||||||
if (direction == 'unlink' || direction == 'sort') return next();
|
if (direction == 'unlink' || direction == 'sort') return next();
|
||||||
return res.status(400).json({err: ":direction must be 'up' or 'down'"});
|
return res.json(400, {err: ":direction must be 'up' or 'down'"});
|
||||||
}
|
}
|
||||||
// If exists already, score it
|
|
||||||
if (task = user.tasks[id]) {
|
Tasks.Task.findOne({
|
||||||
// Set completed if type is daily or todo and task exists
|
_id: id,
|
||||||
|
userId: user._id
|
||||||
|
}, function(err, task){
|
||||||
|
if(err) return next(err);
|
||||||
|
|
||||||
|
// If exists already, score it
|
||||||
|
if (!task) {
|
||||||
|
// If it doesn't exist, this is likely a 3rd party up/down - create a new one, then score it
|
||||||
|
// Defaults. Other defaults are handled in user.ops.addTask()
|
||||||
|
task = new Tasks.Task({
|
||||||
|
_id: id, // TODO this might easily lead to conflicts as ids are now unique db-wide
|
||||||
|
type: body.type,
|
||||||
|
text: body.text,
|
||||||
|
userId: user._id,
|
||||||
|
notes: body.notes || "This task was created by a third-party service. Feel free to edit, it won't harm the connection to that service. Additionally, multiple services may piggy-back off this task." // TODO translate
|
||||||
|
});
|
||||||
|
|
||||||
|
user.tasksOrder[task.type + 's'].unshift(task._id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set completed if type is daily or todo
|
||||||
if (task.type === 'daily' || task.type === 'todo') {
|
if (task.type === 'daily' || task.type === 'todo') {
|
||||||
task.completed = direction === 'up';
|
task.completed = direction === 'up';
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// If it doesn't exist, this is likely a 3rd party up/down - create a new one, then score it
|
|
||||||
// Defaults. Other defaults are handled in user.ops.addTask()
|
|
||||||
task = {
|
|
||||||
id: id,
|
|
||||||
type: req.body && req.body.type,
|
|
||||||
text: req.body && req.body.text,
|
|
||||||
notes: (req.body && req.body.notes) || "This task was created by a third-party service. Feel free to edit, it won't harm the connection to that service. Additionally, multiple services may piggy-back off this task."
|
|
||||||
};
|
|
||||||
|
|
||||||
if (task.type === 'daily' || task.type === 'todo')
|
var delta = shared.ops.scoreTask({
|
||||||
task.completed = direction === 'up';
|
user,
|
||||||
|
task,
|
||||||
|
direction,
|
||||||
|
}, req);
|
||||||
|
|
||||||
task = user.ops.addTask({body:task});
|
async.parallel({
|
||||||
}
|
task: task.save.bind(task),
|
||||||
var delta = user.ops.score({params:{id:task.id, direction:direction}, language: req.language});
|
user: user.save.bind(user)
|
||||||
|
}, function(err, results){
|
||||||
|
if(err) return next(err);
|
||||||
|
|
||||||
user.save(function(err, saved){
|
// FIXME this is suuuper strange, sometimes results.user is an array, sometimes user directly
|
||||||
if (err) return next(err);
|
var saved = Array.isArray(results.user) ? results.user[0] : results.user;
|
||||||
|
var task = Array.isArray(results.task) ? results.task[0] : results.task;
|
||||||
|
|
||||||
var userStats = saved.toJSON().stats;
|
var userStats = saved.toJSON().stats;
|
||||||
var resJsonData = _.extend({ delta: delta, _tmp: user._tmp }, userStats);
|
var resJsonData = _.extend({ delta: delta, _tmp: user._tmp }, userStats);
|
||||||
res.status(200).json(resJsonData);
|
res.json(200, resJsonData);
|
||||||
|
|
||||||
var webhookData = _generateWebhookTaskData(
|
var webhookData = _generateWebhookTaskData(
|
||||||
task, direction, delta, userStats, user
|
task, direction, delta, userStats, user
|
||||||
);
|
);
|
||||||
webhook.sendTaskWebhook(user.preferences.webhooks, webhookData);
|
webhook.sendTaskWebhook(user.preferences.webhooks, webhookData);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(!task.challenge || !task.challenge.id || task.challenge.broken) // If it's a challenge task, sync the score. Do it in the background, we've already sent down a response and the user doesn't care what happens back there
|
(!task.challenge.id || task.challenge.broken) // If it's a challenge task, sync the score. Do it in the background, we've already sent down a response and the user doesn't care what happens back there
|
||||||
|| (task.type == 'reward') // we don't want to update the reward GP cost
|
|| (task.type == 'reward') // we don't want to update the reward GP cost
|
||||||
) return clearMemory();
|
) return;
|
||||||
|
|
||||||
Challenge.findById(task.challenge.id, 'habits dailys todos rewards', function(err, chal) {
|
// select name and shortName because they can be synced on syncToUser
|
||||||
if (err) return next(err);
|
Challenge.findById(task.challenge.id, 'name shortName', function(err, chal) {
|
||||||
if (!chal) {
|
if (err) return next(err);
|
||||||
task.challenge.broken = 'CHALLENGE_DELETED';
|
if (!chal) {
|
||||||
user.save();
|
task.challenge.broken = 'CHALLENGE_DELETED';
|
||||||
return clearMemory();
|
task.save();
|
||||||
}
|
return;
|
||||||
var t = chal.tasks[task.id];
|
}
|
||||||
// this task was removed from the challenge, notify user
|
|
||||||
if (!t) {
|
|
||||||
chal.syncToUser(user);
|
|
||||||
return clearMemory();
|
|
||||||
}
|
|
||||||
|
|
||||||
t.value += delta;
|
Tasks.Task.findOne({
|
||||||
if (t.type == 'habit' || t.type == 'daily') {
|
'_id': task.challenge.taskId,
|
||||||
t.history.push({value: t.value, date: +new Date});
|
userId: {$exists: false}
|
||||||
}
|
}, function(err, chalTask){
|
||||||
chal.save();
|
if(err) return; //FIXME
|
||||||
clearMemory();
|
// this task was removed from the challenge, notify user
|
||||||
|
if(!chalTask) {
|
||||||
|
// TODO finish
|
||||||
|
chal.getTasks(function(err, chalTasks){
|
||||||
|
if(err) return; //FIXME
|
||||||
|
chal.syncToUser(user, chalTasks);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
chalTask.value += delta;
|
||||||
|
if (chalTask.type == 'habit' || chalTask.type == 'daily')
|
||||||
|
chalTask.history.push({value: chalTask.value, date: +new Date});
|
||||||
|
chalTask.save();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -148,32 +177,29 @@ api.score = function(req, res, next) {
|
|||||||
*/
|
*/
|
||||||
api.getTasks = function(req, res, next) {
|
api.getTasks = function(req, res, next) {
|
||||||
var user = res.locals.user;
|
var user = res.locals.user;
|
||||||
if (req.query.type) {
|
|
||||||
return res.json(user[req.query.type+'s']);
|
user.getTasks(req.query.type, function (err, tasks) {
|
||||||
} else {
|
if (err) return next(err);
|
||||||
return res.json(_.toArray(user.tasks));
|
res.status(200).json(tasks.map(task => task.toJSONV2()));
|
||||||
}
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Task
|
* Get Task
|
||||||
*/
|
*/
|
||||||
api.getTask = function(req, res, next) {
|
api.getTask = function(req, res, next) {
|
||||||
var task = findTask(req,res);
|
var user = res.locals.user;
|
||||||
if (!task) return res.status(404).json({err: shared.i18n.t('messageTaskNotFound')});
|
|
||||||
return res.status(200).json(task);
|
Tasks.Task.findOne({
|
||||||
|
userId: user._id,
|
||||||
|
_id: req.params.id,
|
||||||
|
}, function (err, task) {
|
||||||
|
if (err) return next(err);
|
||||||
|
if (!task) return res.status(404).json({err: shared.i18n.t('messageTaskNotFound')});
|
||||||
|
res.status(200).json(task.toJSONV2());
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Update Task
|
|
||||||
*/
|
|
||||||
|
|
||||||
//api.deleteTask // see Shared.ops
|
|
||||||
// api.updateTask // handled in Shared.ops
|
|
||||||
// api.addTask // handled in Shared.ops
|
|
||||||
// api.sortTask // handled in Shared.ops #TODO updated api, mention in docs
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
Items
|
Items
|
||||||
@@ -196,89 +222,91 @@ api.getBuyList = function (req, res, next) {
|
|||||||
* Get User
|
* Get User
|
||||||
*/
|
*/
|
||||||
api.getUser = function(req, res, next) {
|
api.getUser = function(req, res, next) {
|
||||||
var user = res.locals.user.toJSON();
|
res.locals.user.getTransformedData(function(err, user){
|
||||||
user.stats.toNextLevel = shared.tnl(user.stats.lvl);
|
user.stats.toNextLevel = shared.tnl(user.stats.lvl);
|
||||||
user.stats.maxHealth = shared.maxHealth;
|
user.stats.maxHealth = shared.maxHealth;
|
||||||
user.stats.maxMP = res.locals.user._statsComputed.maxMP;
|
user.stats.maxMP = res.locals.user._statsComputed.maxMP;
|
||||||
delete user.apiToken;
|
delete user.apiToken;
|
||||||
if (user.auth && user.auth.local) {
|
if (user.auth && user.auth.local) {
|
||||||
delete user.auth.local.hashed_password;
|
delete user.auth.local.hashed_password;
|
||||||
delete user.auth.local.salt;
|
delete user.auth.local.salt;
|
||||||
}
|
}
|
||||||
return res.status(200).json(user);
|
return res.status(200).json(user);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get anonymized User
|
* Get anonymized User
|
||||||
*/
|
*/
|
||||||
api.getUserAnonymized = function(req, res, next) {
|
api.getUserAnonymized = function(req, res, next) {
|
||||||
var user = res.locals.user.toJSON();
|
res.locals.user.getTransformedData(function(err, user){
|
||||||
user.stats.toNextLevel = shared.tnl(user.stats.lvl);
|
user.stats.toNextLevel = shared.tnl(user.stats.lvl);
|
||||||
user.stats.maxHealth = shared.maxHealth;
|
user.stats.maxHealth = shared.maxHealth;
|
||||||
user.stats.maxMP = res.locals.user._statsComputed.maxMP;
|
user.stats.maxMP = res.locals.user._statsComputed.maxMP;
|
||||||
|
|
||||||
delete user.apiToken;
|
delete user.apiToken;
|
||||||
|
|
||||||
if (user.auth) {
|
if (user.auth) {
|
||||||
delete user.auth.local;
|
delete user.auth.local;
|
||||||
delete user.auth.facebook;
|
delete user.auth.facebook;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete user.newMessages;
|
delete user.newMessages;
|
||||||
|
|
||||||
delete user.profile;
|
delete user.profile;
|
||||||
delete user.purchased.plan;
|
delete user.purchased.plan;
|
||||||
delete user.contributor;
|
delete user.contributor;
|
||||||
delete user.invitations;
|
delete user.invitations;
|
||||||
|
|
||||||
delete user.items.special.nyeReceived;
|
delete user.items.special.nyeReceived;
|
||||||
delete user.items.special.valentineReceived;
|
delete user.items.special.valentineReceived;
|
||||||
|
|
||||||
delete user.webhooks;
|
delete user.webhooks;
|
||||||
delete user.achievements.challenges;
|
delete user.achievements.challenges;
|
||||||
|
|
||||||
_.forEach(user.inbox.messages, function(msg){
|
_.forEach(user.inbox.messages, function(msg){
|
||||||
msg.text = "inbox message text";
|
msg.text = "inbox message text";
|
||||||
});
|
|
||||||
|
|
||||||
_.forEach(user.tags, function(tag){
|
|
||||||
tag.name = "tag";
|
|
||||||
tag.challenge = "challenge";
|
|
||||||
});
|
|
||||||
|
|
||||||
function cleanChecklist(task){
|
|
||||||
var checklistIndex = 0;
|
|
||||||
|
|
||||||
_.forEach(task.checklist, function(c){
|
|
||||||
c.text = "item" + checklistIndex++;
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
_.forEach(user.habits, function(task){
|
_.forEach(user.tags, function(tag){
|
||||||
task.text = "task text";
|
tag.name = "tag";
|
||||||
task.notes = "task notes";
|
tag.challenge = "challenge";
|
||||||
|
});
|
||||||
|
|
||||||
|
function cleanChecklist(task){
|
||||||
|
var checklistIndex = 0;
|
||||||
|
|
||||||
|
_.forEach(task.checklist, function(c){
|
||||||
|
c.text = "item" + checklistIndex++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_.forEach(user.habits, function(task){
|
||||||
|
task.text = "task text";
|
||||||
|
task.notes = "task notes";
|
||||||
|
});
|
||||||
|
|
||||||
|
_.forEach(user.rewards, function(task){
|
||||||
|
task.text = "task text";
|
||||||
|
task.notes = "task notes";
|
||||||
|
});
|
||||||
|
|
||||||
|
_.forEach(user.dailys, function(task){
|
||||||
|
task.text = "task text";
|
||||||
|
task.notes = "task notes";
|
||||||
|
|
||||||
|
cleanChecklist(task);
|
||||||
|
});
|
||||||
|
|
||||||
|
_.forEach(user.todos, function(task){
|
||||||
|
task.text = "task text";
|
||||||
|
task.notes = "task notes";
|
||||||
|
|
||||||
|
cleanChecklist(task);
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.status(200).json(user);
|
||||||
});
|
});
|
||||||
|
|
||||||
_.forEach(user.rewards, function(task){
|
|
||||||
task.text = "task text";
|
|
||||||
task.notes = "task notes";
|
|
||||||
});
|
|
||||||
|
|
||||||
_.forEach(user.dailys, function(task){
|
|
||||||
task.text = "task text";
|
|
||||||
task.notes = "task notes";
|
|
||||||
|
|
||||||
cleanChecklist(task);
|
|
||||||
});
|
|
||||||
|
|
||||||
_.forEach(user.todos, function(task){
|
|
||||||
task.text = "task text";
|
|
||||||
task.notes = "task notes";
|
|
||||||
|
|
||||||
cleanChecklist(task);
|
|
||||||
});
|
|
||||||
|
|
||||||
return res.status(200).json(user);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -587,6 +615,81 @@ api.sessionPartyInvite = function(req,res,next){
|
|||||||
], next);
|
], next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
api.clearCompleted = function(req, res, next) {
|
||||||
|
var user = res.locals.user;
|
||||||
|
|
||||||
|
Tasks.Task.remove({
|
||||||
|
userId: user._id,
|
||||||
|
type: 'todo',
|
||||||
|
completed: true,
|
||||||
|
'challenge.id': {$exists: false},
|
||||||
|
}, function (err) {
|
||||||
|
if (err) return next(err);
|
||||||
|
|
||||||
|
Tasks.Task.find({
|
||||||
|
userId: user._id,
|
||||||
|
type: 'todo',
|
||||||
|
completed: false,
|
||||||
|
}, function (err, uncompleted) {
|
||||||
|
if (err) return next(err);
|
||||||
|
res.json(uncompleted);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
api.deleteTask = function(req, res, next) {
|
||||||
|
var user = res.locals.user;
|
||||||
|
if(!req.params || !req.params.id) return res.json(404, shared.i18n.t('messageTaskNotFound', req.language));
|
||||||
|
|
||||||
|
var id = req.params.id;
|
||||||
|
// Try removing from all orders since we don't know the task's type
|
||||||
|
var removeTaskFromOrder = function(array) {
|
||||||
|
removeFromArray(array, id);
|
||||||
|
};
|
||||||
|
|
||||||
|
['habits', 'dailys', 'todos', 'rewards'].forEach(function (type){
|
||||||
|
removeTaskFromOrder(user.tasksOrder[type])
|
||||||
|
});
|
||||||
|
|
||||||
|
async.parallel({
|
||||||
|
user: user.save.bind(user),
|
||||||
|
task: function(cb) {
|
||||||
|
Tasks.Task.remove({_id: id, userId: user._id}, cb);
|
||||||
|
}
|
||||||
|
}, function(err, results) {
|
||||||
|
if(err) return next(err);
|
||||||
|
|
||||||
|
if(results.task.result.n < 1){
|
||||||
|
return res.status(404).json({err: shared.i18n.t('messageTaskNotFound', req.language)})
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json({});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
api.addTask = function(req, res, next) {
|
||||||
|
var user = res.locals.user;
|
||||||
|
req.body.type = req.body.type || 'habit';
|
||||||
|
req.body.text = req.body.text || 'text';
|
||||||
|
|
||||||
|
var task = new Tasks[req.body.type](Tasks.Task.sanitizeCreate(req.body));
|
||||||
|
|
||||||
|
task.userId = user._id;
|
||||||
|
user.tasksOrder[task.type + 's'].unshift(task._id);
|
||||||
|
|
||||||
|
// Validate that the task is valid and throw if it isn't
|
||||||
|
// otherwise since we're saving user/challenge and task in parallel it could save the user/challenge with a tasksOrder that doens't match reality
|
||||||
|
let validationErrors = task.validateSync();
|
||||||
|
if (validationErrors) return next(validationErrors);
|
||||||
|
|
||||||
|
Q.all([
|
||||||
|
user.save(),
|
||||||
|
task.save({validateBeforeSave: false}) // already done ^
|
||||||
|
]).then(results => {
|
||||||
|
res.status(200).json(results[1].toJSONV2());
|
||||||
|
}).catch(next);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All other user.ops which can easily be mapped to common/script/index.js, not requiring custom API-wrapping
|
* All other user.ops which can easily be mapped to common/script/index.js, not requiring custom API-wrapping
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
var logging = require('../../libs/api-v2/logging');
|
var logging = require('../../libs/api-v2/logging');
|
||||||
|
|
||||||
module.exports = function(err, req, res, next) {
|
module.exports = function(err, req, res, next) {
|
||||||
console.log(err, 'HEEEERE');
|
|
||||||
//res.locals.domain.emit('error', err);
|
//res.locals.domain.emit('error', err);
|
||||||
// when we hit an error, send it to admin as an email. If no ADMIN_EMAIL is present, just send it to yourself (SMTP_USER)
|
// when we hit an error, send it to admin as an email. If no ADMIN_EMAIL is present, just send it to yourself (SMTP_USER)
|
||||||
var stack = (err.stack ? err.stack : err.message ? err.message : err) +
|
var stack = (err.stack ? err.stack : err.message ? err.message : err) +
|
||||||
|
|||||||
@@ -108,6 +108,19 @@ TaskSchema.methods.scoreChallengeTask = async function scoreChallengeTask (delta
|
|||||||
await chalTask.save();
|
await chalTask.save();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Methods to adapt the new schema to API v2 responses (mostly tasks inside the user model)
|
||||||
|
// These will be removed once API v2 is discontinued
|
||||||
|
|
||||||
|
// toJSON for API v2
|
||||||
|
TaskSchema.methods.toJSONV2 = function toJSONV2 () {
|
||||||
|
let toJSON = this.toJSON();
|
||||||
|
toJSON.id = toJSON._id;
|
||||||
|
return toJSON;
|
||||||
|
};
|
||||||
|
|
||||||
|
// END of API v2 methods
|
||||||
|
|
||||||
export let Task = mongoose.model('Task', TaskSchema);
|
export let Task = mongoose.model('Task', TaskSchema);
|
||||||
|
|
||||||
// habits and dailies shared fields
|
// habits and dailies shared fields
|
||||||
|
|||||||
@@ -729,10 +729,25 @@ schema.methods.sendMessage = async function sendMessage (userToReceiveMessage, m
|
|||||||
// These will be removed once API v2 is discontinued
|
// These will be removed once API v2 is discontinued
|
||||||
|
|
||||||
// Get all the tasks belonging to an user,
|
// Get all the tasks belonging to an user,
|
||||||
schema.methods.getTasks = function getUserTasks (cb) {
|
schema.methods.getTasks = function getUserTasks () {
|
||||||
Tasks.Task.find({
|
let args = Array.from(arguments);
|
||||||
|
let cb;
|
||||||
|
let type;
|
||||||
|
|
||||||
|
if (args.length === 1) {
|
||||||
|
cb = args[0];
|
||||||
|
} else {
|
||||||
|
type = args[0];
|
||||||
|
cb = args[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
let query = {
|
||||||
userId: this._id,
|
userId: this._id,
|
||||||
}, cb);
|
};
|
||||||
|
|
||||||
|
if (type) query.type = type;
|
||||||
|
|
||||||
|
Tasks.Task.find(query, cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Given user and an array of tasks, return an API compatible user + tasks obj
|
// Given user and an array of tasks, return an API compatible user + tasks obj
|
||||||
@@ -752,9 +767,9 @@ schema.methods.addTasksToUser = function addTasksToUser (tasks) {
|
|||||||
// We want to push the task at the same position where it's stored in tasksOrder
|
// We want to push the task at the same position where it's stored in tasksOrder
|
||||||
let pos = tasksOrder[`${task.type}s`].indexOf(task._id);
|
let pos = tasksOrder[`${task.type}s`].indexOf(task._id);
|
||||||
if (pos === -1) { // Should never happen, it means the lists got out of sync
|
if (pos === -1) { // Should never happen, it means the lists got out of sync
|
||||||
unordered.push(task.toJSON());
|
unordered.push(task.toJSONV2());
|
||||||
} else {
|
} else {
|
||||||
obj[`${task.type}s`][pos] = task.toJSON();
|
obj[`${task.type}s`][pos] = task.toJSONV2();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user