From b431b020122d4682977582fc333533dc21150c7b Mon Sep 17 00:00:00 2001 From: Matteo Pagliazzi Date: Wed, 6 Apr 2016 19:28:43 +0200 Subject: [PATCH] v3 adapt v2: port tags, cast, cron, deletUser and removeMember. Fix a few bugs in v3 --- common/script/ops/addTag.js | 2 + common/script/ops/deleteTag.js | 2 + common/script/ops/deleteTask.js | 2 + common/script/ops/getTag.js | 2 + common/script/ops/getTags.js | 2 + common/script/ops/sortTag.js | 2 + common/script/ops/sortTask.js | 2 + common/script/ops/updateTag.js | 2 + .../POST-groups_id_removeMember.test.js | 2 +- test/api/v2/user/DELETE-user.test.js | 2 +- test/api/v2/user/GET-user_tags.test.js | 2 +- test/api/v2/user/GET-user_tags_id.test.js | 2 +- .../POST-user_batch-update.test.js | 2 +- website/src/controllers/api-v2/groups.js | 65 ++-- website/src/controllers/api-v2/user.js | 361 ++++++++++++------ website/src/controllers/api-v3/tags.js | 11 +- website/src/controllers/api-v3/user.js | 2 +- website/src/middlewares/api-v3/cron.js | 4 +- website/src/models/task.js | 8 + website/src/models/user.js | 9 + website/src/routes/api-v2/auth.js | 17 +- website/src/routes/api-v2/coupon.js | 7 +- website/src/routes/api-v2/swagger.js | 77 ++-- website/src/routes/api-v2/unsubscription.js | 3 +- website/src/routes/payments.js | 37 +- 25 files changed, 409 insertions(+), 218 deletions(-) diff --git a/common/script/ops/addTag.js b/common/script/ops/addTag.js index a020a5fbaf..2b97e67f38 100644 --- a/common/script/ops/addTag.js +++ b/common/script/ops/addTag.js @@ -1,5 +1,7 @@ import uuid from '../libs/uuid'; +// TODO used only in client, move there? + module.exports = function(user, req, cb) { if (user.tags == null) { user.tags = []; diff --git a/common/script/ops/deleteTag.js b/common/script/ops/deleteTag.js index a82af59e86..275aa3e5bd 100644 --- a/common/script/ops/deleteTag.js +++ b/common/script/ops/deleteTag.js @@ -1,6 +1,8 @@ import i18n from '../i18n'; import _ from 'lodash'; +// TODO used only in client, move there? + module.exports = function(user, req, cb) { var i, tag, tid; tid = req.params.id; diff --git a/common/script/ops/deleteTask.js b/common/script/ops/deleteTask.js index 715b102241..a830e19257 100644 --- a/common/script/ops/deleteTask.js +++ b/common/script/ops/deleteTask.js @@ -1,5 +1,7 @@ import i18n from '../i18n'; +// TODO used only in client, move there? + module.exports = function(user, req, cb) { var i, ref, task; task = user.tasks[(ref = req.params) != null ? ref.id : void 0]; diff --git a/common/script/ops/getTag.js b/common/script/ops/getTag.js index 06f3f24110..b54133c2c7 100644 --- a/common/script/ops/getTag.js +++ b/common/script/ops/getTag.js @@ -1,6 +1,8 @@ import _ from 'lodash'; import i18n from '../i18n'; +// TODO used only in client, move there? + module.exports = function(user, req, cb) { var i, tid; tid = req.params.id; diff --git a/common/script/ops/getTags.js b/common/script/ops/getTags.js index af9419b050..b379f13578 100644 --- a/common/script/ops/getTags.js +++ b/common/script/ops/getTags.js @@ -1,3 +1,5 @@ +// TODO used only in client, move there? + module.exports = function(user, req, cb) { return typeof cb === "function" ? cb(null, user.tags) : void 0; }; diff --git a/common/script/ops/sortTag.js b/common/script/ops/sortTag.js index 85dcda169f..d47083ad3f 100644 --- a/common/script/ops/sortTag.js +++ b/common/script/ops/sortTag.js @@ -1,3 +1,5 @@ +// TODO used only in client, move there? + module.exports = function(user, req, cb) { var from, ref, to; ref = req.query, to = ref.to, from = ref.from; diff --git a/common/script/ops/sortTask.js b/common/script/ops/sortTask.js index b903b692dc..212eaf4de2 100644 --- a/common/script/ops/sortTask.js +++ b/common/script/ops/sortTask.js @@ -1,6 +1,8 @@ import i18n from '../i18n'; import preenTodos from '../libs/preenTodos'; +// TODO used only in client, move there? + module.exports = function(user, req, cb) { var from, id, movedTask, preenedTasks, ref, task, tasks, to; id = req.params.id; diff --git a/common/script/ops/updateTag.js b/common/script/ops/updateTag.js index 8e4019fa51..5e61ff8c6b 100644 --- a/common/script/ops/updateTag.js +++ b/common/script/ops/updateTag.js @@ -1,6 +1,8 @@ import i18n from '../i18n'; import _ from 'lodash'; +// TODO used only in client, move there? + module.exports = function(user, req, cb) { var i, tid; tid = req.params.id; diff --git a/test/api/v2/groups/POST-groups_id_removeMember.test.js b/test/api/v2/groups/POST-groups_id_removeMember.test.js index e594cf0748..ccedd69e9d 100644 --- a/test/api/v2/groups/POST-groups_id_removeMember.test.js +++ b/test/api/v2/groups/POST-groups_id_removeMember.test.js @@ -3,7 +3,7 @@ import { translate as t, } from '../../../helpers/api-integration/v2'; -xdescribe('POST /groups/:id/removeMember', () => { +describe('POST /groups/:id/removeMember', () => { context('user is not member of the group', () => { it('returns an error'); }); diff --git a/test/api/v2/user/DELETE-user.test.js b/test/api/v2/user/DELETE-user.test.js index 1ba8dcfd9c..981349a9e1 100644 --- a/test/api/v2/user/DELETE-user.test.js +++ b/test/api/v2/user/DELETE-user.test.js @@ -10,7 +10,7 @@ import { } from 'lodash'; import Q from 'q'; -xdescribe('DELETE /user', () => { +describe('DELETE /user', () => { let user; beforeEach(async () => { diff --git a/test/api/v2/user/GET-user_tags.test.js b/test/api/v2/user/GET-user_tags.test.js index 08babe3a9f..fd2032dc96 100644 --- a/test/api/v2/user/GET-user_tags.test.js +++ b/test/api/v2/user/GET-user_tags.test.js @@ -2,7 +2,7 @@ import { generateUser, } from '../../../helpers/api-integration/v2'; -xdescribe('GET /user/tags', () => { +describe('GET /user/tags', () => { let user; beforeEach(async () => { diff --git a/test/api/v2/user/GET-user_tags_id.test.js b/test/api/v2/user/GET-user_tags_id.test.js index dd1394aac3..9c774c84b6 100644 --- a/test/api/v2/user/GET-user_tags_id.test.js +++ b/test/api/v2/user/GET-user_tags_id.test.js @@ -3,7 +3,7 @@ import { translate as t, } from '../../../helpers/api-integration/v2'; -xdescribe('GET /user/tags/id', () => { +describe('GET /user/tags/id', () => { let user; beforeEach(async () => { diff --git a/test/api/v2/user/batch-update/POST-user_batch-update.test.js b/test/api/v2/user/batch-update/POST-user_batch-update.test.js index 63dd8021f9..0b1f244ff7 100644 --- a/test/api/v2/user/batch-update/POST-user_batch-update.test.js +++ b/test/api/v2/user/batch-update/POST-user_batch-update.test.js @@ -5,7 +5,7 @@ import { import { each } from 'lodash'; -xdescribe('POST /user/batch-update', () => { +describe('POST /user/batch-update', () => { let user; beforeEach(async () => { diff --git a/website/src/controllers/api-v2/groups.js b/website/src/controllers/api-v2/groups.js index cb795f0612..eaeef5d881 100644 --- a/website/src/controllers/api-v2/groups.js +++ b/website/src/controllers/api-v2/groups.js @@ -12,6 +12,8 @@ var Q = require('q'); var utils = require('./../../libs/api-v2/utils'); var shared = require('../../../../common'); +import { removeFromArray } from '../../libs/api-v3/collectionManipulators'; + import { model as User, } from './../../models/user'; @@ -786,28 +788,35 @@ api.removeMember = function(req, res, next){ return res.status(401).json({err: "You cannot remove yourself!"}); } - if(_.contains(group.members, uuid)){ - var update = {$pull:{members:uuid}}; - if (group.quest && group.quest.leader === uuid) { - update['$set'] = { - quest: { key: null, leader: null } - }; - } else if(group.quest && group.quest.members){ - // remove member from quest - update['$unset'] = {}; - update['$unset']['quest.members.' + uuid] = ""; - } - update['$inc'] = {memberCount: -1}; - Group.update({_id:group._id},update, function(err, saved){ - if (err) return next(err); + User.findById(uuid, function(err, removedUser){ + if (err) return next(err); + let isMember = group._id === removedUser.party._id || _.contains(removedUser.guilds, group._id); + let isInvited = group._id === removedUser.invitations.party._id || !!_.find(removedUser.invitations.guilds, {id: group._id}); - User.findById(uuid, function(err, removedUser){ - if(err) return next(err); + if(isMember){ + var update = {}; + if (group.quest && group.quest.leader === uuid) { + update['$set'] = { + quest: { key: null, leader: null } + }; + } else if(group.quest && group.quest.members){ + // remove member from quest + update['$unset'] = {}; + update['$unset']['quest.members.' + uuid] = ""; + } + update['$inc'] = {memberCount: -1}; + Group.update({_id:group._id},update, function(err, saved){ + if (err) return next(err); sendMessage(removedUser); //Mark removed users messages as seen var update = {$unset:{}}; + if (group.type === 'guild') { + update.$pull = {guilds: group._id}; + } else { + update.$unset.party = true; + } update.$unset['newMessages.' + group._id] = ''; if (group.quest && group.quest.active && group.quest.leader === uuid) { update['$inc'] = {}; @@ -820,12 +829,8 @@ api.removeMember = function(req, res, next){ group = uuid = null; return res.sendStatus(204); }); - }); - }else if(_.contains(group.invites, uuid)){ - User.findById(uuid, function(err,invited){ - if(err) return next(err); - - var invitations = invited.invitations; + }else if(isInvited){ + var invitations = removedUser.invitations; if(group.type === 'guild'){ invitations.guilds.splice(_.indexOf(invitations.guilds, group._id), 1); }else{ @@ -834,11 +839,8 @@ api.removeMember = function(req, res, next){ async.series([ function(cb){ - invited.save(cb); + removedUser.save(cb); }, - function(cb){ - Group.update({_id:group._id},{$pull:{invites:uuid}}, cb); - } ], function(err, results){ if (err) return next(err); @@ -848,12 +850,11 @@ api.removeMember = function(req, res, next){ group = uuid = null; return res.sendStatus(204); }); - - }); - }else{ - group = uuid = null; - return res.status(400).json({err: "User not found among group's members!"}); - } + }else{ + group = uuid = null; + return res.status(400).json({err: "User not found among group's members!"}); + } + }); } // ------------------------------------ diff --git a/website/src/controllers/api-v2/user.js b/website/src/controllers/api-v2/user.js index e88318a03f..3ac3a116ab 100644 --- a/website/src/controllers/api-v2/user.js +++ b/website/src/controllers/api-v2/user.js @@ -2,11 +2,12 @@ var url = require('url'); var ipn = require('paypal-ipn'); var _ = require('lodash'); var nconf = require('nconf'); -var async = require('async'); +var asyncM = require('async'); var shared = require('../../../../common'); import { model as User, } from '../../models/user'; +import { model as Tag } from '../../models/tag'; import * as Tasks from '../../models/task'; import Q from 'q'; import {removeFromArray} from './../../libs/api-v3/collectionManipulators'; @@ -24,6 +25,8 @@ var logging = require('./../../libs/api-v2/logging'); var acceptablePUTPaths; let restrictedPUTSubPaths; +let i18n = shared.i18n; + var api = module.exports; var firebase = require('../../libs/api-v2/firebase'); var webhook = require('../../libs/api-v2/webhook'); @@ -121,7 +124,7 @@ api.score = function(req, res, next) { direction, }, req); - async.parallel({ + asyncM.parallel({ task: task.save.bind(task), user: user.save.bind(user) }, function(err, results){ @@ -405,38 +408,7 @@ api.update = (req, res, next) => { }); }; -api.cron = function(req, res, next) { - var user = res.locals.user, - progress = user.fns.cron({analytics:utils.analytics, timezoneOffset:req.headers['x-user-timezoneoffset']}), - ranCron = user.isModified(), - quest = shared.content.quests[user.party.quest.key]; - - if (ranCron) res.locals.wasModified = true; - if (!ranCron) return next(null,user); - Group.tavernBoss(user,progress); - if (!quest) return user.save(next); - - // If user is on a quest, roll for boss & player, or handle collections - // FIXME this saves user, runs db updates, loads user. Is there a better way to handle this? - async.waterfall([ - function(cb){ - user.save(cb); // make sure to save the cron effects - }, - function(saved, count, cb){ - var type = quest.boss ? 'boss' : 'collect'; - Group[type+'Quest'](user,progress,cb); - }, - function(){ - var cb = arguments[arguments.length-1]; - // User has been updated in boss-grapple, reload - User.findById(user._id, cb); - } - ], function(err, saved) { - res.locals.user = saved; - next(err,saved); - user = progress = quest = null; - }); -}; +api.cron = require('../../middlewares/api-v3/cron'); // api.reroll // Shared.ops // api.reset // Shared.ops @@ -508,84 +480,210 @@ if (nconf.get('NODE_ENV') === 'development') { Tags ------------------------------------------------------------------------ */ -// api.deleteTag // handled in Shared.ops -// api.addTag // handled in Shared.ops -// api.updateTag // handled in Shared.ops -// api.sortTag // handled in Shared.ops + +api.getTags = function (req, res, next) { + res.json(res.locals.user.tags.toObject().map(tag => { + return { + name: tag.name, + id: tag._id, + challenge: tag.challenge, + } + })); +}; + +api.getTag = function (req, res, next) { + let tag = res.locals.user.tags.id(req.params.id); + if (!tag) { + return res.status(404).json({err: i18n.t('messageTagNotFound', req.language)}); + } + + res.json({ + name: tag.name, + id: tag._id, + challenge: tag.challenge, + }); +}; + +api.addTag = function (req, res, next) { + let user = res.locals.user; + + user.tags.push(Tag.sanitize(req.body)); + user.save(function (err, user) { + if (err) return next(err); + + res.json(user.tags.toObject().map(tag => { + return { + name: tag.name, + id: tag._id, + challenge: tag.challenge, + } + })); + }); +}; + +api.updateTag = function (req, res, next) { + let user = res.locals.user; + + let tag = user.tags.id(req.params.id); + if (!tag) { + return res.status(404).json({err: i18n.t('messageTagNotFound', req.language)}); + } + + tag.name = req.body.tag; + user.save(function (err, user) { + if (err) return next(err); + + res.json({ + name: tag.name, + id: tag._id, + challenge: tag.challenge, + }); + }); +} + +api.sortTag = function (req, res, next) { + var ref = req.query; + var to = ref.to; + var from = ref.from; + let user = res.locals.user; + + if (!((to != null) && (from != null))) { + return res.statu(500).json('?to=__&from=__ are required'); + } + + user.tags.splice(to, 0, user.tags.splice(from, 1)[0]); + user.save(function (err, user) { + if (err) return next(err); + + res.json(user.tags.toObject().map(tag => { + return { + name: tag.name, + id: tag._id, + challenge: tag.challenge, + } + })); + }); +} + +api.deleteTag = function (req, res, next) { + let user = res.locals.user; + + let tag = user.tags.id(req.params.id); + if (!tag) { + return res.status(404).json({err: i18n.t('messageTagNotFound', req.language)}); + } + + tag.remove(); + + Tasks.Task.update({ + userId: user._id, + }, { + $pull: { + tags: tag._id, + }, + }, {multi: true}).exec(); + + user.save(function (err, user) { + if (err) return next(err); + + res.json(user.tags.toObject().map(tag => { + return { + name: tag.name, + id: tag._id, + challenge: tag.challenge, + } + })); + }); +} /* ------------------------------------------------------------------------ Spells ------------------------------------------------------------------------ */ -api.cast = function(req, res, next) { - var user = res.locals.user, - targetType = req.query.targetType, - targetId = req.query.targetId, - klass = shared.content.spells.special[req.params.spell] ? 'special' : user.stats.class, - spell = shared.content.spells[klass][req.params.spell]; +api.cast = async function(req, res, next) { + try { + let user = res.locals.user; + let spellId = req.params.spellId; + let targetId = req.query.targetId; - 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'}); + let klass = common.content.spells.special[spellId] ? 'special' : user.stats.class; + let spell = common.content.spells[klass][spellId]; - var done = function(){ - var err = arguments[0]; - var saved = _.size(arguments == 3) ? arguments[2] : arguments[1]; - if (err) return next(err); - res.json(saved); - user = targetType = targetId = klass = spell = null; - } + 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'}); - switch (targetType) { - case 'task': - if (!user.tasks[targetId]) return res.status(404).json({err: 'Task "' + targetId + '" not found.'}); - spell.cast(user, user.tasks[targetId]); - user.save(done); - break; + let targetType = spell.target; - case 'self': - spell.cast(user); - user.save(done); - break; + if (targetType === 'task') { + let task = await Tasks.Task.findOne({ + _id: targetId, + userId: user._id, + }).exec(); + if (!task) { + return res.status(404).json({err: 'Task "' + targetId + '" not found.'}); + } - case 'party': - case 'user': - async.waterfall([ - function(cb){ - Group.findOne({type: 'party', members: {'$in': [user._id]}}).populate('members', 'profile.name stats achievements items.special').exec(cb); - }, - function(group, cb) { - // Solo player? let's just create a faux group for simpler code - var g = group ? group : {members:[user]}; - var series = [], found; - if (targetType == 'party') { - spell.cast(user, g.members); - series = _.transform(g.members, function(m,v,k){ - m.push(function(cb2){v.save(cb2)}); - }); - } else { - found = _.find(g.members, {_id: targetId}) - spell.cast(user, found); - series.push(function(cb2){found.save(cb2)}); - } + spell.cast(user, task, req); + await task.save(); + } else if (targetType === 'self') { + spell.cast(user, null, req); + await user.save(); + } else if (targetType === 'tasks') { // new target type when all the user's tasks are necessary + let tasks = await Tasks.Task.find({ + userId: user._id, + 'challenge.id': {$exists: false}, // exclude challenge tasks + $or: [ // Exclude completed todos + {type: 'todo', completed: false}, + {type: {$in: ['habit', 'daily', 'reward']}}, + ], + }).exec(); - if (group && !spell.silent) { - series.push(function(cb2){ - var message = '`'+user.profile.name+' casts '+spell.text() + (targetType=='user' ? ' on '+found.profile.name : ' for the party')+'.`'; - group.sendChat(message); - group.save(cb2); - }) - } + spell.cast(user, tasks, req); - series.push(function(cb2){g = group = series = found = null;cb2();}) + let toSave = tasks.filter(t => t.isModified()); + let isUserModified = user.isModified(); + toSave.unshift(user.save()); + let saved = await Q.all(toSave); + } else if (targetType === 'party' || targetType === 'user') { + let party = await Group.getGroup({groupId: 'party', user}); + // arrays of users when targetType is 'party' otherwise single users + let partyMembers; - async.series(series, cb); - }, - function(whatever, cb){ - user.save(cb); + if (targetType === 'party') { + if (!party) { + partyMembers = [user]; // Act as solo party + } else { + partyMembers = await User.find({'party._id': party._id}).select(partyMembersFields).exec(); } - ], done); - break; + + spell.cast(user, partyMembers, req); + await Q.all(partyMembers.map(m => m.save())); + } else { + if (!party && (!targetId || user._id === targetId)) { + partyMembers = user; + } else { + partyMembers = await User.findOne({_id: targetId, 'party._id': party._id}).select(partyMembersFields).exec(); + } + + if (!partyMembers) throw new NotFound(res.t('userWithIDNotFound', {userId: targetId})); + spell.cast(user, partyMembers, req); + await partyMembers.save(); + } + + if (party && !spell.silent) { + let message = `\`${user.profile.name} casts ${spell.text()}${targetType === 'user' ? ` on ${partyMembers.profile.name}` : ' for the party'}.\``; + party.sendChat(message); + await party.save(); + } + } + + user.getTransformedData(function (err, transformedUser) { + if (err) next(err); + res.json(transformedUser); + }); + } catch (e) { + return res.status(500).json({err: 'An error happened'}); } } @@ -594,7 +692,7 @@ api.sessionPartyInvite = function(req,res,next){ if (!req.session.partyInvite) return next(); var inv = res.locals.user.invitations; if (inv.party && inv.party.id) return next(); // already invited to a party - async.waterfall([ + asyncM.waterfall([ function(cb){ Group.findOne({_id:req.session.partyInvite.id, members:{$in:[req.session.partyInvite.inviter]}}) .select('invites members type').exec(cb); @@ -646,6 +744,47 @@ api.clearCompleted = function(req, res, next) { }); }; +api.sortTask = async function (req, res, next) { + try { + let user = res.locals.user; + let to = Number(req.query.to); + + let task = await Tasks.Task.findOne({ + _id: req.params.id, + userId: user._id, + }).exec(); + + if (!task) return res.status(404).json(i18n.t('messageTaskNotFound', req.language)); + if (task.type !== 'todo' || !task.completed) { + let order = user.tasksOrder[`${task.type}s`]; + let currentIndex = order.indexOf(task._id); + + // If for some reason the task isn't ordered (should never happen), push it in the new position + // if the task is moved to a non existing position + // or if the task is moved to position -1 (push to bottom) + // -> push task at end of list + if (!order[to] && to !== -1) { + order.push(task._id); + } else { + if (currentIndex !== -1) order.splice(currentIndex, 1); + if (to === -1) { + order.push(task._id); + } else { + order.splice(to, 0, task._id); + } + } + await user.save(); + } + + user.getTasks(function (err, userTasks) { + if(err) return next(err); + res.json(userTasks); + }); + } catch (e) { + res.status(500).json({err: 'An error happened.'}); + } +} + 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)); @@ -660,7 +799,7 @@ api.deleteTask = function(req, res, next) { removeTaskFromOrder(user.tasksOrder[type]) }); - async.parallel({ + asyncM.parallel({ user: user.save.bind(user), task: function(cb) { Tasks.Task.remove({_id: id, userId: user._id}, cb); @@ -789,31 +928,35 @@ api.batchUpdate = function(req, res, next) { }); // call all the operations, then return the user object to the requester - async.waterfall(ops, function(err,_user) { + asyncM.waterfall(ops, function(err,_user) { res.json = oldJson; res.send = oldSend; if (err) return next(err); - var response = _user.toJSON(); - response.wasModified = res.locals.wasModified; - - user.fns.nullify(); - user = res.locals.user = oldSend = oldJson = oldSave = null; + var response; // return only drops & streaks - if (response._tmp && response._tmp.drop){ + if (_user._tmp && _user._tmp.drop){ + response = _user.toJSON(); res.status(200).json({_tmp: {drop: response._tmp.drop}, _v: response._v}); // Fetch full user object - } else if (response.wasModified){ + } else if (res.locals.wasModified){ // Preen 3-day past-completed To-Dos from Angular & mobile app - response.todos = shared.preenTodos(response.todos); - res.status(200).json(response); + _user.getTransformedData(function(err, transformedData){ + response = transformedData; + response.todos = shared.preenTodos(response.todos); + res.status(200).json(response); + }); // return only the version number } else{ + response = _user.toJSON(); res.status(200).json({_v: response._v}); } + + user.fns.nullify(); + user = res.locals.user = oldSend = oldJson = oldSave = null; }); }; diff --git a/website/src/controllers/api-v3/tags.js b/website/src/controllers/api-v3/tags.js index 36d96c7bb6..2d199fe06c 100644 --- a/website/src/controllers/api-v3/tags.js +++ b/website/src/controllers/api-v3/tags.js @@ -1,6 +1,7 @@ import { authWithHeaders } from '../../middlewares/api-v3/auth'; import cron from '../../middlewares/api-v3/cron'; import { model as Tag } from '../../models/tag'; +import { model as Tasks } from '../../models/task'; import { NotFound, } from '../../libs/api-v3/errors'; @@ -96,7 +97,6 @@ api.updateTag = { let user = res.locals.user; req.checkParams('tagId', res.t('tagIdRequired')).notEmpty().isUUID(); - // TODO check that req.body isn't empty let tagId = req.params.tagId; @@ -139,6 +139,15 @@ api.deleteTag = { if (!tag) throw new NotFound(res.t('tagNotFound')); tag.remove(); + // Remove from all the tasks TODO test + await Tasks.Task.update({ + userId: user._id, + }, { + $pull: { + tags: tag._id, + }, + }, {multi: true}).exec(); + await user.save(); res.respond(200, {}); }, diff --git a/website/src/controllers/api-v3/user.js b/website/src/controllers/api-v3/user.js index 0267e9511b..1f3ec4e0a0 100644 --- a/website/src/controllers/api-v3/user.js +++ b/website/src/controllers/api-v3/user.js @@ -373,7 +373,7 @@ api.castSpell = { let response = { tasks: isUserModified ? _.rest(saved) : saved, }; - if (isUserModified) res.user = user; + if (isUserModified) response.user = user; res.respond(200, response); } else if (targetType === 'party' || targetType === 'user') { let party = await Group.getGroup({groupId: 'party', user}); diff --git a/website/src/middlewares/api-v3/cron.js b/website/src/middlewares/api-v3/cron.js index 9baa503b9d..6b7d3de06e 100644 --- a/website/src/middlewares/api-v3/cron.js +++ b/website/src/middlewares/api-v3/cron.js @@ -26,7 +26,7 @@ let clearBuffs = { // For incomplete Dailys, deduct experience // Make sure to run this function once in a while as server will not take care of overnight calculations. // And you have to run it every time client connects. -export function cron (options = {}) { +function cron (options = {}) { let {user, tasksByType, analytics, now = new Date(), daysMissed, timezoneOffsetFromUserPrefs} = options; user.auth.timestamps.loggedin = now; @@ -271,7 +271,7 @@ export function cron (options = {}) { } // TODO check that it's used everywhere -module.exports = async function cronMiddleware (req, res, next) { +module.exports = function cronMiddleware (req, res, next) { let user = res.locals.user; let analytics = res.analytics; diff --git a/website/src/models/task.js b/website/src/models/task.js index 1a6d201037..3d296eb973 100644 --- a/website/src/models/task.js +++ b/website/src/models/task.js @@ -112,6 +112,14 @@ TaskSchema.methods.scoreChallengeTask = async function scoreChallengeTask (delta TaskSchema.methods.toJSONV2 = function toJSONV2 () { let toJSON = this.toJSON(); toJSON.id = toJSON._id; + + let v3Tags = this.tags; + + toJSON.tags = {}; + v3Tags.forEach(tag => { + toJSON.tags[tag] = true; + }); + return toJSON; }; diff --git a/website/src/models/user.js b/website/src/models/user.js index 3964dc839a..d6d529ca9e 100644 --- a/website/src/models/user.js +++ b/website/src/models/user.js @@ -753,6 +753,15 @@ 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.tags = obj.tags.map(tag => { + return { + id: tag._id, + name: tag.name, + challenge: tag.challenge, + }; + }); + let tasksOrder = obj.tasksOrder; // Saving a reference because we won't return it obj.habits = []; diff --git a/website/src/routes/api-v2/auth.js b/website/src/routes/api-v2/auth.js index 615eee8fb3..d4cad28c9e 100644 --- a/website/src/routes/api-v2/auth.js +++ b/website/src/routes/api-v2/auth.js @@ -2,17 +2,18 @@ var auth = require('../../controllers/api-v2/auth'); var express = require('express'); var i18n = require('../../libs/api-v2/i18n'); var router = express.Router(); +import getUserLanguage from '../../middlewares/api-v3/getUserLanguage'; /* auth.auth*/ // auth.setupPassport(router); //FIXME make this consistent with the others -router.post('/register', i18n.getUserLanguage, auth.registerUser); -router.post('/user/auth/local', i18n.getUserLanguage, auth.loginLocal); -router.post('/user/auth/social', i18n.getUserLanguage, auth.loginSocial); -router.delete('/user/auth/social', i18n.getUserLanguage, auth.auth, auth.deleteSocial); -router.post('/user/reset-password', i18n.getUserLanguage, auth.resetPassword); -router.post('/user/change-password', i18n.getUserLanguage, auth.auth, auth.changePassword); -router.post('/user/change-username', i18n.getUserLanguage, auth.auth, auth.changeUsername); -router.post('/user/change-email', i18n.getUserLanguage, auth.auth, auth.changeEmail); +router.post('/register', getUserLanguage, auth.registerUser); +router.post('/user/auth/local', getUserLanguage, auth.loginLocal); +router.post('/user/auth/social', getUserLanguage, auth.loginSocial); +router.delete('/user/auth/social', getUserLanguage, auth.auth, auth.deleteSocial); +router.post('/user/reset-password', getUserLanguage, auth.resetPassword); +router.post('/user/change-password', getUserLanguage, auth.auth, auth.changePassword); +router.post('/user/change-username', getUserLanguage, auth.auth, auth.changeUsername); +router.post('/user/change-email', getUserLanguage, auth.auth, auth.changeEmail); // router.post('/user/auth/firebase', i18n.getUserLanguage, auth.auth, auth.getFirebaseToken); module.exports = router; diff --git a/website/src/routes/api-v2/coupon.js b/website/src/routes/api-v2/coupon.js index 10c6ece15a..29fdd75312 100644 --- a/website/src/routes/api-v2/coupon.js +++ b/website/src/routes/api-v2/coupon.js @@ -4,9 +4,10 @@ var router = express.Router(); var auth = require('../../controllers/api-v2/auth'); var coupon = require('../../controllers/api-v2/coupon'); var i18n = require('../../libs/api-v2/i18n'); +import getUserLanguage from '../../middlewares/api-v3/getUserLanguage'; -router.get('/coupons', auth.authWithUrl, i18n.getUserLanguage, coupon.ensureAdmin, coupon.getCoupons); -router.post('/coupons/generate/:event', auth.auth, i18n.getUserLanguage, coupon.ensureAdmin, coupon.generateCoupons); -router.post('/user/coupon/:code', auth.auth, i18n.getUserLanguage, coupon.enterCode); +router.get('/coupons', auth.authWithUrl, getUserLanguage, coupon.ensureAdmin, coupon.getCoupons); +router.post('/coupons/generate/:event', auth.auth, getUserLanguage, coupon.ensureAdmin, coupon.generateCoupons); +router.post('/user/coupon/:code', auth.auth, getUserLanguage, coupon.enterCode); module.exports = router; diff --git a/website/src/routes/api-v2/swagger.js b/website/src/routes/api-v2/swagger.js index fc94bdd9ed..4912bbd70b 100644 --- a/website/src/routes/api-v2/swagger.js +++ b/website/src/routes/api-v2/swagger.js @@ -19,6 +19,7 @@ var cron = user.cron; var _ = require('lodash'); var content = require('../../../../common').content; var i18n = require('../../libs/api-v2/i18n'); +import getUserLanguage from '../../middlewares/api-v3/getUserLanguage'; var forceRefresh = require('../../middlewares/forceRefresh').middleware; module.exports = function(swagger, v2) { @@ -60,7 +61,7 @@ module.exports = function(swagger, v2) { description: "Export user history", method: 'GET' }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: dataexport.history }, "/user/tasks/{id}/{direction}": { @@ -134,7 +135,7 @@ module.exports = function(swagger, v2) { description: 'Unlink a task from its challenge', parameters: [path("id", "Task ID", "string"), query('keep', "When unlinking a challenge task, how to handle the orphans?", 'string', ['keep', 'keep-all', 'remove', 'remove-all'])] }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: challenges.unlink }, "/user/inventory/buy": { @@ -235,7 +236,7 @@ module.exports = function(swagger, v2) { method: 'DELETE', description: "Delete a user object entirely, USE WITH CAUTION!" }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: user["delete"] }, "/user/revive": { @@ -311,7 +312,7 @@ module.exports = function(swagger, v2) { description: "This is an advanced route which is useful for apps which might for example need offline support. You can send a whole batch of user-based operations, which allows you to queue them up offline and send them all at once. The format is {op:'nameOfOperation',parameters:{},body:{},query:{}}", parameters: [body('', 'The array of batch-operations to perform', 'object')] }, - middleware: [forceRefresh, auth.auth, i18n.getUserLanguage, cron, user.sessionPartyInvite], + middleware: [forceRefresh, auth.auth, getUserLanguage, cron, user.sessionPartyInvite], action: user.batchUpdate }, "/user/tags/{id}:GET": { @@ -406,7 +407,7 @@ module.exports = function(swagger, v2) { description: "Get a list of groups", parameters: [query('type', "Comma-separated types of groups to return, eg 'party,guilds,public,tavern'", 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: groups.list }, "/groups:POST": { @@ -416,7 +417,7 @@ module.exports = function(swagger, v2) { description: 'Create a group', parameters: [body('', 'Group object (see GroupSchema)', 'object')] }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: groups.create }, "/groups/{gid}:GET": { @@ -425,7 +426,7 @@ module.exports = function(swagger, v2) { description: "Get a group. The party the user currently is in can be accessed with the gid 'party'.", parameters: [path('gid', 'Group ID', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: groups.get }, "/groups/{gid}:POST": { @@ -435,7 +436,7 @@ module.exports = function(swagger, v2) { description: "Edit a group", parameters: [body('', 'Group object (see GroupSchema)', 'object')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.update }, "/groups/{gid}/join": { @@ -444,7 +445,7 @@ module.exports = function(swagger, v2) { description: 'Join a group', parameters: [path('gid', 'Id of the group to join', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.join }, "/groups/{gid}/leave": { @@ -453,7 +454,7 @@ module.exports = function(swagger, v2) { description: 'Leave a group', parameters: [path('gid', 'ID of the group to leave', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.leave }, "/groups/{gid}/invite": { @@ -462,7 +463,7 @@ module.exports = function(swagger, v2) { description: "Invite a user to a group", parameters: [path('gid', 'Group id', 'string'), body('', 'a payload of invites either under body.uuids or body.emails, only one of them!', 'object')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.invite }, "/groups/{gid}/removeMember": { @@ -471,7 +472,7 @@ module.exports = function(swagger, v2) { description: "Remove / boot a member from a group", parameters: [path('gid', 'Group id', 'string'), query('uuid', 'User id to boot', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.removeMember }, "/groups/{gid}/questAccept": { @@ -480,7 +481,7 @@ module.exports = function(swagger, v2) { description: "Accept a quest invitation", parameters: [path('gid', "Group id", 'string'), query('key', "optional. if provided, trigger new invite, if not, accept existing invite", 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.questAccept }, "/groups/{gid}/questReject": { @@ -489,7 +490,7 @@ module.exports = function(swagger, v2) { description: 'Reject quest invitation', parameters: [path('gid', 'Group id', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.questReject }, "/groups/{gid}/questCancel": { @@ -498,7 +499,7 @@ module.exports = function(swagger, v2) { description: 'Cancel quest before it starts (in invitation stage)', parameters: [path('gid', 'Group to cancel quest in', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.questCancel }, "/groups/{gid}/questAbort": { @@ -507,7 +508,7 @@ module.exports = function(swagger, v2) { description: 'Abort quest after it has started (all progress will be lost)', parameters: [path('gid', 'Group to abort quest in', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.questAbort }, "/groups/{gid}/questLeave": { @@ -516,7 +517,7 @@ module.exports = function(swagger, v2) { description: 'Leave an active quest (Quest leaders cannot leave active quests. They must abort the quest to leave)', parameters: [path('gid', 'Group to leave quest in', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.questLeave }, "/groups/{gid}/chat:GET": { @@ -525,7 +526,7 @@ module.exports = function(swagger, v2) { description: "Get all chat messages", parameters: [path('gid', 'Group to return the chat from ', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.getChat }, "/groups/{gid}/chat:POST": { @@ -535,7 +536,7 @@ module.exports = function(swagger, v2) { description: "Send a chat message", parameters: [query('message', 'Chat message', 'string'), path('gid', 'Group id', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.postChat }, "/groups/{gid}/chat/seen": { @@ -552,7 +553,7 @@ module.exports = function(swagger, v2) { description: 'Delete a chat message in a given group', parameters: [path('gid', 'ID of the group containing the message to be deleted', 'string'), path('messageId', 'ID of message to be deleted', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.deleteChatMessage }, "/groups/{gid}/chat/{mid}/like": { @@ -561,7 +562,7 @@ module.exports = function(swagger, v2) { description: "Like a chat message", parameters: [path('gid', 'Group id', 'string'), path('mid', 'Message id', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.likeChatMessage }, "/groups/{gid}/chat/{mid}/flag": { @@ -570,7 +571,7 @@ module.exports = function(swagger, v2) { description: "Flag a chat message", parameters: [path('gid', 'Group id', 'string'), path('mid', 'Message id', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.flagChatMessage }, "/groups/{gid}/chat/{mid}/clearflags": { @@ -579,7 +580,7 @@ module.exports = function(swagger, v2) { description: "Clear flag count from message and unhide it", parameters: [path('gid', 'Group id', 'string'), path('mid', 'Message id', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup], + middleware: [auth.auth, getUserLanguage, groups.attachGroup], action: groups.clearFlagCount }, "/members/{uuid}:GET": { @@ -588,7 +589,7 @@ module.exports = function(swagger, v2) { description: "Get a member.", parameters: [path('uuid', 'Member ID', 'string')] }, - middleware: [i18n.getUserLanguage], + middleware: [getUserLanguage], action: members.getMember }, "/members/{uuid}/message": { @@ -620,14 +621,14 @@ module.exports = function(swagger, v2) { }, "/hall/heroes": { spec: {}, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: hall.getHeroes }, "/hall/heroes/{uid}:GET": { spec: { path: "/hall/heroes/{uid}" }, - middleware: [auth.auth, i18n.getUserLanguage, hall.ensureAdmin], + middleware: [auth.auth, getUserLanguage, hall.ensureAdmin], action: hall.getHero }, "/hall/heroes/{uid}:POST": { @@ -635,14 +636,14 @@ module.exports = function(swagger, v2) { method: 'POST', path: "/hall/heroes/{uid}" }, - middleware: [auth.auth, i18n.getUserLanguage, hall.ensureAdmin], + middleware: [auth.auth, getUserLanguage, hall.ensureAdmin], action: hall.updateHero }, "/hall/patrons": { spec: { parameters: [query('page', 'Page number to fetch (this list is long)', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: hall.getPatrons }, "/challenges:GET": { @@ -650,7 +651,7 @@ module.exports = function(swagger, v2) { path: '/challenges', description: "Get a list of challenges" }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: challenges.list }, "/challenges:POST": { @@ -660,7 +661,7 @@ module.exports = function(swagger, v2) { description: "Create a challenge", parameters: [body('', 'Challenge object (see ChallengeSchema)', 'object')] }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: challenges.create }, "/challenges/{cid}:GET": { @@ -669,7 +670,7 @@ module.exports = function(swagger, v2) { description: 'Get a challenge', parameters: [path('cid', 'Challenge id', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: challenges.get }, "/challenges/{cid}/csv": { @@ -686,7 +687,7 @@ module.exports = function(swagger, v2) { description: "Update a challenge", parameters: [path('cid', 'Challenge id', 'string'), body('', 'Challenge object (see ChallengeSchema)', 'object')] }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: challenges.update }, "/challenges/{cid}:DELETE": { @@ -696,7 +697,7 @@ module.exports = function(swagger, v2) { description: "Delete a challenge", parameters: [path('cid', 'Challenge id', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: challenges["delete"] }, "/challenges/{cid}/close": { @@ -705,7 +706,7 @@ module.exports = function(swagger, v2) { description: 'Close a challenge', parameters: [path('cid', 'Challenge id', 'string'), query('uid', 'User ID of the winner', 'string', true)] }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: challenges.selectWinner }, "/challenges/{cid}/join": { @@ -714,7 +715,7 @@ module.exports = function(swagger, v2) { description: "Join a challenge", parameters: [path('cid', 'Challenge id', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: challenges.join }, "/challenges/{cid}/leave": { @@ -723,7 +724,7 @@ module.exports = function(swagger, v2) { description: 'Leave a challenge', parameters: [path('cid', 'Challenge id', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: challenges.leave }, "/challenges/{cid}/member/{uid}": { @@ -731,7 +732,7 @@ module.exports = function(swagger, v2) { description: "Get a member's progress in a particular challenge", parameters: [path('cid', 'Challenge id', 'string'), path('uid', 'User id', 'string')] }, - middleware: [auth.auth, i18n.getUserLanguage], + middleware: [auth.auth, getUserLanguage], action: challenges.getMember } }; @@ -765,7 +766,7 @@ module.exports = function(swagger, v2) { method: 'GET' }); if (route.middleware == null) { - route.middleware = path.indexOf('/user') === 0 ? [auth.auth, i18n.getUserLanguage, cron] : [i18n.getUserLanguage]; + route.middleware = path.indexOf('/user') === 0 ? [auth.auth, getUserLanguage, cron] : [i18n.getUserLanguage]; } swagger["add" + route.spec.method](route); return true; diff --git a/website/src/routes/api-v2/unsubscription.js b/website/src/routes/api-v2/unsubscription.js index 832980daf9..08393edb79 100644 --- a/website/src/routes/api-v2/unsubscription.js +++ b/website/src/routes/api-v2/unsubscription.js @@ -2,7 +2,8 @@ var express = require('express'); var router = express.Router(); var i18n = require('../../libs/api-v2/i18n'); var unsubscription = require('../../controllers/api-v2/unsubscription'); +import getUserLanguage from '../../middlewares/api-v3/getUserLanguage'; -router.get('/unsubscribe', i18n.getUserLanguage, unsubscription.unsubscribe); +router.get('/unsubscribe', getUserLanguage, unsubscription.unsubscribe); module.exports = router; diff --git a/website/src/routes/payments.js b/website/src/routes/payments.js index 4733deb4dc..7b7f538eb8 100644 --- a/website/src/routes/payments.js +++ b/website/src/routes/payments.js @@ -4,28 +4,29 @@ var router = express.Router(); var auth = require('../controllers/api-v2/auth'); var payments = require('../controllers/payments'); var i18n = require('../libs/api-v2/i18n'); +import getUserLanguage from '../../middlewares/api-v3/getUserLanguage'; -router.get('/paypal/checkout', auth.authWithUrl, i18n.getUserLanguage, payments.paypalCheckout); -router.get('/paypal/checkout/success', i18n.getUserLanguage, payments.paypalCheckoutSuccess); -router.get('/paypal/subscribe', auth.authWithUrl, i18n.getUserLanguage, payments.paypalSubscribe); -router.get('/paypal/subscribe/success', i18n.getUserLanguage, payments.paypalSubscribeSuccess); -router.get('/paypal/subscribe/cancel', auth.authWithUrl, i18n.getUserLanguage, payments.paypalSubscribeCancel); -router.post('/paypal/ipn', i18n.getUserLanguage, payments.paypalIPN); // misc ipn handling +router.get('/paypal/checkout', auth.authWithUrl, getUserLanguage, payments.paypalCheckout); +router.get('/paypal/checkout/success', getUserLanguage, payments.paypalCheckoutSuccess); +router.get('/paypal/subscribe', auth.authWithUrl, getUserLanguage, payments.paypalSubscribe); +router.get('/paypal/subscribe/success', getUserLanguage, payments.paypalSubscribeSuccess); +router.get('/paypal/subscribe/cancel', auth.authWithUrl, getUserLanguage, payments.paypalSubscribeCancel); +router.post('/paypal/ipn', getUserLanguage, payments.paypalIPN); // misc ipn handling -router.post('/stripe/checkout', auth.auth, i18n.getUserLanguage, payments.stripeCheckout); -router.post('/stripe/subscribe/edit', auth.auth, i18n.getUserLanguage, payments.stripeSubscribeEdit); -//router.get('/stripe/subscribe', auth.authWithUrl, i18n.getUserLanguage, payments.stripeSubscribe); // checkout route is used (above) with ?plan= instead -router.get('/stripe/subscribe/cancel', auth.authWithUrl, i18n.getUserLanguage, payments.stripeSubscribeCancel); +router.post('/stripe/checkout', auth.auth, getUserLanguage, payments.stripeCheckout); +router.post('/stripe/subscribe/edit', auth.auth, getUserLanguage, payments.stripeSubscribeEdit); +//router.get('/stripe/subscribe', auth.authWithUrl, getUserLanguage, payments.stripeSubscribe); // checkout route is used (above) with ?plan= instead +router.get('/stripe/subscribe/cancel', auth.authWithUrl, getUserLanguage, payments.stripeSubscribeCancel); -router.post('/amazon/verifyAccessToken', auth.auth, i18n.getUserLanguage, payments.amazonVerifyAccessToken); -router.post('/amazon/createOrderReferenceId', auth.auth, i18n.getUserLanguage, payments.amazonCreateOrderReferenceId); -router.post('/amazon/checkout', auth.auth, i18n.getUserLanguage, payments.amazonCheckout); -router.post('/amazon/subscribe', auth.auth, i18n.getUserLanguage, payments.amazonSubscribe); -router.get('/amazon/subscribe/cancel', auth.authWithUrl, i18n.getUserLanguage, payments.amazonSubscribeCancel); +router.post('/amazon/verifyAccessToken', auth.auth, getUserLanguage, payments.amazonVerifyAccessToken); +router.post('/amazon/createOrderReferenceId', auth.auth, getUserLanguage, payments.amazonCreateOrderReferenceId); +router.post('/amazon/checkout', auth.auth, getUserLanguage, payments.amazonCheckout); +router.post('/amazon/subscribe', auth.auth, getUserLanguage, payments.amazonSubscribe); +router.get('/amazon/subscribe/cancel', auth.authWithUrl, getUserLanguage, payments.amazonSubscribeCancel); -router.post('/iap/android/verify', auth.authWithUrl, /*i18n.getUserLanguage, */payments.iapAndroidVerify); -router.post('/iap/ios/verify', auth.auth, /*i18n.getUserLanguage, */ payments.iapIosVerify); +router.post('/iap/android/verify', auth.authWithUrl, /*getUserLanguage, */payments.iapAndroidVerify); +router.post('/iap/ios/verify', auth.auth, /*getUserLanguage, */ payments.iapIosVerify); -router.get('/api/v2/coupons/valid-discount/:code', /*auth.authWithUrl, i18n.getUserLanguage, */ payments.validCoupon); +router.get('/api/v2/coupons/valid-discount/:code', /*auth.authWithUrl, getUserLanguage, */ payments.validCoupon); module.exports = router;