diff --git a/configs/game.json b/configs/game.json deleted file mode 100644 index e69de29..0000000 diff --git a/src/common/Utils.ts b/src/common/Utils.ts new file mode 100644 index 0000000..ca1e4b9 --- /dev/null +++ b/src/common/Utils.ts @@ -0,0 +1,9 @@ +export const isObjectIdString = (str: string) => { + return /^[0-9a-fA-F]{24}$/.test(str) +} + +// check if a string is a valid share code +// alphabet:'3fBCM8j17XNA9xYun4wmLWep2oHFlhPcgyEJskqOz6GK0UtV5ZRaDSvrTbidQI' +export const isValidShareCode = (str: string) => { + return /^[3fBCM8j17XNA9xYun4wmLWep2oHFlhPcgyEJskqOz6GK0UtV5ZRaDSvrTbidQI]{10}$/.test(str) +} diff --git a/src/controllers/activity.controller.ts b/src/controllers/activity.controller.ts index cbb5aae..0430794 100644 --- a/src/controllers/activity.controller.ts +++ b/src/controllers/activity.controller.ts @@ -6,6 +6,7 @@ import { ScoreRecord } from 'models/ScoreRecord' import { formatAddress } from 'zutils/utils/chain.util' import { formatDate } from 'zutils/utils/date.util' import { SCORE_INVITE_INVITEE, SCORE_INVITE_USER } from 'common/Constants' +import { isValidShareCode } from 'common/Utils' const shareCfg = require('../../configs/share_cfg.json') const MAX_LIMIT = 100 @@ -33,6 +34,9 @@ export default class ActivityController extends BaseController { async uploadInviteCode(req) { new SyncLocker().checkLock(req) let { code } = req.params + if (!isValidShareCode(code)) { + throw new ZError(11, 'invalid invite code') + } let user = req.user if (user.inviteUser) { throw new ZError(11, 'invite user already set') diff --git a/src/controllers/chest.controller.ts b/src/controllers/chest.controller.ts index 61fb8c4..3ecc530 100644 --- a/src/controllers/chest.controller.ts +++ b/src/controllers/chest.controller.ts @@ -8,6 +8,7 @@ import { ChestRecord } from 'models/chain/ChestRecord' import { generateNewChest } from 'services/game.svr' import { SCORE_OPEN_CHEST } from 'common/Constants' import { formatAddress } from 'zutils/utils/chain.util' +import { isObjectIdString, isValidShareCode } from 'common/Utils' /** * 宝箱相关接口 @@ -45,8 +46,8 @@ class BoxController extends BaseController { const user = req.user let { chestId, chestid } = req.params chestid = chestId || chestid - if (!chestid) { - throw new ZError(11, 'chestId is required') + if (!isObjectIdString(chestid)) { + throw new ZError(11, 'must provide valid chestid') } const chest = await ActivityChest.findById(chestid) if (!chest) { @@ -84,20 +85,26 @@ class BoxController extends BaseController { const { code } = req.params const user = req.user const uid = user.id + if (!isValidShareCode(code)) { + throw new ZError(11, 'invalid share code') + } // TODO:: 待规则确定后, 检查用户是否符合助力条件 const chest = await ActivityChest.findOne({ shareCode: code, activity: user.activity }) + if (!chest) { + throw new ZError(12, 'chest not found') + } if (chest.bonusUsers.includes(uid)) { throw new ZError(10, 'user already enhanced') } if (chest.bonusUsers.length >= chest.maxBounsCount) { - throw new ZError(12, 'enhanced times exceed') + throw new ZError(13, 'enhanced times exceed') } if (chest.status === ChestStatusEnum.OPENED) { - throw new ZError(13, 'chest already opened') + throw new ZError(14, 'chest already opened') } if (chest.status === ChestStatusEnum.LOCKED) { - throw new ZError(14, 'chest is locked') + throw new ZError(15, 'chest is locked') } // 生产环境不能助力自己 if (process.env.NODE_ENV === 'production' && chest.user === uid) { @@ -141,8 +148,8 @@ class BoxController extends BaseController { new SyncLocker().checkLock(req) const user = req.user const { chestId } = req.params - if (!chestId) { - throw new ZError(11, 'chestId is required') + if (!isObjectIdString(chestId)) { + throw new ZError(11, 'must provide valid chestId') } const openRecord = await ChestRecord.findOne({ from: user.address.toLowerCase(), chestId }) if (!openRecord) { diff --git a/src/controllers/game.controller.ts b/src/controllers/game.controller.ts index e11a8a2..878b801 100644 --- a/src/controllers/game.controller.ts +++ b/src/controllers/game.controller.ts @@ -73,10 +73,13 @@ class GameController extends BaseController { new SyncLocker().checkLock(req) const user = req.user let { days } = req.params - if (!days) { + if (!days || isNaN(days)) { throw new ZError(11, 'invalid days') } days = parseInt(days) + if (days < 1) { + throw new ZError(12, 'invalid days') + } const dateTag = formatDate(new Date()) const checkRecord = await checkInToday(user.address.toLowerCase(), dateTag) if (!checkRecord) { @@ -198,7 +201,11 @@ class GameController extends BaseController { if (isNaN(step)) { throw new ZError(11, 'invalid step') } + // check if step is safe int step = parseInt(step) + if (step < 1) { + step = 1 + } // const session = await mongoose.startSession() // session.startTransaction() // try { @@ -227,6 +234,8 @@ class GameController extends BaseController { updateData.maxNoChestCount = 0 const level = generateChestLevel() chests.push(generateNewChest(user.id, user.activity, level, ChestStatusEnum.NORMAL)) + } else { + updateData['$inc']['maxNoChestCount'] = step } } await ActivityGame.updateOne({ user: user.id, activity: user.activity }, updateData)