mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-19 07:37:25 +01:00
port create challenge
This commit is contained in:
@@ -38,5 +38,8 @@
|
|||||||
"groupMemberNotFound": "User not found among group's members",
|
"groupMemberNotFound": "User not found among group's members",
|
||||||
"keepOrRemoveAll": "req.query.keep must be either \"keep-all\" or \"remove-all\"",
|
"keepOrRemoveAll": "req.query.keep must be either \"keep-all\" or \"remove-all\"",
|
||||||
"canOnlyInviteEmailUuid": "Can only invite using uuids or emails but not both at the same time.",
|
"canOnlyInviteEmailUuid": "Can only invite using uuids or emails but not both at the same time.",
|
||||||
"inviteMissingEmail": "Missing email address in invite."
|
"inviteMissingEmail": "Missing email address in invite.",
|
||||||
|
"onlyGroupLeaderChal": "Only the group leader can create challenges",
|
||||||
|
"pubChalsMinPrize": "Prize must be at least 1 Gem for public challenges.",
|
||||||
|
"cantAfford": "You can't afford this prize. Purchase more gems or lower the prize amount."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,101 @@
|
|||||||
import { authWithHeaders } from '../../middlewares/api-v3/auth';
|
import { authWithHeaders } from '../../middlewares/api-v3/auth';
|
||||||
import cron from '../../middlewares/api-v3/cron';
|
import cron from '../../middlewares/api-v3/cron';
|
||||||
import { model as Challenge } from '../../models/challenge';
|
import { model as Challenge } from '../../models/challenge';
|
||||||
|
import { model as Group } from '../../models/group';
|
||||||
|
import {
|
||||||
|
NotFound,
|
||||||
|
NotAuthorized,
|
||||||
|
} from '../../libs/api-v3/errors';
|
||||||
|
import * as Tasks from './task';
|
||||||
|
import Q from 'q';
|
||||||
|
|
||||||
let api = {};
|
let api = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api {post} /challenges Create a new challenge
|
||||||
|
* @apiVersion 3.0.0
|
||||||
|
* @apiName CreateChallenge
|
||||||
|
* @apiGroup Challenge
|
||||||
|
*
|
||||||
|
* @apiSuccess {object} challenge The newly created challenge
|
||||||
|
*/
|
||||||
|
api.getChallenges = {
|
||||||
|
method: 'POST',
|
||||||
|
url: '/challenges',
|
||||||
|
middlewares: [authWithHeaders(), cron],
|
||||||
|
handler (req, res, next) {
|
||||||
|
let user = res.locals.user;
|
||||||
|
|
||||||
|
req.checkBody('group', res.t('groupIdRequired')).notEmpty();
|
||||||
|
|
||||||
|
let validationErrors = req.validationErrors();
|
||||||
|
if (validationErrors) return next(validationErrors);
|
||||||
|
|
||||||
|
let groupId = req.body.group;
|
||||||
|
let prize = req.body.prize;
|
||||||
|
|
||||||
|
Group.getGroup(user, groupId, '-chat')
|
||||||
|
.then(group => {
|
||||||
|
if (!group) throw new NotFound(res.t('groupNotFound'));
|
||||||
|
|
||||||
|
if (group.leaderOnly && group.leaderOnly.challenges && group.leader !== user._id) {
|
||||||
|
throw new NotAuthorized(res.t('onlyGroupLeaderChal'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groupId === 'habitrpg' && prize < 1) {
|
||||||
|
throw new NotAuthorized(res.t('pubChalsMinPrize'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prize > 0) {
|
||||||
|
let groupBalance = group.balance && group.leader === user._id ? group.balance : 0;
|
||||||
|
let prizeCost = prize / 4;
|
||||||
|
|
||||||
|
if (prizeCost > user.balance + groupBalance) {
|
||||||
|
throw new NotAuthorized(res.t('cantAfford'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (groupBalance >= prizeCost) {
|
||||||
|
// Group pays for all of prize
|
||||||
|
group.balance -= prizeCost;
|
||||||
|
} else if (groupBalance > 0) {
|
||||||
|
// User pays remainder of prize cost after group
|
||||||
|
let remainder = prizeCost - group.balance;
|
||||||
|
group.balance = 0;
|
||||||
|
user.balance -= remainder;
|
||||||
|
} else {
|
||||||
|
// User pays for all of prize
|
||||||
|
user.balance -= prizeCost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let tasks = req.body.tasks || []; // TODO validate
|
||||||
|
req.body.leader = user._id;
|
||||||
|
req.body.official = user.contributor.admin && req.body.official;
|
||||||
|
let challenge = new Challenge(Challenge.sanitize(req.body));
|
||||||
|
|
||||||
|
let toSave = tasks.map(tasks, taskToCreate => {
|
||||||
|
// TODO validate type
|
||||||
|
let task = new Tasks[taskToCreate.type](Tasks.Task.sanitizeCreate(taskToCreate));
|
||||||
|
task.challenge.id = challenge._id;
|
||||||
|
challenge.tasksOrder[`${task.type}s`].push(task._id);
|
||||||
|
return task.save();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
toSave.unshift(challenge, group);
|
||||||
|
return Q.all(toSave);
|
||||||
|
})
|
||||||
|
.then(results => {
|
||||||
|
let savedChal = results[0];
|
||||||
|
|
||||||
|
user.challenges.push(savedChal._id); // TODO save user only after group created, so that we can account for failed validation. Revisit in other places
|
||||||
|
return savedChal.syncToUser(user) // (it also saves the user)
|
||||||
|
.then(() => res.respond(201, savedChal));
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {get} /challenges Get challenges for a user
|
* @api {get} /challenges Get challenges for a user
|
||||||
* @apiVersion 3.0.0
|
* @apiVersion 3.0.0
|
||||||
|
|||||||
@@ -22,18 +22,11 @@ let schema = new Schema({
|
|||||||
group: {type: String, ref: 'Group', validate: [validator.isUUID, 'Invalid uuid.'], required: true},
|
group: {type: String, ref: 'Group', validate: [validator.isUUID, 'Invalid uuid.'], required: true},
|
||||||
timestamp: {type: Date, default: Date.now, required: true}, // TODO what is this? use timestamps from plugin?
|
timestamp: {type: Date, default: Date.now, required: true}, // TODO what is this? use timestamps from plugin?
|
||||||
memberCount: {type: Number, default: 0},
|
memberCount: {type: Number, default: 0},
|
||||||
prize: {type: Number, default: 0, required: true},
|
prize: {type: Number, default: 0, min: 0},
|
||||||
});
|
});
|
||||||
|
|
||||||
schema.plugin(baseModel, {
|
schema.plugin(baseModel, {
|
||||||
noSet: ['_id', 'memberCount', 'tasksOrder'],
|
noSet: ['_id', 'memberCount', 'tasksOrder'],
|
||||||
toJSONTransform: function userToJSON (doc) {
|
|
||||||
// TODO fixme
|
|
||||||
// TODO this works?
|
|
||||||
doc._isMember = this._isMember;
|
|
||||||
|
|
||||||
return doc;
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user