From 86efb02358c52d5254a084ce94ee82be9beb0662 Mon Sep 17 00:00:00 2001 From: SabreCat Date: Tue, 18 Apr 2023 15:43:35 -0500 Subject: [PATCH] fix(api): address issues caused by 3p tools and flag accounts that use them --- website/common/script/constants.js | 2 ++ website/common/script/index.js | 2 ++ website/server/controllers/api-v3/user.js | 7 ++++++ website/server/middlewares/auth.js | 4 ++++ website/server/models/user/schema.js | 29 ++++++++++++----------- 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/website/common/script/constants.js b/website/common/script/constants.js index b3510378e0..248560f28a 100644 --- a/website/common/script/constants.js +++ b/website/common/script/constants.js @@ -25,6 +25,8 @@ export const SUPPORTED_SOCIAL_NETWORKS = [ { key: 'apple', name: 'Apple' }, ]; +export const OFFICIAL_PLATFORMS = ['habitica-web', 'habitica-ios', 'habitica-android']; + export const GUILDS_PER_PAGE = 30; // number of guilds to return per page when using pagination export const PARTY_LIMIT_MEMBERS = 29; diff --git a/website/common/script/index.js b/website/common/script/index.js index 3045e012ee..3c6b5b0d6c 100644 --- a/website/common/script/index.js +++ b/website/common/script/index.js @@ -22,6 +22,7 @@ import { TAVERN_ID, MAX_MESSAGE_LENGTH, MAX_GIFT_MESSAGE_LENGTH, + OFFICIAL_PLATFORMS, } from './constants'; import content from './content/index'; import * as count from './count'; @@ -124,6 +125,7 @@ api.constants = { MAX_MESSAGE_LENGTH, MAX_GIFT_MESSAGE_LENGTH, MAX_LEVEL_HARD_CAP, + OFFICIAL_PLATFORMS, }; // TODO Move these under api.constants api.maxLevel = MAX_LEVEL; diff --git a/website/server/controllers/api-v3/user.js b/website/server/controllers/api-v3/user.js index c422541705..c5e1acbc8e 100644 --- a/website/server/controllers/api-v3/user.js +++ b/website/server/controllers/api-v3/user.js @@ -22,6 +22,7 @@ import { } from '../../libs/email'; import * as inboxLib from '../../libs/inbox'; import * as userLib from '../../libs/user'; +import { OFFICIAL_PLATFORMS } from '../../../common/script/constants'; const TECH_ASSISTANCE_EMAIL = nconf.get('EMAILS_TECH_ASSISTANCE_EMAIL'); const DELETE_CONFIRMATION = 'DELETE'; @@ -494,6 +495,9 @@ api.buy = { let quantity = 1; if (req.body.quantity) quantity = req.body.quantity; req.quantity = quantity; + if (OFFICIAL_PLATFORMS.indexOf(req.headers['x-client']) === -1) { + res.analytics = undefined; + } const buyRes = await common.ops.buy(user, req, res.analytics); await user.save(); @@ -584,6 +588,9 @@ api.buyArmoire = { const { user } = res.locals; req.type = 'armoire'; req.params.key = 'armoire'; + if (OFFICIAL_PLATFORMS.indexOf(req.headers['x-client']) === -1) { + res.analytics = undefined; + } const buyArmoireResponse = await common.ops.buy(user, req, res.analytics); await user.save(); res.respond(200, ...buyArmoireResponse); diff --git a/website/server/middlewares/auth.js b/website/server/middlewares/auth.js index 7332ba30c3..dfc01ed99e 100644 --- a/website/server/middlewares/auth.js +++ b/website/server/middlewares/auth.js @@ -55,6 +55,7 @@ export function authWithHeaders (options = {}) { return function authWithHeadersHandler (req, res, next) { const userId = req.header('x-api-user'); const apiToken = req.header('x-api-key'); + const client = req.header('x-client'); const optional = options.optional || false; if (!userId || !apiToken) { @@ -90,6 +91,9 @@ export function authWithHeaders (options = {}) { req.session.userId = user._id; stackdriverTraceUserId(user._id); user.auth.timestamps.updated = new Date(); + if (common.constants.OFFICIAL_PLATFORMS.indexOf(client) === -1 && !user.flags.thirdPartyTools) { + User.updateOne(userQuery, { $set: { 'flags.thirdPartyTools': true }}).exec(); + } return next(); }) .catch(next); diff --git a/website/server/models/user/schema.js b/website/server/models/user/schema.js index 7c9ab11a59..2af2b88e66 100644 --- a/website/server/models/user/schema.js +++ b/website/server/models/user/schema.js @@ -306,6 +306,7 @@ export default new Schema({ cardReceived: { $type: Boolean, default: false }, warnedLowHealth: { $type: Boolean, default: false }, verifiedUsername: { $type: Boolean, default: false }, + thirdPartyTools: { $type: Boolean, default: false }, }, history: { @@ -613,10 +614,10 @@ export default new Schema({ }, }, stats: { - hp: { $type: Number, default: shared.maxHealth }, - mp: { $type: Number, default: 10 }, - exp: { $type: Number, default: 0 }, - gp: { $type: Number, default: 0 }, + hp: { $type: Number, default: shared.maxHealth, min: 0 }, + mp: { $type: Number, default: 10, min: 0 }, + exp: { $type: Number, default: 0, min: 0 }, + gp: { $type: Number, default: 0, min: 0 }, lvl: { $type: Number, default: 1, @@ -628,17 +629,17 @@ export default new Schema({ class: { $type: String, enum: ['warrior', 'rogue', 'wizard', 'healer'], default: 'warrior', required: true, }, - points: { $type: Number, default: 0 }, - str: { $type: Number, default: 0 }, - con: { $type: Number, default: 0 }, - int: { $type: Number, default: 0 }, - per: { $type: Number, default: 0 }, + points: { $type: Number, default: 0, min: 0 }, + str: { $type: Number, default: 0, min: 0 }, + con: { $type: Number, default: 0, min: 0 }, + int: { $type: Number, default: 0, min: 0 }, + per: { $type: Number, default: 0, min: 0 }, buffs: { - str: { $type: Number, default: 0 }, - int: { $type: Number, default: 0 }, - per: { $type: Number, default: 0 }, - con: { $type: Number, default: 0 }, - stealth: { $type: Number, default: 0 }, + str: { $type: Number, default: 0, min: 0 }, + int: { $type: Number, default: 0, min: 0 }, + per: { $type: Number, default: 0, min: 0 }, + con: { $type: Number, default: 0, min: 0 }, + stealth: { $type: Number, default: 0, min: 0 }, streaks: { $type: Boolean, default: false }, snowball: { $type: Boolean, default: false }, spookySparkles: { $type: Boolean, default: false },