v3: port coupons
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
import csvStringify from '../../libs/api-v3/csvStringify';
|
||||
import {
|
||||
authWithHeaders,
|
||||
authWithSession,
|
||||
} from '../../middlewares/api-v3/auth';
|
||||
import cron from '../../middlewares/api-v3/cron';
|
||||
import { ensureSudo } from '../../middlewares/api-v3/ensureAccessRight';
|
||||
import { model as Coupon } from '../../models/coupon';
|
||||
import _ from 'lodash';
|
||||
import couponCode from 'coupon-code';
|
||||
|
||||
let api = {};
|
||||
|
||||
/**
|
||||
* @api {get} /coupons Get coupons (sudo users only)
|
||||
* @apiVersion 3.0.0
|
||||
* @apiName GetCoupons
|
||||
* @apiGroup Coupon
|
||||
*
|
||||
* @apiSuccess string Coupons in CSV format
|
||||
*/
|
||||
api.getCoupons = {
|
||||
method: 'GET',
|
||||
url: '/coupons',
|
||||
middlewares: [authWithSession, cron, ensureSudo],
|
||||
async handler (req, res) {
|
||||
let coupons = await Coupon.find().sort('createdAt').lean().exec();
|
||||
|
||||
let output = [['code', 'event', 'date', 'user']].concat(_.map(coupons, coupon => {
|
||||
return [coupon._id, coupon.event, coupon.createdAt, coupon.user];
|
||||
}));
|
||||
let csv = await csvStringify(output);
|
||||
|
||||
res.set({
|
||||
'Content-Type': 'text/csv',
|
||||
'Content-disposition': `attachment; filename=habitica-coupons.csv`,
|
||||
});
|
||||
res.status(200).send(csv);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @api {post} /coupons/generate/:event Generate coupons for an event (sudo users only)
|
||||
* @apiVersion 3.0.0
|
||||
* @apiName GenerateCoupons
|
||||
* @apiGroup Coupon
|
||||
*
|
||||
* @apiParam {string} event The event for which the coupon should be generated
|
||||
* @apiParam {number} count Query parameter to specify the number of coupon codes to generate
|
||||
*
|
||||
* @apiSuccess array Generated coupons
|
||||
*/
|
||||
api.generateCoupons = {
|
||||
method: 'POST',
|
||||
url: '/coupons/generate/:event',
|
||||
middlewares: [authWithHeaders(), cron, ensureSudo],
|
||||
async handler (req, res) {
|
||||
req.checkParams('event', res.t('eventRequired')).notEmpty();
|
||||
req.checkQuery('count', res.t('countRequired')).notEmpty().isNumeric();
|
||||
|
||||
let validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
|
||||
let coupons = await Coupon.generate(req.params.event, req.query.count);
|
||||
res.respond(200, coupons);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @api {post} /user/coupon/:code Enter coupon code
|
||||
* @apiVersion 3.0.0
|
||||
* @apiName EnterCouponCode
|
||||
* @apiGroup Coupon
|
||||
*
|
||||
* @apiParam {string} code The coupon code to apply
|
||||
*
|
||||
* @apiSuccess object User object
|
||||
*/
|
||||
api.enterCouponCode = {
|
||||
method: 'POST',
|
||||
url: '/coupons/enter/:code',
|
||||
middlewares: [authWithHeaders(), cron],
|
||||
async handler (req, res) {
|
||||
let user = res.locals.user;
|
||||
|
||||
req.checkParams('code', res.t('couponCodeRequired')).notEmpty();
|
||||
|
||||
let validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
|
||||
await Coupon.apply(user, req, req.params.code);
|
||||
res.respond(200, user);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @api {post} /coupons/validate/:code Validate a coupon code
|
||||
* @apiVersion 3.0.0
|
||||
* @apiName ValidateCoupon
|
||||
* @apiGroup Coupon
|
||||
*
|
||||
* @apiSuccess valid {boolean} true or false
|
||||
*/
|
||||
api.validateCoupon = {
|
||||
method: 'POST',
|
||||
url: '/coupons/validate/:code',
|
||||
middlewares: [authWithHeaders(true)],
|
||||
async handler (req, res) {
|
||||
req.checkParams('code', res.t('couponCodeRequired')).notEmpty();
|
||||
|
||||
let validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
|
||||
let valid = false;
|
||||
let code = couponCode.validate(req.params.code);
|
||||
if (code) {
|
||||
let coupon = await Coupon.findOne({_id: code}).exec();
|
||||
valid = coupon ? true : false;
|
||||
}
|
||||
|
||||
res.respond(200, {valid});
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = api;
|
||||
@@ -1,9 +1,9 @@
|
||||
import { authWithHeaders } from '../../middlewares/api-v3/auth';
|
||||
import { ensureAdmin } from '../../middlewares/api-v3/ensureAccessRight';
|
||||
import cron from '../../middlewares/api-v3/cron';
|
||||
import { model as User } from '../../models/user';
|
||||
import {
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
} from '../../libs/api-v3/errors';
|
||||
import _ from 'lodash';
|
||||
|
||||
@@ -90,9 +90,8 @@ const heroAdminFields = 'contributor balance profile.name purchased items auth';
|
||||
api.getHero = {
|
||||
method: 'GET',
|
||||
url: '/hall/heroes/:heroId',
|
||||
middlewares: [authWithHeaders(), cron],
|
||||
middlewares: [authWithHeaders(), cron, ensureAdmin],
|
||||
async handler (req, res) {
|
||||
let user = res.locals.user;
|
||||
let heroId = req.params.heroId;
|
||||
|
||||
req.checkParams('heroId', res.t('heroIdRequired')).notEmpty().isUUID();
|
||||
@@ -100,10 +99,6 @@ api.getHero = {
|
||||
let validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
|
||||
if (!user.contributor.admin) {
|
||||
throw new NotAuthorized(res.t('noAdminAccess'));
|
||||
}
|
||||
|
||||
let hero = await User
|
||||
.findById(heroId)
|
||||
.select(heroAdminFields)
|
||||
@@ -132,9 +127,8 @@ const gemsPerTier = {1: 3, 2: 3, 3: 3, 4: 4, 5: 4, 6: 4, 7: 4, 8: 0, 9: 0};
|
||||
api.updateHero = {
|
||||
method: 'PUT',
|
||||
url: '/hall/heroes/:heroId',
|
||||
middlewares: [authWithHeaders(), cron],
|
||||
middlewares: [authWithHeaders(), cron, ensureAdmin],
|
||||
async handler (req, res) {
|
||||
let user = res.locals.user;
|
||||
let heroId = req.params.heroId;
|
||||
let updateData = req.body;
|
||||
|
||||
@@ -143,10 +137,6 @@ api.updateHero = {
|
||||
let validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
|
||||
if (!user.contributor.admin) {
|
||||
throw new NotAuthorized(res.t('noAdminAccess'));
|
||||
}
|
||||
|
||||
let hero = await User.findById(heroId).exec();
|
||||
if (!hero) throw new NotFound(res.t('userWithIDNotFound', {userId: heroId}));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user