From f584a5b499ac2cefc3dfc8f0786a70b0dadd89d9 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Wed, 12 Jul 2023 18:17:15 -0400 Subject: [PATCH] Make user data update endpoint do something --- package-lock.json | 11 ++- package.json | 3 +- src/services/api/routes/v1/user.ts | 121 +++++++++++++++++++++++++---- src/types/mii-js.d.ts | 1 + 4 files changed, 118 insertions(+), 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index e0c0320..fde4b19 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,7 +41,8 @@ "typescript-is": "^0.19.0", "validator": "^13.7.0", "xmlbuilder": "^13.0.2", - "xmlbuilder2": "0.0.4" + "xmlbuilder2": "0.0.4", + "zod": "^3.21.4" }, "devDependencies": { "@hcaptcha/types": "^1.0.3", @@ -5811,6 +5812,14 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", + "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index fefab26..a94aaa7 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,8 @@ "typescript-is": "^0.19.0", "validator": "^13.7.0", "xmlbuilder": "^13.0.2", - "xmlbuilder2": "0.0.4" + "xmlbuilder2": "0.0.4", + "zod": "^3.21.4" }, "devDependencies": { "@hcaptcha/types": "^1.0.3", diff --git a/src/services/api/routes/v1/user.ts b/src/services/api/routes/v1/user.ts index c15bfd9..0622763 100644 --- a/src/services/api/routes/v1/user.ts +++ b/src/services/api/routes/v1/user.ts @@ -1,19 +1,21 @@ import express from 'express'; -import joi from 'joi'; -//import { PNID } from '@/models/pnid'; +import { z } from 'zod'; +import Mii from 'mii-js'; import { config } from '@/config-manager'; +import { PNID } from '@/models/pnid'; import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; import { UpdateUserRequest } from '@/types/services/api/update-user-request'; const router: express.Router = express.Router(); -// TODO: Extend this later with more settings -const userSchema: joi.ObjectSchema = joi.object({ - mii: joi.object({ - name: joi.string(), - primary: joi.string(), - data: joi.string(), - }) +// TODO - Extend this later with more settings +const userSchema = z.object({ + mii: z.object({ + name: z.string().trim(), + primary: z.enum(['Y', 'N']), + data: z.string(), + }).optional(), + environment: z.enum(['prod', 'test', 'dev']).optional() }); /** @@ -85,25 +87,112 @@ router.post('/', async (request: express.Request, response: express.Response): P return; } - const valid: joi.ValidationResult = userSchema.validate(updateUserRequest); + const result = userSchema.safeParse(updateUserRequest); - if (valid.error) { + if (!result.success) { response.status(400).json({ app: 'api', status: 400, - error: valid.error + error: result.error }); return; } - // TODO - Make this do something + if (result.data.mii) { + const miiNameBuffer: Buffer = Buffer.from(result.data.mii.name, 'utf16le'); // * UTF8 to UTF16 - //const pid: number = pnid.pid; + if (miiNameBuffer.length < 1) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Mii name too short' + }); - //const updateData = {}; + return; + } - //await PNID.updateOne({ pid }, { $set: updateData }).exec(); + if (miiNameBuffer.length > 0x14) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Mii name too long' + }); + + return; + } + + try { + const miiDataBuffer: Buffer = Buffer.from(result.data.mii.data, 'base64'); + + if (miiDataBuffer.length < 0x60) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Mii data too short' + }); + + return; + } + + if (miiDataBuffer.length > 0x60) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Mii data too long' + }); + + return; + } + + const mii: Mii = new Mii(miiDataBuffer); + mii.validate(); + } catch (_) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Failed to decode Mii data' + }); + + return; + } + + await pnid.updateMii({ + name: result.data.mii.name, + primary: result.data.mii.primary, + data: result.data.mii.data + }); + } + + const updateData: Record = {}; + + if (result.data.environment) { + const environment: string = result.data.environment; + + if (environment === 'test' && pnid.access_level < 1) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Do not have permission to enter this environment' + }); + + return; + } + + if (environment === 'dev' && pnid.access_level < 3) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Do not have permission to enter this environment' + }); + + return; + } + + updateData.server_access_level = environment; + } + + await PNID.updateOne({ pid: pnid.pid }, { $set: updateData }).exec(); response.json({ access_level: pnid.access_level, diff --git a/src/types/mii-js.d.ts b/src/types/mii-js.d.ts index a63a5b8..55cc57f 100644 --- a/src/types/mii-js.d.ts +++ b/src/types/mii-js.d.ts @@ -96,4 +96,5 @@ type Mii = { studioUrl: (options: MiiStudioURLOptions) => string; encode: () => Buffer; + validate: () => void; }; \ No newline at end of file