From 2bc1d9cf8e81485babc8ad013e2219db0ef66873 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 14 Apr 2024 18:02:01 -0400 Subject: [PATCH 1/7] nnas: renamed nnid service to nnas --- package.json | 2 +- src/database.ts | 2 +- src/server.ts | 4 +- src/services/nnas/index.ts | 48 +++++++++++++++++++ src/services/{nnid => nnas}/routes/admin.ts | 0 src/services/{nnid => nnas}/routes/content.ts | 6 +-- src/services/{nnid => nnas}/routes/devices.ts | 0 src/services/{nnid => nnas}/routes/miis.ts | 0 src/services/{nnid => nnas}/routes/oauth.ts | 0 src/services/{nnid => nnas}/routes/people.ts | 10 ++-- .../{nnid => nnas}/routes/provider.ts | 0 src/services/{nnid => nnas}/routes/support.ts | 0 src/services/{nnid => nnas}/timezones.json | 0 src/services/nnid/index.ts | 48 ------------------- src/types/services/{nnid => nnas}/person.ts | 0 .../services/{nnid => nnas}/pnid-profile.ts | 0 .../{nnid => nnas}/region-languages.ts | 2 +- .../{nnid => nnas}/region-timezones.ts | 0 18 files changed, 61 insertions(+), 61 deletions(-) create mode 100644 src/services/nnas/index.ts rename src/services/{nnid => nnas}/routes/admin.ts (100%) rename src/services/{nnid => nnas}/routes/content.ts (94%) rename src/services/{nnid => nnas}/routes/devices.ts (100%) rename src/services/{nnid => nnas}/routes/miis.ts (100%) rename src/services/{nnid => nnas}/routes/oauth.ts (100%) rename src/services/{nnid => nnas}/routes/people.ts (95%) rename src/services/{nnid => nnas}/routes/provider.ts (100%) rename src/services/{nnid => nnas}/routes/support.ts (100%) rename src/services/{nnid => nnas}/timezones.json (100%) delete mode 100644 src/services/nnid/index.ts rename src/types/services/{nnid => nnas}/person.ts (100%) rename src/types/services/{nnid => nnas}/pnid-profile.ts (100%) rename src/types/services/{nnid => nnas}/region-languages.ts (55%) rename src/types/services/{nnid => nnas}/region-timezones.ts (100%) diff --git a/package.json b/package.json index b1359b7..b945ec9 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "clean": "rimraf ./dist", "copy-static": "npm run copy-assets && npm run copy-timezones", "copy-assets": "cp -r ./src/assets ./dist/assets", - "copy-timezones": "cp ./src/services/nnid/timezones.json ./dist/services/nnid/timezones.json", + "copy-timezones": "cp ./src/services/nnas/timezones.json ./dist/services/nnas/timezones.json", "start": "node .", "start:dev": "NODE_ENV=development node ." }, diff --git a/src/database.ts b/src/database.ts index a301b92..656e547 100644 --- a/src/database.ts +++ b/src/database.ts @@ -11,7 +11,7 @@ import { IDevice } from '@/types/mongoose/device'; import { IDeviceAttribute } from '@/types/mongoose/device-attribute'; import { HydratedServerDocument } from '@/types/mongoose/server'; import { Token } from '@/types/common/token'; -import { PNIDProfile } from '@/types/services/nnid/pnid-profile'; +import { PNIDProfile } from '@/types/services/nnas/pnid-profile'; import { ConnectionData } from '@/types/services/api/connection-data'; import { ConnectionResponse } from '@/types/services/api/connection-response'; import { DiscordConnectionData } from '@/types/services/api/discord-connection-data'; diff --git a/src/server.ts b/src/server.ts index 0050b1a..ad5bd83 100644 --- a/src/server.ts +++ b/src/server.ts @@ -16,7 +16,7 @@ import { LOG_INFO, LOG_SUCCESS, LOG_WARN } from '@/logger'; import conntest from '@/services/conntest'; import cbvc from '@/services/cbvc'; -import nnid from '@/services/nnid'; +import nnas from '@/services/nnas'; import nasc from '@/services/nasc'; import datastore from '@/services/datastore'; import api from '@/services/api'; @@ -41,7 +41,7 @@ app.use(xmlparser); // import the servers into one app.use(conntest); app.use(cbvc); -app.use(nnid); +app.use(nnas); app.use(nasc); app.use(datastore); app.use(api); diff --git a/src/services/nnas/index.ts b/src/services/nnas/index.ts new file mode 100644 index 0000000..c90d5eb --- /dev/null +++ b/src/services/nnas/index.ts @@ -0,0 +1,48 @@ +// handles "account.nintendo.net" endpoints + +import express from 'express'; +import subdomain from 'express-subdomain'; +import clientHeaderCheck from '@/middleware/client-header'; +import cemuMiddleware from '@/middleware/cemu'; +import pnidMiddleware from '@/middleware/pnid'; +import { LOG_INFO } from '@/logger'; + +import admin from '@/services/nnas/routes/admin'; +import content from '@/services/nnas/routes/content'; +import devices from '@/services/nnas/routes/devices'; +import miis from '@/services/nnas/routes/miis'; +import oauth from '@/services/nnas/routes/oauth'; +import people from '@/services/nnas/routes/people'; +import provider from '@/services/nnas/routes/provider'; +import support from '@/services/nnas/routes/support'; + +// Router to handle the subdomain restriction +const nnas: express.Router = express.Router(); + +LOG_INFO('[NNAS] Importing middleware'); +nnas.use(clientHeaderCheck); +nnas.use(cemuMiddleware); +nnas.use(pnidMiddleware); + +// Setup routes +LOG_INFO('[NNAS] Applying imported routes'); +nnas.use('/v1/api/admin', admin); +nnas.use('/v1/api/content', content); +nnas.use('/v1/api/devices', devices); +nnas.use('/v1/api/miis', miis); +nnas.use('/v1/api/oauth20', oauth); +nnas.use('/v1/api/people', people); +nnas.use('/v1/api/provider', provider); +nnas.use('/v1/api/support', support); + +// Main router for endpoints +const router = express.Router(); + +// Create subdomains +LOG_INFO('[NNAS] Creating \'account\' subdomain'); +router.use(subdomain('account', nnas)); + +LOG_INFO('[NNAS] Creating \'c.account\' subdomain'); +router.use(subdomain('c.account', nnas)); + +export default router; \ No newline at end of file diff --git a/src/services/nnid/routes/admin.ts b/src/services/nnas/routes/admin.ts similarity index 100% rename from src/services/nnid/routes/admin.ts rename to src/services/nnas/routes/admin.ts diff --git a/src/services/nnid/routes/content.ts b/src/services/nnas/routes/content.ts similarity index 94% rename from src/services/nnid/routes/content.ts rename to src/services/nnas/routes/content.ts index b4d1ac3..db5100d 100644 --- a/src/services/nnid/routes/content.ts +++ b/src/services/nnas/routes/content.ts @@ -1,8 +1,8 @@ import express from 'express'; import xmlbuilder from 'xmlbuilder'; -import timezones from '@/services/nnid/timezones.json'; -import { RegionLanguages } from '@/types/services/nnid/region-languages'; -import { RegionTimezones } from '@/types/services/nnid/region-timezones'; +import timezones from '@/services/nnas/timezones.json'; +import { RegionLanguages } from '@/types/services/nnas/region-languages'; +import { RegionTimezones } from '@/types/services/nnas/region-timezones'; const router: express.Router = express.Router(); diff --git a/src/services/nnid/routes/devices.ts b/src/services/nnas/routes/devices.ts similarity index 100% rename from src/services/nnid/routes/devices.ts rename to src/services/nnas/routes/devices.ts diff --git a/src/services/nnid/routes/miis.ts b/src/services/nnas/routes/miis.ts similarity index 100% rename from src/services/nnid/routes/miis.ts rename to src/services/nnas/routes/miis.ts diff --git a/src/services/nnid/routes/oauth.ts b/src/services/nnas/routes/oauth.ts similarity index 100% rename from src/services/nnid/routes/oauth.ts rename to src/services/nnas/routes/oauth.ts diff --git a/src/services/nnid/routes/people.ts b/src/services/nnas/routes/people.ts similarity index 95% rename from src/services/nnid/routes/people.ts rename to src/services/nnas/routes/people.ts index 8b95850..c4b8bcd 100644 --- a/src/services/nnid/routes/people.ts +++ b/src/services/nnas/routes/people.ts @@ -12,14 +12,14 @@ import { PNID } from '@/models/pnid'; import { NEXAccount } from '@/models/nex-account'; import { LOG_ERROR } from '@/logger'; -import timezones from '@/services/nnid/timezones.json'; +import timezones from '@/services/nnas/timezones.json'; import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; import { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; -import { RegionLanguages } from '@/types/services/nnid/region-languages'; -import { RegionTimezone, RegionTimezones } from '@/types/services/nnid/region-timezones'; -import { Person } from '@/types/services/nnid/person'; -import { PNIDProfile } from '@/types/services/nnid/pnid-profile'; +import { RegionLanguages } from '@/types/services/nnas/region-languages'; +import { RegionTimezone, RegionTimezones } from '@/types/services/nnas/region-timezones'; +import { Person } from '@/types/services/nnas/person'; +import { PNIDProfile } from '@/types/services/nnas/pnid-profile'; const router: express.Router = express.Router(); diff --git a/src/services/nnid/routes/provider.ts b/src/services/nnas/routes/provider.ts similarity index 100% rename from src/services/nnid/routes/provider.ts rename to src/services/nnas/routes/provider.ts diff --git a/src/services/nnid/routes/support.ts b/src/services/nnas/routes/support.ts similarity index 100% rename from src/services/nnid/routes/support.ts rename to src/services/nnas/routes/support.ts diff --git a/src/services/nnid/timezones.json b/src/services/nnas/timezones.json similarity index 100% rename from src/services/nnid/timezones.json rename to src/services/nnas/timezones.json diff --git a/src/services/nnid/index.ts b/src/services/nnid/index.ts deleted file mode 100644 index 726b95c..0000000 --- a/src/services/nnid/index.ts +++ /dev/null @@ -1,48 +0,0 @@ -// handles "account.nintendo.net" endpoints - -import express from 'express'; -import subdomain from 'express-subdomain'; -import clientHeaderCheck from '@/middleware/client-header'; -import cemuMiddleware from '@/middleware/cemu'; -import pnidMiddleware from '@/middleware/pnid'; -import { LOG_INFO } from '@/logger'; - -import admin from '@/services/nnid/routes/admin'; -import content from '@/services/nnid/routes/content'; -import devices from '@/services/nnid/routes/devices'; -import miis from '@/services/nnid/routes/miis'; -import oauth from '@/services/nnid/routes/oauth'; -import people from '@/services/nnid/routes/people'; -import provider from '@/services/nnid/routes/provider'; -import support from '@/services/nnid/routes/support'; - -// Router to handle the subdomain restriction -const nnid: express.Router = express.Router(); - -LOG_INFO('[NNID] Importing middleware'); -nnid.use(clientHeaderCheck); -nnid.use(cemuMiddleware); -nnid.use(pnidMiddleware); - -// Setup routes -LOG_INFO('[NNID] Applying imported routes'); -nnid.use('/v1/api/admin', admin); -nnid.use('/v1/api/content', content); -nnid.use('/v1/api/devices', devices); -nnid.use('/v1/api/miis', miis); -nnid.use('/v1/api/oauth20', oauth); -nnid.use('/v1/api/people', people); -nnid.use('/v1/api/provider', provider); -nnid.use('/v1/api/support', support); - -// Main router for endpoints -const router = express.Router(); - -// Create subdomains -LOG_INFO('[NNID] Creating \'account\' subdomain'); -router.use(subdomain('account', nnid)); - -LOG_INFO('[NNID] Creating \'c.account\' subdomain'); -router.use(subdomain('c.account', nnid)); - -export default router; \ No newline at end of file diff --git a/src/types/services/nnid/person.ts b/src/types/services/nnas/person.ts similarity index 100% rename from src/types/services/nnid/person.ts rename to src/types/services/nnas/person.ts diff --git a/src/types/services/nnid/pnid-profile.ts b/src/types/services/nnas/pnid-profile.ts similarity index 100% rename from src/types/services/nnid/pnid-profile.ts rename to src/types/services/nnas/pnid-profile.ts diff --git a/src/types/services/nnid/region-languages.ts b/src/types/services/nnas/region-languages.ts similarity index 55% rename from src/types/services/nnid/region-languages.ts rename to src/types/services/nnas/region-languages.ts index e25307d..fd4bbf9 100644 --- a/src/types/services/nnid/region-languages.ts +++ b/src/types/services/nnas/region-languages.ts @@ -1,4 +1,4 @@ -import { RegionTimezones } from '@/types/services/nnid/region-timezones'; +import { RegionTimezones } from '@/types/services/nnas/region-timezones'; export interface RegionLanguages { [myKey: string]: RegionTimezones diff --git a/src/types/services/nnid/region-timezones.ts b/src/types/services/nnas/region-timezones.ts similarity index 100% rename from src/types/services/nnid/region-timezones.ts rename to src/types/services/nnas/region-timezones.ts From cb10a1666812b994f58ebc2fe9a83f03901e6dcc Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 14 Apr 2024 19:16:25 -0400 Subject: [PATCH 2/7] chore: removed unnecessary type declarations --- .eslintrc.json | 2 +- src/cache.ts | 12 +- src/config-manager.ts | 4 +- src/database.ts | 41 ++++--- src/logger.ts | 10 +- src/mailer.ts | 8 +- src/middleware/api.ts | 7 +- src/middleware/cemu.ts | 2 +- src/middleware/client-header.ts | 6 +- src/middleware/console-status-verification.ts | 13 +-- src/middleware/device-certificate.ts | 2 +- src/middleware/nasc.ts | 55 +++++----- src/middleware/pnid.ts | 8 +- src/middleware/ratelimit.ts | 2 +- src/middleware/xml-parser.ts | 6 +- src/models/device.ts | 2 +- src/models/nex-account.ts | 16 +-- src/models/pnid.ts | 42 +++---- src/models/server.ts | 2 +- src/nintendo-certificate.ts | 12 +- src/server.ts | 12 +- src/services/api/index.ts | 4 +- src/services/api/routes/v1/connections.ts | 21 ++-- src/services/api/routes/v1/email.ts | 9 +- src/services/api/routes/v1/forgotPassword.ts | 4 +- src/services/api/routes/v1/login.ts | 25 ++--- src/services/api/routes/v1/register.ts | 62 +++++------ src/services/api/routes/v1/resetPassword.ts | 25 ++--- src/services/api/routes/v1/user.ts | 15 ++- src/services/assets/index.ts | 4 +- src/services/cbvc/index.ts | 4 +- src/services/conntest/index.ts | 4 +- src/services/datastore/index.ts | 4 +- src/services/datastore/routes/upload.ts | 42 +++---- .../grpc/account/api-key-middleware.ts | 2 +- .../account/exchange-token-for-user-data.ts | 3 +- src/services/grpc/account/get-nex-data.ts | 3 +- src/services/grpc/account/get-nex-password.ts | 3 +- src/services/grpc/account/get-user-data.ts | 3 +- src/services/grpc/account/implementation.ts | 3 +- .../grpc/account/update-pnid-permissions.ts | 3 +- src/services/grpc/api/api-key-middleware.ts | 2 +- .../grpc/api/authentication-middleware.ts | 8 +- src/services/grpc/api/forgot-password.ts | 2 +- src/services/grpc/api/get-user-data.ts | 3 +- src/services/grpc/api/implementation.ts | 3 +- src/services/grpc/api/login.ts | 23 ++-- src/services/grpc/api/register.ts | 62 +++++------ src/services/grpc/api/reset-password.ts | 23 ++-- .../grpc/api/set-discord-connection-data.ts | 5 +- .../grpc/api/set-stripe-connection-data.ts | 5 +- src/services/grpc/api/update-user-data.ts | 3 +- src/services/grpc/server.ts | 4 +- src/services/local-cdn/index.ts | 4 +- src/services/local-cdn/routes/get.ts | 6 +- src/services/nasc/index.ts | 4 +- src/services/nasc/routes/ac.ts | 28 +++-- src/services/nnas/index.ts | 2 +- src/services/nnas/routes/admin.ts | 15 ++- src/services/nnas/routes/content.ts | 12 +- src/services/nnas/routes/devices.ts | 2 +- src/services/nnas/routes/miis.ts | 9 +- src/services/nnas/routes/oauth.ts | 26 ++--- src/services/nnas/routes/people.ts | 103 +++++++++--------- src/services/nnas/routes/provider.ts | 40 +++---- src/services/nnas/routes/support.ts | 23 ++-- src/types/common/config.ts | 7 -- src/types/services/nnas/region-languages.ts | 5 - src/types/services/nnas/region-timezones.ts | 9 -- src/util.ts | 57 +++++----- 70 files changed, 465 insertions(+), 537 deletions(-) delete mode 100644 src/types/services/nnas/region-languages.ts delete mode 100644 src/types/services/nnas/region-timezones.ts diff --git a/.eslintrc.json b/.eslintrc.json index d66114d..24079aa 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -29,7 +29,7 @@ "no-extra-semi": "off", "@typescript-eslint/no-extra-semi": "error", "@typescript-eslint/no-empty-interface": "warn", - "@typescript-eslint/no-inferrable-types": "off", + "@typescript-eslint/no-inferrable-types": "error", "@typescript-eslint/explicit-function-return-type": "error", "one-var": [ "error", diff --git a/src/cache.ts b/src/cache.ts index 593554b..e354732 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -4,9 +4,9 @@ import { config, disabledFeatures } from '@/config-manager'; let client: redis.RedisClientType; -const memoryCache: { [key: string]: Buffer } = {}; +const memoryCache: Record = {}; -const LOCAL_CDN_BASE: string = `${__dirname}/../cdn`; +const LOCAL_CDN_BASE = `${__dirname}/../cdn`; export async function connect(): Promise { if (!disabledFeatures.redis) { @@ -26,12 +26,12 @@ export async function setCachedFile(fileName: string, value: Buffer): Promise { - let cachedFile: Buffer = Buffer.alloc(0); + let cachedFile = Buffer.alloc(0); if (disabledFeatures.redis) { cachedFile = memoryCache[fileName] || null; } else { - const redisValue: string | null = await client.get(fileName); + const redisValue = await client.get(fileName); if (redisValue) { cachedFile = Buffer.from(redisValue, encoding); } @@ -43,11 +43,11 @@ export async function getCachedFile(fileName: string, encoding?: BufferEncoding) // * Local CDN cache functions export async function getLocalCDNFile(name: string, encoding?: BufferEncoding): Promise { - let file: Buffer = await getCachedFile(`local_cdn:${name}`, encoding); + let file = await getCachedFile(`local_cdn:${name}`, encoding); if (file === null) { if (await fs.pathExists(`${LOCAL_CDN_BASE}/${name}`)) { - const fileBuffer: string | Buffer = await fs.readFile(`${LOCAL_CDN_BASE}/${name}`, { encoding }); + const fileBuffer = await fs.readFile(`${LOCAL_CDN_BASE}/${name}`, { encoding }); file = Buffer.from(fileBuffer); await setLocalCDNFile(name, file); } diff --git a/src/config-manager.ts b/src/config-manager.ts index 09a2220..de58294 100644 --- a/src/config-manager.ts +++ b/src/config-manager.ts @@ -2,11 +2,11 @@ import fs from 'fs-extra'; import mongoose from 'mongoose'; import dotenv from 'dotenv'; import { LOG_INFO, LOG_WARN, LOG_ERROR } from '@/logger'; -import { Config, DisabledFeatures } from '@/types/common/config'; +import { Config } from '@/types/common/config'; dotenv.config(); -export const disabledFeatures: DisabledFeatures = { +export const disabledFeatures = { redis: false, email: false, captcha: false, diff --git a/src/database.ts b/src/database.ts index 656e547..4f0e7a2 100644 --- a/src/database.ts +++ b/src/database.ts @@ -7,20 +7,18 @@ import { Server } from '@/models/server'; import { LOG_ERROR } from '@/logger'; import { config } from '@/config-manager'; import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; -import { IDevice } from '@/types/mongoose/device'; import { IDeviceAttribute } from '@/types/mongoose/device-attribute'; import { HydratedServerDocument } from '@/types/mongoose/server'; -import { Token } from '@/types/common/token'; import { PNIDProfile } from '@/types/services/nnas/pnid-profile'; import { ConnectionData } from '@/types/services/api/connection-data'; import { ConnectionResponse } from '@/types/services/api/connection-response'; import { DiscordConnectionData } from '@/types/services/api/discord-connection-data'; -const connection_string: string = config.mongoose.connection_string; -const options: mongoose.ConnectOptions = config.mongoose.options; +const connection_string = config.mongoose.connection_string; +const options = config.mongoose.options; // TODO: Extend this later with more settings -const discordConnectionSchema: joi.ObjectSchema = joi.object({ +const discordConnectionSchema = joi.object({ id: joi.string() }); @@ -79,19 +77,19 @@ export async function getPNIDByBasicAuth(token: string): Promise expireTime) { return null; @@ -128,13 +125,13 @@ export async function getPNIDByTokenAuth(token: string): Promise { verifyConnected(); - const pnid: HydratedPNIDDocument | null = await getPNIDByPID(pid); + const pnid = await getPNIDByPID(pid); if (!pnid) { return null; } - const device: IDevice = pnid.devices[0]; // * Just grab the first device + const device = pnid.devices[0]; // * Just grab the first device let device_attributes: { device_attribute: { name: string; @@ -145,9 +142,9 @@ export async function getPNIDProfileJSONByPID(pid: number): Promise { - const name: string = attribute.name; - const value: string = attribute.value; - const created_date: string | undefined = attribute.created_date; + const name = attribute.name; + const value = attribute.value; + const created_date = attribute.created_date; return { device_attribute: { @@ -237,7 +234,7 @@ export async function addPNIDConnection(pnid: HydratedPNIDDocument, data: Connec } export async function addPNIDConnectionDiscord(pnid: HydratedPNIDDocument, data: DiscordConnectionData): Promise { - const valid: joi.ValidationResult = discordConnectionSchema.validate(data); + const valid = discordConnectionSchema.validate(data); if (valid.error) { return { diff --git a/src/logger.ts b/src/logger.ts index 917b677..d3114ee 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -3,7 +3,7 @@ import colors from 'colors'; colors.enable(); -const root: string = process.env.PN_ACT_LOGGER_PATH ? process.env.PN_ACT_LOGGER_PATH : `${__dirname}/..`; +const root = process.env.PN_ACT_LOGGER_PATH ? process.env.PN_ACT_LOGGER_PATH : `${__dirname}/..`; fs.ensureDirSync(`${root}/logs`); const streams = { @@ -15,7 +15,7 @@ const streams = { } as const; export function LOG_SUCCESS(input: string): void { - const time: Date = new Date(); + const time = new Date(); input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [SUCCESS]: ${input}`; streams.success.write(`${input}\n`); @@ -23,7 +23,7 @@ export function LOG_SUCCESS(input: string): void { } export function LOG_ERROR(input: string): void { - const time: Date = new Date(); + const time = new Date(); input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [ERROR]: ${input}`; streams.error.write(`${input}\n`); @@ -31,7 +31,7 @@ export function LOG_ERROR(input: string): void { } export function LOG_WARN(input: string): void { - const time: Date = new Date(); + const time = new Date(); input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [WARN]: ${input}`; streams.warn.write(`${input}\n`); @@ -39,7 +39,7 @@ export function LOG_WARN(input: string): void { } export function LOG_INFO(input: string): void { - const time: Date = new Date(); + const time = new Date(); input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [INFO]: ${input}`; streams.info.write(`${input}\n`); diff --git a/src/mailer.ts b/src/mailer.ts index ea9a1cd..10efd10 100644 --- a/src/mailer.ts +++ b/src/mailer.ts @@ -5,8 +5,8 @@ import * as aws from '@aws-sdk/client-ses'; import { config, disabledFeatures } from '@/config-manager'; import { MailerOptions } from '@/types/common/mailer-options'; -const genericEmailTemplate: string = fs.readFileSync(path.join(__dirname, './assets/emails/genericTemplate.html'), 'utf8'); -const confirmationEmailTemplate: string = fs.readFileSync(path.join(__dirname, './assets/emails/confirmationTemplate.html'), 'utf8'); +const genericEmailTemplate = fs.readFileSync(path.join(__dirname, './assets/emails/genericTemplate.html'), 'utf8'); +const confirmationEmailTemplate = fs.readFileSync(path.join(__dirname, './assets/emails/confirmationTemplate.html'), 'utf8'); let transporter: nodemailer.Transporter; @@ -32,7 +32,7 @@ export async function sendMail(options: MailerOptions): Promise { if (!disabledFeatures.email) { const { to, subject, username, paragraph, preview, text, link, confirmation } = options; - let html: string = confirmation ? confirmationEmailTemplate : genericEmailTemplate; + let html = confirmation ? confirmationEmailTemplate : genericEmailTemplate; html = html.replace(/{{username}}/g, username); html = html.replace(/{{paragraph}}/g, paragraph || ''); @@ -43,7 +43,7 @@ export async function sendMail(options: MailerOptions): Promise { if (link) { const { href, text } = link; - const button: string = ` ${text}`; + const button = ` ${text}`; html = html.replace(//g, button); } diff --git a/src/middleware/api.ts b/src/middleware/api.ts index 6e03492..8a5f915 100644 --- a/src/middleware/api.ts +++ b/src/middleware/api.ts @@ -1,18 +1,17 @@ import express from 'express'; import { getValueFromHeaders } from '@/util'; import { getPNIDByTokenAuth } from '@/database'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; async function APIMiddleware(request: express.Request, _response: express.Response, next: express.NextFunction): Promise { - const authHeader: string | undefined = getValueFromHeaders(request.headers, 'authorization'); + const authHeader = getValueFromHeaders(request.headers, 'authorization'); if (!authHeader || !(authHeader.startsWith('Bearer'))) { return next(); } try { - const token: string = authHeader.split(' ')[1]; - const pnid: HydratedPNIDDocument | null = await getPNIDByTokenAuth(token); + const token = authHeader.split(' ')[1]; + const pnid = await getPNIDByTokenAuth(token); request.pnid = pnid; } catch (error) { diff --git a/src/middleware/cemu.ts b/src/middleware/cemu.ts index dc44985..6edca3b 100644 --- a/src/middleware/cemu.ts +++ b/src/middleware/cemu.ts @@ -1,7 +1,7 @@ import express from 'express'; function CemuMiddleware(request: express.Request, _response: express.Response, next: express.NextFunction): void { - const subdomain: string = request.subdomains.reverse().join('.'); + const subdomain = request.subdomains.reverse().join('.'); request.isCemu = subdomain === 'c.account'; diff --git a/src/middleware/client-header.ts b/src/middleware/client-header.ts index 2288c80..851317f 100644 --- a/src/middleware/client-header.ts +++ b/src/middleware/client-header.ts @@ -2,7 +2,7 @@ import express from 'express'; import xmlbuilder from 'xmlbuilder'; import { getValueFromHeaders } from '@/util'; -const VALID_CLIENT_ID_SECRET_PAIRS: { [key: string]: string } = { +const VALID_CLIENT_ID_SECRET_PAIRS: Record = { // * 'Key' is the client ID, 'Value' is the client secret 'a2efa818a34fa16b8afbc8a74eba3eda': 'c91cdb5658bd4954ade78533a339cf9a', // * Possibly WiiU exclusive? 'daf6227853bcbdce3d75baee8332b': '3eff548eac636e2bf45bb7b375e7b6b0', // * Possibly 3DS exclusive? @@ -14,8 +14,8 @@ function nintendoClientHeaderCheck(request: express.Request, response: express.R response.set('Server', 'Nintendo 3DS (http)'); response.set('X-Nintendo-Date', new Date().getTime().toString()); - const clientId: string | undefined = getValueFromHeaders(request.headers, 'x-nintendo-client-id'); - const clientSecret: string | undefined = getValueFromHeaders(request.headers, 'x-nintendo-client-secret'); + const clientId = getValueFromHeaders(request.headers, 'x-nintendo-client-id'); + const clientSecret = getValueFromHeaders(request.headers, 'x-nintendo-client-secret'); if ( !clientId || diff --git a/src/middleware/console-status-verification.ts b/src/middleware/console-status-verification.ts index cb1b7d3..90d5cb3 100644 --- a/src/middleware/console-status-verification.ts +++ b/src/middleware/console-status-verification.ts @@ -3,7 +3,6 @@ import express from 'express'; import xmlbuilder from 'xmlbuilder'; import { Device } from '@/models/device'; import { getValueFromHeaders } from '@/util'; -import { HydratedDeviceDocument } from '@/types/mongoose/device'; async function consoleStatusVerificationMiddleware(request: express.Request, response: express.Response, next: express.NextFunction): Promise { if (!request.certificate || !request.certificate.valid) { @@ -17,7 +16,7 @@ async function consoleStatusVerificationMiddleware(request: express.Request, res return; } - const deviceIDHeader: string | undefined = getValueFromHeaders(request.headers, 'x-nintendo-device-id'); + const deviceIDHeader = getValueFromHeaders(request.headers, 'x-nintendo-device-id'); if (!deviceIDHeader) { response.status(400).send(xmlbuilder.create({ @@ -30,7 +29,7 @@ async function consoleStatusVerificationMiddleware(request: express.Request, res return; } - const deviceID: number = Number(deviceIDHeader); + const deviceID = Number(deviceIDHeader); if (isNaN(deviceID)) { response.status(400).send(xmlbuilder.create({ @@ -43,7 +42,7 @@ async function consoleStatusVerificationMiddleware(request: express.Request, res return; } - const serialNumber: string | undefined = getValueFromHeaders(request.headers, 'x-nintendo-serial-number'); + const serialNumber = getValueFromHeaders(request.headers, 'x-nintendo-serial-number'); // TODO - Verify serial numbers somehow? // * This is difficult to do safely because serial numbers are @@ -72,7 +71,7 @@ async function consoleStatusVerificationMiddleware(request: express.Request, res // * This is kinda temp for now. Needs to be redone to handle linking this data to existing 3DS devices in the DB // TODO - 3DS consoles are created in the NASC middleware. They need special handling to link them up with the data in the NNID API! if (request.certificate.consoleType === 'wiiu') { - const certificateDeviceID: number = parseInt(request.certificate.certificateName.slice(2), 16); + const certificateDeviceID = parseInt(request.certificate.certificateName.slice(2), 16); if (deviceID !== certificateDeviceID) { // TODO - Change this to a different error @@ -88,9 +87,9 @@ async function consoleStatusVerificationMiddleware(request: express.Request, res } // * Only store a hash of the certificate in case of a breach - const certificateHash: string = crypto.createHash('sha256').update(request.certificate._certificate).digest('base64'); + const certificateHash = crypto.createHash('sha256').update(request.certificate._certificate).digest('base64'); - let device: HydratedDeviceDocument | null = await Device.findOne({ + let device = await Device.findOne({ certificate_hash: certificateHash, }); diff --git a/src/middleware/device-certificate.ts b/src/middleware/device-certificate.ts index 9e7d224..4080d89 100644 --- a/src/middleware/device-certificate.ts +++ b/src/middleware/device-certificate.ts @@ -3,7 +3,7 @@ import NintendoCertificate from '@/nintendo-certificate'; import { getValueFromHeaders } from '@/util'; function deviceCertificateMiddleware(request: express.Request, _response: express.Response, next: express.NextFunction): void { - const certificate: string | undefined = getValueFromHeaders(request.headers, 'x-nintendo-device-cert'); + const certificate = getValueFromHeaders(request.headers, 'x-nintendo-device-cert'); if (!certificate) { return next(); diff --git a/src/middleware/nasc.ts b/src/middleware/nasc.ts index 4cc657f..73bdb11 100644 --- a/src/middleware/nasc.ts +++ b/src/middleware/nasc.ts @@ -1,6 +1,5 @@ import crypto from 'node:crypto'; import express from 'express'; -import mongoose from 'mongoose'; import { Device } from '@/models/device'; import { NEXAccount } from '@/models/nex-account'; import { nascError, nintendoBase64Decode } from '@/util'; @@ -8,8 +7,6 @@ import { connection as databaseConnection } from '@/database'; import NintendoCertificate from '@/nintendo-certificate'; import { LOG_ERROR } from '@/logger'; import { NASCRequestParams } from '@/types/services/nasc/request-params'; -import { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; -import { HydratedDeviceDocument } from '@/types/mongoose/device'; async function NASCMiddleware(request: express.Request, response: express.Response, next: express.NextFunction): Promise { const requestParams: NASCRequestParams = request.body; @@ -25,19 +22,19 @@ async function NASCMiddleware(request: express.Request, response: express.Respon return; } - const action: string = nintendoBase64Decode(requestParams.action).toString(); - const fcdcert: Buffer = nintendoBase64Decode(requestParams.fcdcert); - const serialNumber: string = nintendoBase64Decode(requestParams.csnum).toString(); - const macAddress: string = nintendoBase64Decode(requestParams.macadr).toString(); - const titleID: string = nintendoBase64Decode(requestParams.titleid).toString(); - const environment: string = nintendoBase64Decode(requestParams.servertype).toString(); + const action = nintendoBase64Decode(requestParams.action).toString(); + const fcdcert = nintendoBase64Decode(requestParams.fcdcert); + const serialNumber = nintendoBase64Decode(requestParams.csnum).toString(); + const macAddress = nintendoBase64Decode(requestParams.macadr).toString(); + const titleID = nintendoBase64Decode(requestParams.titleid).toString(); + const environment = nintendoBase64Decode(requestParams.servertype).toString(); - const macAddressHash: string = crypto.createHash('sha256').update(macAddress).digest('base64'); - const fcdcertHash: string = crypto.createHash('sha256').update(fcdcert).digest('base64'); + const macAddressHash = crypto.createHash('sha256').update(macAddress).digest('base64'); + const fcdcertHash = crypto.createHash('sha256').update(fcdcert).digest('base64'); - let pid: number = 0; // * Real PIDs are always positive and non-zero - let pidHmac: string = ''; - let password: string = ''; + let pid = 0; // * Real PIDs are always positive and non-zero + let pidHmac = ''; + let password = ''; if (requestParams.userid) { pid = Number(nintendoBase64Decode(requestParams.userid).toString()); @@ -56,7 +53,7 @@ async function NASCMiddleware(request: express.Request, response: express.Respon return; } - const cert: NintendoCertificate = new NintendoCertificate(fcdcert); + const cert = new NintendoCertificate(fcdcert); if (!cert.valid) { response.status(200).send(nascError('121').toString()); @@ -68,7 +65,7 @@ async function NASCMiddleware(request: express.Request, response: express.Respon return; } - let model: string = ''; + let model = ''; switch (serialNumber[0]) { case 'C': model = 'ctr'; @@ -95,7 +92,7 @@ async function NASCMiddleware(request: express.Request, response: express.Respon return; } - let nexAccount: HydratedNEXAccountDocument | null = null; + let nexAccount = null; if (pid) { nexAccount = await NEXAccount.findOne({ pid }); @@ -106,7 +103,7 @@ async function NASCMiddleware(request: express.Request, response: express.Respon } - let device: HydratedDeviceDocument | null = await Device.findOne({ + let device = await Device.findOne({ fcdcert_hash: fcdcertHash, }); @@ -117,7 +114,7 @@ async function NASCMiddleware(request: express.Request, response: express.Respon } if (pid) { - const linkedPIDs: number[] = device.linked_pids; + const linkedPIDs = device.linked_pids; // * If a user performs a system transfer from // * a console to another using a Nintendo account @@ -169,7 +166,7 @@ async function NASCMiddleware(request: express.Request, response: express.Respon if (password && !pid && !pidHmac) { // Register new user - const session: mongoose.ClientSession = await databaseConnection().startSession(); + const session = await databaseConnection().startSession(); await session.startTransaction(); try { @@ -185,15 +182,15 @@ async function NASCMiddleware(request: express.Request, response: express.Respon pid = nexAccount.pid; - const pidBuffer: Buffer = Buffer.alloc(4); + const pidBuffer = Buffer.alloc(4); pidBuffer.writeUInt32LE(pid); - const hash: crypto.Hash = crypto.createHash('sha1').update(pidBuffer); - const pidHash: Buffer = hash.digest(); - const checksum: number = pidHash[0] >> 1; - const hex: string = checksum.toString(16) + pid.toString(16); - const int: number = parseInt(hex, 16); - const friendCode: string = int.toString().padStart(12, '0').match(/.{1,4}/g)!.join('-'); + const hash = crypto.createHash('sha1').update(pidBuffer); + const pidHash = hash.digest(); + const checksum = pidHash[0] >> 1; + const hex = checksum.toString(16) + pid.toString(16); + const int = parseInt(hex, 16); + const friendCode = int.toString().padStart(12, '0').match(/.{1,4}/g)!.join('-'); nexAccount.friend_code = friendCode; @@ -240,7 +237,7 @@ async function NASCMiddleware(request: express.Request, response: express.Respon // https://www.adminsub.net/mac-address-finder/nintendo // Saves us from doing an OUI lookup each time -const NINTENDO_VENDER_OUIS: string[] = [ +const NINTENDO_VENDER_OUIS = [ 'ECC40D', 'E84ECE', 'E0F6B5', 'E0E751', 'E00C7F', 'DC68EB', 'D86BF7', 'D4F057', 'CCFB65', 'CC9E00', 'B8AE6E', 'B88AEC', 'B87826', 'A4C0E1', 'A45C27', 'A438CC', '9CE635', '98E8FA', @@ -266,7 +263,7 @@ const NINTENDO_VENDER_OUIS: string[] = [ ]; // TODO: Make something better -const MAC_REGEX: RegExp = /^[0-9a-fA-F]{12}$/; +const MAC_REGEX = /^[0-9a-fA-F]{12}$/; // Maybe should later parse more data out function validNintendoMACAddress(macAddress: string): boolean { diff --git a/src/middleware/pnid.ts b/src/middleware/pnid.ts index 780dc74..cb9776e 100644 --- a/src/middleware/pnid.ts +++ b/src/middleware/pnid.ts @@ -5,15 +5,15 @@ import { getPNIDByBasicAuth, getPNIDByTokenAuth } from '@/database'; import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; async function PNIDMiddleware(request: express.Request, response: express.Response, next: express.NextFunction): Promise { - const authHeader: string | undefined = getValueFromHeaders(request.headers, 'authorization'); + const authHeader = getValueFromHeaders(request.headers, 'authorization'); if (!authHeader || !(authHeader.startsWith('Bearer') || authHeader.startsWith('Basic'))) { return next(); } - const parts: string[] = authHeader.split(' '); - const type: string = parts[0]; - let token: string = parts[1]; + const parts = authHeader.split(' '); + const type = parts[0]; + let token = parts[1]; let pnid: HydratedPNIDDocument | null; if (request.isCemu) { diff --git a/src/middleware/ratelimit.ts b/src/middleware/ratelimit.ts index 7538724..c12f7f1 100644 --- a/src/middleware/ratelimit.ts +++ b/src/middleware/ratelimit.ts @@ -7,7 +7,7 @@ export default ratelimit({ windowMs: 60 * 1000, max: 1, keyGenerator: (request: express.Request): string => { - let data: string | undefined = getValueFromHeaders(request.headers, 'x-nintendo-device-cert'); + let data = getValueFromHeaders(request.headers, 'x-nintendo-device-cert'); if (!data) { data = request.ip; diff --git a/src/middleware/xml-parser.ts b/src/middleware/xml-parser.ts index 435b1e3..dec8caa 100644 --- a/src/middleware/xml-parser.ts +++ b/src/middleware/xml-parser.ts @@ -5,9 +5,9 @@ import { getValueFromHeaders, mapToObject } from '@/util'; function XMLMiddleware(request: express.Request, response: express.Response, next: express.NextFunction): void { if (request.method == 'POST' || request.method == 'PUT') { - const contentType: string | undefined = getValueFromHeaders(request.headers, 'content-type'); - const contentLength: string | undefined = getValueFromHeaders(request.headers, 'content-length'); - let body: string = ''; + const contentType = getValueFromHeaders(request.headers, 'content-type'); + const contentLength = getValueFromHeaders(request.headers, 'content-length'); + let body = ''; if ( !contentType || diff --git a/src/models/device.ts b/src/models/device.ts index cf4ff10..a219516 100644 --- a/src/models/device.ts +++ b/src/models/device.ts @@ -44,4 +44,4 @@ export const DeviceSchema = new Schema({ certificate_hash: String }); -export const Device: DeviceModel = model('Device', DeviceSchema); \ No newline at end of file +export const Device = model('Device', DeviceSchema); \ No newline at end of file diff --git a/src/models/nex-account.ts b/src/models/nex-account.ts index 3f7c0dd..9372ac6 100644 --- a/src/models/nex-account.ts +++ b/src/models/nex-account.ts @@ -1,6 +1,6 @@ import { Schema, model } from 'mongoose'; import uniqueValidator from 'mongoose-unique-validator'; -import { HydratedNEXAccountDocument, INEXAccount, INEXAccountMethods, NEXAccountModel } from '@/types/mongoose/nex-account'; +import { INEXAccount, INEXAccountMethods, NEXAccountModel } from '@/types/mongoose/nex-account'; const NEXAccountSchema = new Schema({ device_type: { @@ -39,12 +39,12 @@ NEXAccountSchema.plugin(uniqueValidator, { message: '{PATH} already in use.' }); and the next few accounts counting down seem to be admin, service and internal test accounts */ NEXAccountSchema.method('generatePID', async function generatePID(): Promise { - const min: number = 1000000000; // The console (WiiU) seems to not accept PIDs smaller than this - const max: number = 1799999999; + const min = 1000000000; // The console (WiiU) seems to not accept PIDs smaller than this + const max = 1799999999; - const pid: number = Math.floor(Math.random() * (max - min + 1) + min); + const pid = Math.floor(Math.random() * (max - min + 1) + min); - const inuse: HydratedNEXAccountDocument | null = await NEXAccount.findOne({ pid }); + const inuse = await NEXAccount.findOne({ pid }); if (inuse) { await this.generatePID(); @@ -55,13 +55,13 @@ NEXAccountSchema.method('generatePID', async function generatePID(): Promise('NEXAccount', NEXAccountSchema); \ No newline at end of file +export const NEXAccount = model('NEXAccount', NEXAccountSchema); \ No newline at end of file diff --git a/src/models/pnid.ts b/src/models/pnid.ts index e3054cc..1e19629 100644 --- a/src/models/pnid.ts +++ b/src/models/pnid.ts @@ -9,7 +9,7 @@ import Stripe from 'stripe'; import { DeviceSchema } from '@/models/device'; import { uploadCDNAsset } from '@/util'; import { LOG_ERROR, LOG_WARN } from '@/logger'; -import { HydratedPNIDDocument, IPNID, IPNIDMethods, PNIDModel } from '@/types/mongoose/pnid'; +import { IPNID, IPNIDMethods, PNIDModel } from '@/types/mongoose/pnid'; import { PNIDPermissionFlag } from '@/types/common/permission-flags'; import { config } from '@/config-manager'; @@ -133,12 +133,12 @@ PNIDSchema.plugin(uniqueValidator, {message: '{PATH} already in use.'}); and the next few accounts counting down seem to be admin, service and internal test accounts */ PNIDSchema.method('generatePID', async function generatePID(): Promise { - const min: number = 1000000000; // The console (WiiU) seems to not accept PIDs smaller than this - const max: number = 1799999999; + const min = 1000000000; // The console (WiiU) seems to not accept PIDs smaller than this + const max = 1799999999; - const pid: number = Math.floor(Math.random() * (max - min + 1) + min); + const pid = Math.floor(Math.random() * (max - min + 1) + min); - const inuse: HydratedPNIDDocument | null = await PNID.findOne({ + const inuse = await PNID.findOne({ pid }); @@ -152,15 +152,15 @@ PNIDSchema.method('generatePID', async function generatePID(): Promise { PNIDSchema.method('generateEmailValidationCode', async function generateEmailValidationCode(): Promise { // WiiU passes the PID along with the email code // Does not actually need to be unique to all users - const code: string = Math.random().toFixed(6).split('.')[1]; // Dirty one-liner to generate numbers of 6 length and padded 0 + const code = Math.random().toFixed(6).split('.')[1]; // Dirty one-liner to generate numbers of 6 length and padded 0 this.identification.email_code = code; }); PNIDSchema.method('generateEmailValidationToken', async function generateEmailValidationToken(): Promise { - const token: string = crypto.randomBytes(32).toString('hex'); + const token = crypto.randomBytes(32).toString('hex'); - const inuse: HydratedPNIDDocument | null = await PNID.findOne({ + const inuse = await PNID.findOne({ 'identification.email_token': token }); @@ -185,40 +185,40 @@ PNIDSchema.method('updateMii', async function updateMii({ name, primary, data }: }); PNIDSchema.method('generateMiiImages', async function generateMiiImages(): Promise { - const miiData: string = this.mii.data; - const mii: Mii = new Mii(Buffer.from(miiData, 'base64')); - const miiStudioUrl: string = mii.studioUrl({ + const miiData = this.mii.data; + const mii = new Mii(Buffer.from(miiData, 'base64')); + const miiStudioUrl = mii.studioUrl({ type: 'face', width: 128, instanceCount: 1, }); - const miiStudioNormalFaceImageData: Buffer = await got(miiStudioUrl).buffer(); - const pngData: ImageData = await imagePixels(miiStudioNormalFaceImageData); - const tga: Buffer = TGA.createTgaBuffer(pngData.width, pngData.height, Uint8Array.from(pngData.data), false); + const miiStudioNormalFaceImageData = await got(miiStudioUrl).buffer(); + const pngData = await imagePixels(miiStudioNormalFaceImageData); + const tga = TGA.createTgaBuffer(pngData.width, pngData.height, Uint8Array.from(pngData.data), false); - const userMiiKey: string = `mii/${this.pid}`; + const userMiiKey = `mii/${this.pid}`; await uploadCDNAsset('pn-cdn', `${userMiiKey}/standard.tga`, tga, 'public-read'); await uploadCDNAsset('pn-cdn', `${userMiiKey}/normal_face.png`, miiStudioNormalFaceImageData, 'public-read'); - const expressions: string[] = ['frustrated', 'smile_open_mouth', 'wink_left', 'sorrow', 'surprise_open_mouth']; + const expressions = ['frustrated', 'smile_open_mouth', 'wink_left', 'sorrow', 'surprise_open_mouth']; for (const expression of expressions) { - const miiStudioExpressionUrl: string = mii.studioUrl({ + const miiStudioExpressionUrl = mii.studioUrl({ type: 'face', expression: expression, width: 128, instanceCount: 1, }); - const miiStudioExpressionImageData: Buffer = await got(miiStudioExpressionUrl).buffer(); + const miiStudioExpressionImageData = await got(miiStudioExpressionUrl).buffer(); await uploadCDNAsset('pn-cdn', `${userMiiKey}/${expression}.png`, miiStudioExpressionImageData, 'public-read'); } - const miiStudioBodyUrl: string = mii.studioUrl({ + const miiStudioBodyUrl = mii.studioUrl({ type: 'all_body', width: 270, instanceCount: 1, }); - const miiStudioBodyImageData: Buffer = await got(miiStudioBodyUrl).buffer(); + const miiStudioBodyImageData = await got(miiStudioBodyUrl).buffer(); await uploadCDNAsset('pn-cdn', `${userMiiKey}/body.png`, miiStudioBodyImageData, 'public-read'); }); @@ -290,4 +290,4 @@ PNIDSchema.method('clearPermission', function clearPermission(flag: PNIDPermissi this.permissions &= ~flag; }); -export const PNID: PNIDModel = model('PNID', PNIDSchema); \ No newline at end of file +export const PNID = model('PNID', PNIDSchema); \ No newline at end of file diff --git a/src/models/server.ts b/src/models/server.ts index afdd9af..3ab6fce 100644 --- a/src/models/server.ts +++ b/src/models/server.ts @@ -18,4 +18,4 @@ const ServerSchema = new Schema({ ServerSchema.plugin(uniqueValidator, { message: '{PATH} already in use.' }); -export const Server: ServerModel = model('Server', ServerSchema); \ No newline at end of file +export const Server = model('Server', ServerSchema); \ No newline at end of file diff --git a/src/nintendo-certificate.ts b/src/nintendo-certificate.ts index ba15762..da1741c 100644 --- a/src/nintendo-certificate.ts +++ b/src/nintendo-certificate.ts @@ -120,7 +120,7 @@ class NintendoCertificate { // * Assume regular certificate this.signatureType = this._certificate.readUInt32BE(0x00); - const signatureTypeSizes: SignatureSize = this._signatureTypeSizes(this.signatureType); + const signatureTypeSizes = this._signatureTypeSizes(this.signatureType); this._certificateBody = this._certificate.subarray(0x4 + signatureTypeSizes.SIZE + signatureTypeSizes.PADDING_SIZE); @@ -180,7 +180,7 @@ class NintendoCertificate { } _verifySignatureRSA4096(): void { - const publicKey: NodeRSA = new NodeRSA(); + const publicKey = new NodeRSA(); publicKey.importKey({ n: this.publicKeyData.subarray(0x0, 0x200), @@ -191,7 +191,7 @@ class NintendoCertificate { } _verifySignatureRSA2048(): void { - const publicKey: NodeRSA = new NodeRSA(); + const publicKey = new NodeRSA(); publicKey.importKey({ n: this.publicKeyData.subarray(0x0, 0x100), @@ -206,8 +206,8 @@ class NintendoCertificate { // from bytes to PEM! // https://github.com/Myriachan _verifySignatureECDSA(): void { - const pem: string = this.consoleType === 'wiiu' ? WIIU_DEVICE_PUB_PEM : CTR_DEVICE_PUB_PEM; - const key: crypto.VerifyPublicKeyInput = { + const pem = this.consoleType === 'wiiu' ? WIIU_DEVICE_PUB_PEM : CTR_DEVICE_PUB_PEM; + const key = { key: pem, dsaEncoding: 'ieee-p1363' as crypto.DSAEncoding }; @@ -216,7 +216,7 @@ class NintendoCertificate { } _verifySignatureLFCS(): void { - const publicKey: NodeRSA = new NodeRSA(); + const publicKey = new NodeRSA(); publicKey.importKey({ n: CTR_LFCS_B_PUB, diff --git a/src/server.ts b/src/server.ts index ad5bd83..e496b74 100644 --- a/src/server.ts +++ b/src/server.ts @@ -25,7 +25,7 @@ import assets from '@/services/assets'; import { config } from '@/config-manager'; -const app: express.Express = express(); +const app = express(); // START APPLICATION @@ -51,8 +51,8 @@ app.use(assets); // 404 handler LOG_INFO('Creating 404 status handler'); app.use((request: express.Request, response: express.Response): void => { - const url: string = fullUrl(request); - let deviceId: string | undefined = getValueFromHeaders(request.headers, 'X-Nintendo-Device-ID'); + const url = fullUrl(request); + let deviceId = getValueFromHeaders(request.headers, 'X-Nintendo-Device-ID'); if (!deviceId) { deviceId = 'Unknown'; @@ -78,9 +78,9 @@ app.use((request: express.Request, response: express.Response): void => { // non-404 error handler LOG_INFO('Creating non-404 status handler'); app.use((error: any, request: express.Request, response: express.Response, _next: express.NextFunction): void => { - const status: number = error.status || 500; - const url: string = fullUrl(request); - let deviceId: string | undefined = getValueFromHeaders(request.headers, 'X-Nintendo-Device-ID'); + const status = error.status || 500; + const url = fullUrl(request); + let deviceId = getValueFromHeaders(request.headers, 'X-Nintendo-Device-ID'); if (!deviceId) { deviceId = 'Unknown'; diff --git a/src/services/api/index.ts b/src/services/api/index.ts index b849f3e..45efc53 100644 --- a/src/services/api/index.ts +++ b/src/services/api/index.ts @@ -7,7 +7,7 @@ import { LOG_INFO } from '@/logger'; import { V1 } from '@/services/api/routes'; // Router to handle the subdomain restriction -const api: express.Router = express.Router(); +const api = express.Router(); LOG_INFO('[USER API] Importing middleware'); api.use(APIMiddleware); @@ -26,7 +26,7 @@ api.use('/v1/user', V1.USER); // Main router for endpoints -const router: express.Router = express.Router(); +const router = express.Router(); // Create subdomains LOG_INFO('[USER API] Creating \'api\' subdomain'); diff --git a/src/services/api/routes/v1/connections.ts b/src/services/api/routes/v1/connections.ts index 92c3fd8..2a0612a 100644 --- a/src/services/api/routes/v1/connections.ts +++ b/src/services/api/routes/v1/connections.ts @@ -1,12 +1,9 @@ import express from 'express'; import { addPNIDConnection, removePNIDConnection } from '@/database'; -import { ConnectionData } from '@/types/services/api/connection-data'; -import { ConnectionResponse } from '@/types/services/api/connection-response'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; -const router: express.Router = express.Router(); +const router = express.Router(); -const VALID_CONNECTION_TYPES: string[] = [ +const VALID_CONNECTION_TYPES = [ 'discord' ]; @@ -16,9 +13,9 @@ const VALID_CONNECTION_TYPES: string[] = [ * Description: Adds an account connection to the users PNID */ router.post('/add/:type', async (request: express.Request, response: express.Response): Promise => { - const data: ConnectionData = request.body?.data; - const pnid: HydratedPNIDDocument | null = request.pnid; - const type: string = request.params.type; + const data = request.body?.data; + const pnid = request.pnid; + const type = request.params.type; if (!pnid) { response.status(400).json({ @@ -50,7 +47,7 @@ router.post('/add/:type', async (request: express.Request, response: express.Res return; } - let result: ConnectionResponse | undefined = await addPNIDConnection(pnid, data, type); + let result = await addPNIDConnection(pnid, data, type); if (!result) { result = { @@ -69,8 +66,8 @@ router.post('/add/:type', async (request: express.Request, response: express.Res * Description: Removes an account connection from the users PNID */ router.delete('/remove/:type', async (request: express.Request, response: express.Response): Promise => { - const pnid: HydratedPNIDDocument | null = request.pnid; - const type: string = request.params.type; + const pnid = request.pnid; + const type = request.params.type; if (!pnid) { response.status(400).json({ @@ -92,7 +89,7 @@ router.delete('/remove/:type', async (request: express.Request, response: expres return; } - let result: ConnectionResponse | undefined = await removePNIDConnection(pnid, type); + let result = await removePNIDConnection(pnid, type); if (!result) { result = { diff --git a/src/services/api/routes/v1/email.ts b/src/services/api/routes/v1/email.ts index b0b41f3..fa306c5 100644 --- a/src/services/api/routes/v1/email.ts +++ b/src/services/api/routes/v1/email.ts @@ -2,12 +2,11 @@ import express from 'express'; import moment from 'moment'; import { PNID } from '@/models/pnid'; import { getValueFromQueryString, sendEmailConfirmedEmail } from '@/util'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; -const router: express.Router = express.Router(); +const router = express.Router(); router.get('/verify', async (request: express.Request, response: express.Response): Promise => { - const token: string | undefined = getValueFromQueryString(request.query, 'token'); + const token = getValueFromQueryString(request.query, 'token'); if (!token || token.trim() == '') { response.status(400).json({ @@ -19,7 +18,7 @@ router.get('/verify', async (request: express.Request, response: express.Respons return; } - const pnid: HydratedPNIDDocument | null = await PNID.findOne({ + const pnid = await PNID.findOne({ 'identification.email_token': token }); @@ -33,7 +32,7 @@ router.get('/verify', async (request: express.Request, response: express.Respons return; } - const validatedDate: string = moment().format('YYYY-MM-DDTHH:MM:SS'); + const validatedDate = moment().format('YYYY-MM-DDTHH:MM:SS'); pnid.email.reachable = true; pnid.email.validated = true; diff --git a/src/services/api/routes/v1/forgotPassword.ts b/src/services/api/routes/v1/forgotPassword.ts index 521bc56..58838bb 100644 --- a/src/services/api/routes/v1/forgotPassword.ts +++ b/src/services/api/routes/v1/forgotPassword.ts @@ -4,10 +4,10 @@ import { getPNIDByEmailAddress, getPNIDByUsername } from '@/database'; import { sendForgotPasswordEmail } from '@/util'; import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; -const router: express.Router = express.Router(); +const router = express.Router(); router.post('/', async (request: express.Request, response: express.Response): Promise => { - const input: string = request.body?.input; + const input = request.body?.input; if (!input || input.trim() === '') { response.status(400).json({ diff --git a/src/services/api/routes/v1/login.ts b/src/services/api/routes/v1/login.ts index 03e47bb..21a92b6 100644 --- a/src/services/api/routes/v1/login.ts +++ b/src/services/api/routes/v1/login.ts @@ -3,10 +3,9 @@ import bcrypt from 'bcrypt'; import { getPNIDByUsername, getPNIDByTokenAuth } from '@/database'; import { nintendoPasswordHash, generateToken} from '@/util'; import { config } from '@/config-manager'; -import { TokenOptions } from '@/types/common/token-options'; import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; -const router: express.Router = express.Router(); +const router = express.Router(); /** * [POST] @@ -15,10 +14,10 @@ const router: express.Router = express.Router(); * TODO: Replace this with a more robust OAuth2 implementation */ router.post('/', async (request: express.Request, response: express.Response): Promise => { - const grantType: string = request.body?.grant_type; - const username: string = request.body?.username; - const password: string = request.body?.password; - const refreshToken: string = request.body?.refresh_token; + const grantType = request.body?.grant_type; + const username = request.body?.username; + const password = request.body?.password; + const refreshToken = request.body?.refresh_token; if (!['password', 'refresh_token'].includes(grantType)) { response.status(400).json({ @@ -75,7 +74,7 @@ router.post('/', async (request: express.Request, response: express.Response): P return; } - const hashedPassword: string = nintendoPasswordHash(password, pnid.pid); + const hashedPassword = nintendoPasswordHash(password, pnid.pid); if (!pnid || !bcrypt.compareSync(hashedPassword, pnid.password)) { response.status(400).json({ @@ -100,7 +99,7 @@ router.post('/', async (request: express.Request, response: express.Response): P } } - const accessTokenOptions: TokenOptions = { + const accessTokenOptions = { system_type: 0x3, // * API token_type: 0x1, // * OAuth Access pid: pnid.pid, @@ -109,7 +108,7 @@ router.post('/', async (request: express.Request, response: express.Response): P expire_time: BigInt(Date.now() + (3600 * 1000)) }; - const refreshTokenOptions: TokenOptions = { + const refreshTokenOptions = { system_type: 0x3, // * API token_type: 0x2, // * OAuth Refresh pid: pnid.pid, @@ -118,11 +117,11 @@ router.post('/', async (request: express.Request, response: express.Response): P expire_time: BigInt(Date.now() + (3600 * 1000)) }; - const accessTokenBuffer: Buffer | null = await generateToken(config.aes_key, accessTokenOptions); - const refreshTokenBuffer: Buffer | null = await generateToken(config.aes_key, refreshTokenOptions); + const accessTokenBuffer = await generateToken(config.aes_key, accessTokenOptions); + const refreshTokenBuffer = await generateToken(config.aes_key, refreshTokenOptions); - const accessToken: string = accessTokenBuffer ? accessTokenBuffer.toString('hex') : ''; - const newRefreshToken: string = refreshTokenBuffer ? refreshTokenBuffer.toString('hex') : ''; + const accessToken = accessTokenBuffer ? accessTokenBuffer.toString('hex') : ''; + const newRefreshToken = refreshTokenBuffer ? refreshTokenBuffer.toString('hex') : ''; // TODO - Handle null tokens diff --git a/src/services/api/routes/v1/register.ts b/src/services/api/routes/v1/register.ts index 7dd89ba..12a1b5e 100644 --- a/src/services/api/routes/v1/register.ts +++ b/src/services/api/routes/v1/register.ts @@ -6,31 +6,29 @@ import bcrypt from 'bcrypt'; import moment from 'moment'; import hcaptcha from 'hcaptcha'; import Mii from 'mii-js'; -import mongoose from 'mongoose'; import { doesPNIDExist, connection as databaseConnection } from '@/database'; import { nintendoPasswordHash, sendConfirmationEmail, generateToken } from '@/util'; import { LOG_ERROR } from '@/logger'; import { PNID } from '@/models/pnid'; import { NEXAccount } from '@/models/nex-account'; import { config, disabledFeatures } from '@/config-manager'; -import { TokenOptions } from '@/types/common/token-options'; import { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; -const router: express.Router = express.Router(); +const router = express.Router(); -const PNID_VALID_CHARACTERS_REGEX: RegExp = /^[\w\-.]*$/; -const PNID_PUNCTUATION_START_REGEX: RegExp = /^[_\-.]/; -const PNID_PUNCTUATION_END_REGEX: RegExp = /[_\-.]$/; -const PNID_PUNCTUATION_DUPLICATE_REGEX: RegExp = /[_\-.]{2,}/; +const PNID_VALID_CHARACTERS_REGEX = /^[\w\-.]*$/; +const PNID_PUNCTUATION_START_REGEX = /^[_\-.]/; +const PNID_PUNCTUATION_END_REGEX = /[_\-.]$/; +const PNID_PUNCTUATION_DUPLICATE_REGEX = /[_\-.]{2,}/; // This sucks -const PASSWORD_WORD_OR_NUMBER_REGEX: RegExp = /(?=.*[a-zA-Z])(?=.*\d).*/; -const PASSWORD_WORD_OR_PUNCTUATION_REGEX: RegExp = /(?=.*[a-zA-Z])(?=.*[_\-.]).*/; -const PASSWORD_NUMBER_OR_PUNCTUATION_REGEX: RegExp = /(?=.*\d)(?=.*[_\-.]).*/; -const PASSWORD_REPEATED_CHARACTER_REGEX: RegExp = /(.)\1\1/; +const PASSWORD_WORD_OR_NUMBER_REGEX = /(?=.*[a-zA-Z])(?=.*\d).*/; +const PASSWORD_WORD_OR_PUNCTUATION_REGEX = /(?=.*[a-zA-Z])(?=.*[_\-.]).*/; +const PASSWORD_NUMBER_OR_PUNCTUATION_REGEX = /(?=.*\d)(?=.*[_\-.]).*/; +const PASSWORD_REPEATED_CHARACTER_REGEX = /(.)\1\1/; -const DEFAULT_MII_DATA: Buffer = Buffer.from('AwAAQOlVognnx0GC2/uogAOzuI0n2QAAAEBEAGUAZgBhAHUAbAB0AAAAAAAAAEBAAAAhAQJoRBgmNEYUgRIXaA0AACkAUkhQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGm9', 'base64'); +const DEFAULT_MII_DATA = Buffer.from('AwAAQOlVognnx0GC2/uogAOzuI0n2QAAAEBEAGUAZgBhAHUAbAB0AAAAAAAAAEBAAAAhAQJoRBgmNEYUgRIXaA0AACkAUkhQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGm9', 'base64'); /** * [POST] @@ -38,12 +36,12 @@ const DEFAULT_MII_DATA: Buffer = Buffer.from('AwAAQOlVognnx0GC2/uogAOzuI0n2QAAAE * Description: Creates a new user PNID */ router.post('/', async (request: express.Request, response: express.Response): Promise => { - const email: string = request.body.email?.trim(); - const username: string = request.body.username?.trim(); - const miiName: string = request.body.mii_name?.trim(); - const password: string = request.body.password?.trim(); - const passwordConfirm: string = request.body.password_confirm?.trim(); - const hCaptchaResponse: string = request.body.hCaptchaResponse?.trim(); + const email = request.body.email?.trim(); + const username = request.body.username?.trim(); + const miiName = request.body.mii_name?.trim(); + const password = request.body.password?.trim(); + const passwordConfirm = request.body.password_confirm?.trim(); + const hCaptchaResponse = request.body.hCaptchaResponse?.trim(); if (!disabledFeatures.captcha) { if (!hCaptchaResponse || hCaptchaResponse === '') { @@ -56,7 +54,7 @@ router.post('/', async (request: express.Request, response: express.Response): P return; } - const captchaVerify: VerifyResponse = await hcaptcha.verify(config.hcaptcha.secret, hCaptchaResponse); + const captchaVerify = await hcaptcha.verify(config.hcaptcha.secret, hCaptchaResponse); if (!captchaVerify.success) { response.status(400).json({ @@ -160,7 +158,7 @@ router.post('/', async (request: express.Request, response: express.Response): P return; } - const userExists: boolean = await doesPNIDExist(username); + const userExists = await doesPNIDExist(username); if (userExists) { response.status(400).json({ @@ -252,7 +250,7 @@ router.post('/', async (request: express.Request, response: express.Response): P return; } - const miiNameBuffer: Buffer = Buffer.from(miiName, 'utf16le'); // UTF8 to UTF16 + const miiNameBuffer = Buffer.from(miiName, 'utf16le'); // UTF8 to UTF16 if (miiNameBuffer.length > 0x14) { response.status(400).json({ @@ -264,14 +262,14 @@ router.post('/', async (request: express.Request, response: express.Response): P return; } - const mii: Mii = new Mii(DEFAULT_MII_DATA); + const mii = new Mii(DEFAULT_MII_DATA); mii.miiName = miiName; - const creationDate: string = moment().format('YYYY-MM-DDTHH:MM:SS'); + const creationDate = moment().format('YYYY-MM-DDTHH:MM:SS'); let pnid: HydratedPNIDDocument; let nexAccount: HydratedNEXAccountDocument; - const session: mongoose.ClientSession = await databaseConnection().startSession(); + const session = await databaseConnection().startSession(); await session.startTransaction(); try { @@ -293,8 +291,8 @@ router.post('/', async (request: express.Request, response: express.Response): P await nexAccount.save({ session }); - const primaryPasswordHash: string = nintendoPasswordHash(password, nexAccount.pid); - const passwordHash: string = await bcrypt.hash(primaryPasswordHash, 10); + const primaryPasswordHash = nintendoPasswordHash(password, nexAccount.pid); + const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); pnid = new PNID({ pid: nexAccount.pid, @@ -367,7 +365,7 @@ router.post('/', async (request: express.Request, response: express.Response): P await sendConfirmationEmail(pnid); - const accessTokenOptions: TokenOptions = { + const accessTokenOptions = { system_type: 0x3, // * API token_type: 0x1, // * OAuth Access pid: pnid.pid, @@ -376,7 +374,7 @@ router.post('/', async (request: express.Request, response: express.Response): P expire_time: BigInt(Date.now() + (3600 * 1000)) }; - const refreshTokenOptions: TokenOptions = { + const refreshTokenOptions = { system_type: 0x3, // * API token_type: 0x2, // * OAuth Refresh pid: pnid.pid, @@ -385,11 +383,11 @@ router.post('/', async (request: express.Request, response: express.Response): P expire_time: BigInt(Date.now() + (3600 * 1000)) }; - const accessTokenBuffer: Buffer | null = await generateToken(config.aes_key, accessTokenOptions); - const refreshTokenBuffer: Buffer | null = await generateToken(config.aes_key, refreshTokenOptions); + const accessTokenBuffer = await generateToken(config.aes_key, accessTokenOptions); + const refreshTokenBuffer = await generateToken(config.aes_key, refreshTokenOptions); - const accessToken: string = accessTokenBuffer ? accessTokenBuffer.toString('hex') : ''; - const refreshToken: string = refreshTokenBuffer ? refreshTokenBuffer.toString('hex') : ''; + const accessToken = accessTokenBuffer ? accessTokenBuffer.toString('hex') : ''; + const refreshToken = refreshTokenBuffer ? refreshTokenBuffer.toString('hex') : ''; // TODO - Handle null tokens diff --git a/src/services/api/routes/v1/resetPassword.ts b/src/services/api/routes/v1/resetPassword.ts index 7b1aa18..025ca64 100644 --- a/src/services/api/routes/v1/resetPassword.ts +++ b/src/services/api/routes/v1/resetPassword.ts @@ -3,20 +3,19 @@ import bcrypt from 'bcrypt'; import { PNID } from '@/models/pnid'; import { decryptToken, unpackToken, nintendoPasswordHash } from '@/util'; import { Token } from '@/types/common/token'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; -const router: express.Router = express.Router(); +const router = express.Router(); // This sucks -const PASSWORD_WORD_OR_NUMBER_REGEX: RegExp = /(?=.*[a-zA-Z])(?=.*\d).*/; -const PASSWORD_WORD_OR_PUNCTUATION_REGEX: RegExp = /(?=.*[a-zA-Z])(?=.*[_\-.]).*/; -const PASSWORD_NUMBER_OR_PUNCTUATION_REGEX: RegExp = /(?=.*\d)(?=.*[_\-.]).*/; -const PASSWORD_REPEATED_CHARACTER_REGEX: RegExp = /(.)\1\1/; +const PASSWORD_WORD_OR_NUMBER_REGEX = /(?=.*[a-zA-Z])(?=.*\d).*/; +const PASSWORD_WORD_OR_PUNCTUATION_REGEX = /(?=.*[a-zA-Z])(?=.*[_\-.]).*/; +const PASSWORD_NUMBER_OR_PUNCTUATION_REGEX = /(?=.*\d)(?=.*[_\-.]).*/; +const PASSWORD_REPEATED_CHARACTER_REGEX = /(.)\1\1/; router.post('/', async (request: express.Request, response: express.Response): Promise => { - const password: string = request.body.password?.trim(); - const passwordConfirm: string = request.body.password_confirm?.trim(); - const token: string = request.body.token?.trim(); + const password = request.body.password?.trim(); + const passwordConfirm = request.body.password_confirm?.trim(); + const token = request.body.token?.trim(); if (!token || token === '') { response.status(400).json({ @@ -30,7 +29,7 @@ router.post('/', async (request: express.Request, response: express.Response): P let unpackedToken: Token; try { - const decryptedToken: Buffer = await decryptToken(Buffer.from(token, 'hex')); + const decryptedToken = await decryptToken(Buffer.from(token, 'hex')); unpackedToken = unpackToken(decryptedToken); } catch (error) { response.status(400).json({ @@ -52,7 +51,7 @@ router.post('/', async (request: express.Request, response: express.Response): P return; } - const pnid: HydratedPNIDDocument | null = await PNID.findOne({ pid: unpackedToken.pid }); + const pnid = await PNID.findOne({ pid: unpackedToken.pid }); if (!pnid) { response.status(400).json({ @@ -135,8 +134,8 @@ router.post('/', async (request: express.Request, response: express.Response): P return; } - const primaryPasswordHash: string = nintendoPasswordHash(password, pnid.pid); - const passwordHash: string = await bcrypt.hash(primaryPasswordHash, 10); + const primaryPasswordHash = nintendoPasswordHash(password, pnid.pid); + const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); pnid.password = passwordHash; diff --git a/src/services/api/routes/v1/user.ts b/src/services/api/routes/v1/user.ts index 0622763..0c27e88 100644 --- a/src/services/api/routes/v1/user.ts +++ b/src/services/api/routes/v1/user.ts @@ -3,10 +3,9 @@ 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(); +const router = express.Router(); // TODO - Extend this later with more settings const userSchema = z.object({ @@ -24,7 +23,7 @@ const userSchema = z.object({ * Description: Gets PNID details about the current user */ router.get('/', async (request: express.Request, response: express.Response): Promise => { - const pnid: HydratedPNIDDocument | null = request.pnid; + const pnid = request.pnid; if (!pnid) { response.status(400).json({ @@ -74,7 +73,7 @@ router.get('/', async (request: express.Request, response: express.Response): Pr * Description: Updates PNID certain details about the current user */ router.post('/', async (request: express.Request, response: express.Response): Promise => { - const pnid: HydratedPNIDDocument | null = request.pnid; + const pnid = request.pnid; const updateUserRequest: UpdateUserRequest = request.body; if (!pnid) { @@ -100,7 +99,7 @@ router.post('/', async (request: express.Request, response: express.Response): P } if (result.data.mii) { - const miiNameBuffer: Buffer = Buffer.from(result.data.mii.name, 'utf16le'); // * UTF8 to UTF16 + const miiNameBuffer = Buffer.from(result.data.mii.name, 'utf16le'); // * UTF8 to UTF16 if (miiNameBuffer.length < 1) { response.status(400).json({ @@ -123,7 +122,7 @@ router.post('/', async (request: express.Request, response: express.Response): P } try { - const miiDataBuffer: Buffer = Buffer.from(result.data.mii.data, 'base64'); + const miiDataBuffer = Buffer.from(result.data.mii.data, 'base64'); if (miiDataBuffer.length < 0x60) { response.status(400).json({ @@ -145,7 +144,7 @@ router.post('/', async (request: express.Request, response: express.Response): P return; } - const mii: Mii = new Mii(miiDataBuffer); + const mii = new Mii(miiDataBuffer); mii.validate(); } catch (_) { response.status(400).json({ @@ -167,7 +166,7 @@ router.post('/', async (request: express.Request, response: express.Response): P const updateData: Record = {}; if (result.data.environment) { - const environment: string = result.data.environment; + const environment = result.data.environment; if (environment === 'test' && pnid.access_level < 1) { response.status(400).json({ diff --git a/src/services/assets/index.ts b/src/services/assets/index.ts index 03faa93..22be241 100644 --- a/src/services/assets/index.ts +++ b/src/services/assets/index.ts @@ -6,14 +6,14 @@ import subdomain from 'express-subdomain'; import { LOG_INFO } from '@/logger'; // Router to handle the subdomain restriction -const assets: express.Router = express.Router(); +const assets = express.Router(); // Setup public folder LOG_INFO('[assets] Setting up public folder'); assets.use(express.static(path.join(__dirname, '../../assets'))); // Main router for endpoints -const router: express.Router = express.Router(); +const router = express.Router(); // Create subdomains LOG_INFO('[conntest] Creating \'assets\' subdomain'); diff --git a/src/services/cbvc/index.ts b/src/services/cbvc/index.ts index c3e5472..5116f93 100644 --- a/src/services/cbvc/index.ts +++ b/src/services/cbvc/index.ts @@ -5,7 +5,7 @@ import subdomain from 'express-subdomain'; import { LOG_INFO } from '@/logger'; // Router to handle the subdomain restriction -const cbvc: express.Router = express.Router(); +const cbvc = express.Router(); // Setup route LOG_INFO('[cbvc] Applying imported routes'); @@ -22,7 +22,7 @@ cbvc.get('/:consoleType/:unknown/:region', (request: express.Request, response: }); // Main router for endpoints -const router: express.Router = express.Router(); +const router = express.Router(); // Create subdomains LOG_INFO('[cbvc] Creating \'cbvc\' subdomain'); diff --git a/src/services/conntest/index.ts b/src/services/conntest/index.ts index 75784cc..8b5f68a 100644 --- a/src/services/conntest/index.ts +++ b/src/services/conntest/index.ts @@ -5,7 +5,7 @@ import subdomain from 'express-subdomain'; import { LOG_INFO } from '@/logger'; // Router to handle the subdomain restriction -const conntest: express.Router = express.Router(); +const conntest = express.Router(); // Setup route LOG_INFO('[conntest] Applying imported routes'); @@ -27,7 +27,7 @@ This is test.html page }); // Main router for endpoints -const router: express.Router = express.Router(); +const router = express.Router(); // Create subdomains LOG_INFO('[conntest] Creating \'conntest\' subdomain'); diff --git a/src/services/datastore/index.ts b/src/services/datastore/index.ts index 3d2e4f7..35b9ade 100644 --- a/src/services/datastore/index.ts +++ b/src/services/datastore/index.ts @@ -5,14 +5,14 @@ import { LOG_INFO } from '@/logger'; import upload from '@/services/datastore/routes/upload'; // Router to handle the subdomain -const datastore: express.Router = express.Router(); +const datastore = express.Router(); // Setup routes LOG_INFO('[DATASTORE] Applying imported routes'); datastore.use(upload); // Main router for endpoints -const router: express.Router = express.Router(); +const router = express.Router(); // Create subdomains LOG_INFO('[DATASTORE] Creating \'datastore\' subdomain'); diff --git a/src/services/datastore/routes/upload.ts b/src/services/datastore/routes/upload.ts index 3ceccda..09119d6 100644 --- a/src/services/datastore/routes/upload.ts +++ b/src/services/datastore/routes/upload.ts @@ -4,32 +4,32 @@ import express from 'express'; import Dicer from 'dicer'; import { uploadCDNAsset } from '@/util'; -const router: express.Router = express.Router(); +const router = express.Router(); -const signatureSecret: Buffer = fs.readFileSync(`${__dirname}/../../../../certs/nex/datastore/secret.key`); +const signatureSecret = fs.readFileSync(`${__dirname}/../../../../certs/nex/datastore/secret.key`); function multipartParser(request: express.Request, response: express.Response, next: express.NextFunction): void { - const RE_BOUNDARY: RegExp = /^multipart\/.+?(?:; boundary=(?:(?:"(.+)")|(?:([^\s]+))))$/i; - const RE_FILE_NAME: RegExp = /name="(.*)"/; + const RE_BOUNDARY = /^multipart\/.+?(?:; boundary=(?:(?:"(.+)")|(?:([^\s]+))))$/i; + const RE_FILE_NAME = /name="(.*)"/; - const contentType: string | undefined = request.header('content-type'); + const contentType = request.header('content-type'); if (!contentType) { return next(); } - const boundary: RegExpExecArray | null = RE_BOUNDARY.exec(contentType); + const boundary = RE_BOUNDARY.exec(contentType); if (!boundary) { return next(); } - const dicer: Dicer = new Dicer({ boundary: boundary[1] || boundary[2] }); - const files: { [key: string]: Buffer } = {}; + const dicer = new Dicer({ boundary: boundary[1] || boundary[2] }); + const files: Record = {}; dicer.on('part', (part: Dicer.PartStream) => { - let fileBuffer: Buffer = Buffer.alloc(0); - let fileName: string = ''; + let fileBuffer = Buffer.alloc(0); + let fileName = ''; part.on('header', header => { const contentDisposition = header['content-disposition' as keyof object]; @@ -67,26 +67,26 @@ router.post('/upload', multipartParser, async (request: express.Request, respons return; } - const bucket: string = request.files.bucket.toString(); - const key: string = request.files.key.toString(); - const file: Buffer = request.files.file; - const acl: string = request.files.acl.toString(); - const pid: string = request.files.pid.toString(); - const date: string = request.files.date.toString(); - const signature: string = request.files.signature.toString(); + const bucket = request.files.bucket.toString(); + const key = request.files.key.toString(); + const file = request.files.file; + const acl = request.files.acl.toString(); + const pid = request.files.pid.toString(); + const date = request.files.date.toString(); + const signature = request.files.signature.toString(); // Signatures only good for 1 minute - const minute: number = 1000 * 60; - const minuteAgo: number = Date.now() - minute; + const minute = 1000 * 60; + const minuteAgo = Date.now() - minute; if (Number(date) < Math.floor(minuteAgo / 1000)) { response.sendStatus(400); return; } - const data: string = `${pid}${bucket}${key}${date}`; + const data = `${pid}${bucket}${key}${date}`; - const hmac: string = crypto.createHmac('sha256', signatureSecret).update(data).digest('hex'); + const hmac = crypto.createHmac('sha256', signatureSecret).update(data).digest('hex'); console.log(hmac, signature); diff --git a/src/services/grpc/account/api-key-middleware.ts b/src/services/grpc/account/api-key-middleware.ts index ee42a13..2a6158d 100644 --- a/src/services/grpc/account/api-key-middleware.ts +++ b/src/services/grpc/account/api-key-middleware.ts @@ -5,7 +5,7 @@ export async function* apiKeyMiddleware( call: ServerMiddlewareCall, context: CallContext, ): AsyncGenerator { - const apiKey: string | undefined = context.metadata.get('X-API-Key'); + const apiKey = context.metadata.get('X-API-Key'); if (!apiKey || apiKey !== config.grpc.master_api_keys.account) { throw new ServerError(Status.UNAUTHENTICATED, 'Missing or invalid API key'); diff --git a/src/services/grpc/account/exchange-token-for-user-data.ts b/src/services/grpc/account/exchange-token-for-user-data.ts index 164a6a3..347c4da 100644 --- a/src/services/grpc/account/exchange-token-for-user-data.ts +++ b/src/services/grpc/account/exchange-token-for-user-data.ts @@ -2,7 +2,6 @@ import { Status, ServerError } from 'nice-grpc'; import { ExchangeTokenForUserDataRequest } from '@pretendonetwork/grpc/account/exchange_token_for_user_data'; import { GetUserDataResponse } from '@pretendonetwork/grpc/account/get_user_data_rpc'; import { getPNIDByTokenAuth } from '@/database'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; import { PNID_PERMISSION_FLAGS } from '@/types/common/permission-flags'; import { config } from '@/config-manager'; @@ -11,7 +10,7 @@ export async function exchangeTokenForUserData(request: ExchangeTokenForUserData throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid token'); } - const pnid: HydratedPNIDDocument | null = await getPNIDByTokenAuth(request.token); + const pnid = await getPNIDByTokenAuth(request.token); if (!pnid) { throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid token'); diff --git a/src/services/grpc/account/get-nex-data.ts b/src/services/grpc/account/get-nex-data.ts index 1731620..38a938d 100644 --- a/src/services/grpc/account/get-nex-data.ts +++ b/src/services/grpc/account/get-nex-data.ts @@ -1,10 +1,9 @@ import { Status, ServerError } from 'nice-grpc'; import {GetNEXDataRequest,GetNEXDataResponse, DeepPartial } from '@pretendonetwork/grpc/account/get_nex_data_rpc'; import { NEXAccount } from '@/models/nex-account'; -import { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; export async function getNEXData(request: GetNEXDataRequest): Promise> { - const nexAccount: HydratedNEXAccountDocument | null = await NEXAccount.findOne({ pid: request.pid }); + const nexAccount = await NEXAccount.findOne({ pid: request.pid }); if (!nexAccount) { throw new ServerError( diff --git a/src/services/grpc/account/get-nex-password.ts b/src/services/grpc/account/get-nex-password.ts index 7a06886..a872d2b 100644 --- a/src/services/grpc/account/get-nex-password.ts +++ b/src/services/grpc/account/get-nex-password.ts @@ -1,10 +1,9 @@ import { Status, ServerError } from 'nice-grpc'; import {GetNEXPasswordRequest,GetNEXPasswordResponse, DeepPartial } from '@pretendonetwork/grpc/account/get_nex_password_rpc'; import { NEXAccount } from '@/models/nex-account'; -import { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; export async function getNEXPassword(request: GetNEXPasswordRequest): Promise> { - const nexAccount: HydratedNEXAccountDocument | null = await NEXAccount.findOne({ pid: request.pid }); + const nexAccount = await NEXAccount.findOne({ pid: request.pid }); if (!nexAccount) { throw new ServerError( diff --git a/src/services/grpc/account/get-user-data.ts b/src/services/grpc/account/get-user-data.ts index 70baca4..80d2704 100644 --- a/src/services/grpc/account/get-user-data.ts +++ b/src/services/grpc/account/get-user-data.ts @@ -1,12 +1,11 @@ import { Status, ServerError } from 'nice-grpc'; import { GetUserDataRequest, GetUserDataResponse } from '@pretendonetwork/grpc/account/get_user_data_rpc'; import { getPNIDByPID } from '@/database'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; import { PNID_PERMISSION_FLAGS } from '@/types/common/permission-flags'; import { config } from '@/config-manager'; export async function getUserData(request: GetUserDataRequest): Promise { - const pnid: HydratedPNIDDocument | null = await getPNIDByPID(request.pid); + const pnid = await getPNIDByPID(request.pid); if (!pnid) { throw new ServerError( diff --git a/src/services/grpc/account/implementation.ts b/src/services/grpc/account/implementation.ts index 8e970d4..37a9dd4 100644 --- a/src/services/grpc/account/implementation.ts +++ b/src/services/grpc/account/implementation.ts @@ -1,11 +1,10 @@ -import { AccountServiceImplementation } from '@pretendonetwork/grpc/account/account_service'; import { getUserData } from '@/services/grpc/account/get-user-data'; import { getNEXPassword } from '@/services/grpc/account/get-nex-password'; import { getNEXData } from '@/services/grpc/account/get-nex-data'; import { updatePNIDPermissions } from '@/services/grpc/account/update-pnid-permissions'; import { exchangeTokenForUserData } from '@/services/grpc/account/exchange-token-for-user-data'; -export const accountServiceImplementation: AccountServiceImplementation = { +export const accountServiceImplementation = { getUserData, getNEXPassword, getNEXData, diff --git a/src/services/grpc/account/update-pnid-permissions.ts b/src/services/grpc/account/update-pnid-permissions.ts index e899021..d547311 100644 --- a/src/services/grpc/account/update-pnid-permissions.ts +++ b/src/services/grpc/account/update-pnid-permissions.ts @@ -3,10 +3,9 @@ import { UpdatePNIDPermissionsRequest } from '@pretendonetwork/grpc/account/upda import { getPNIDByPID } from '@/database'; import { PNID_PERMISSION_FLAGS } from '@/types/common/permission-flags'; import type { Empty } from '@pretendonetwork/grpc/api/google/protobuf/empty'; -import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; export async function updatePNIDPermissions(request: UpdatePNIDPermissionsRequest): Promise { - const pnid: HydratedPNIDDocument | null = await getPNIDByPID(request.pid); + const pnid = await getPNIDByPID(request.pid); if (!pnid) { throw new ServerError( diff --git a/src/services/grpc/api/api-key-middleware.ts b/src/services/grpc/api/api-key-middleware.ts index 19c4e3b..215df34 100644 --- a/src/services/grpc/api/api-key-middleware.ts +++ b/src/services/grpc/api/api-key-middleware.ts @@ -5,7 +5,7 @@ export async function* apiKeyMiddleware( call: ServerMiddlewareCall, context: CallContext, ): AsyncGenerator { - const apiKey: string | undefined = context.metadata.get('X-API-Key'); + const apiKey = context.metadata.get('X-API-Key'); if (!apiKey || apiKey !== config.grpc.master_api_keys.api) { throw new ServerError(Status.UNAUTHENTICATED, 'Missing or invalid API key'); diff --git a/src/services/grpc/api/authentication-middleware.ts b/src/services/grpc/api/authentication-middleware.ts index d0a4405..c466c9e 100644 --- a/src/services/grpc/api/authentication-middleware.ts +++ b/src/services/grpc/api/authentication-middleware.ts @@ -3,7 +3,7 @@ import { getPNIDByTokenAuth } from '@/database'; import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; // * These paths require that a token be present -const TOKEN_REQUIRED_PATHS: string[] = [ +const TOKEN_REQUIRED_PATHS = [ '/api.API/GetUserData', '/api.API/UpdateUserData', '/api.API/ResetPassword', // * This paths token is not an authentication token, it is a password reset token @@ -20,14 +20,14 @@ export async function* authenticationMiddleware( call: ServerMiddlewareCall, context: CallContext, ): AsyncGenerator { - const token: string | undefined = context.metadata.get('X-Token')?.trim(); + const token = context.metadata.get('X-Token')?.trim(); if (!token && TOKEN_REQUIRED_PATHS.includes(call.method.path)) { throw new ServerError(Status.UNAUTHENTICATED, 'Missing or invalid authentication token'); } try { - let pnid: HydratedPNIDDocument | null = null; + let pnid = null; if (token) { pnid = await getPNIDByTokenAuth(token); @@ -42,7 +42,7 @@ export async function* authenticationMiddleware( pnid }); } catch (error) { - let message: string = 'Unknown server error'; + let message = 'Unknown server error'; console.log(error); diff --git a/src/services/grpc/api/forgot-password.ts b/src/services/grpc/api/forgot-password.ts index 7cdbd4f..45b9b6e 100644 --- a/src/services/grpc/api/forgot-password.ts +++ b/src/services/grpc/api/forgot-password.ts @@ -7,7 +7,7 @@ import type { Empty } from '@pretendonetwork/grpc/api/google/protobuf/empty'; import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; export async function forgotPassword(request: ForgotPasswordRequest): Promise { - const input: string = request.emailAddressOrUsername.trim(); + const input = request.emailAddressOrUsername.trim(); if (!input) { throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid or missing input'); diff --git a/src/services/grpc/api/get-user-data.ts b/src/services/grpc/api/get-user-data.ts index 6682c79..150f6cb 100644 --- a/src/services/grpc/api/get-user-data.ts +++ b/src/services/grpc/api/get-user-data.ts @@ -3,11 +3,10 @@ import { GetUserDataResponse, DeepPartial } from '@pretendonetwork/grpc/api/get_ import { config } from '@/config-manager'; import type { Empty } from '@pretendonetwork/grpc/api/google/protobuf/empty'; import type { AuthenticationCallContextExt } from '@/services/grpc/api/authentication-middleware'; -import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; export async function getUserData(_request: Empty, context: CallContext & AuthenticationCallContextExt): Promise> { // * This is asserted in authentication-middleware, we know this is never null - const pnid: HydratedPNIDDocument = context.pnid!; + const pnid = context.pnid!; return { deleted: pnid.deleted, diff --git a/src/services/grpc/api/implementation.ts b/src/services/grpc/api/implementation.ts index f606b5f..bc0c8fe 100644 --- a/src/services/grpc/api/implementation.ts +++ b/src/services/grpc/api/implementation.ts @@ -1,4 +1,3 @@ -import { APIServiceImplementation } from '@pretendonetwork/grpc/api/api_service'; import { register } from '@/services/grpc/api/register'; import { login } from '@/services/grpc/api/login'; import { getUserData } from '@/services/grpc/api/get-user-data'; @@ -8,7 +7,7 @@ import { resetPassword } from '@/services/grpc/api/reset-password'; import { setDiscordConnectionData } from '@/services/grpc/api/set-discord-connection-data'; import { setStripeConnectionData } from '@/services/grpc/api/set-stripe-connection-data'; -export const apiServiceImplementation: APIServiceImplementation = { +export const apiServiceImplementation = { register, login, getUserData, diff --git a/src/services/grpc/api/login.ts b/src/services/grpc/api/login.ts index 043c65a..8c4bfea 100644 --- a/src/services/grpc/api/login.ts +++ b/src/services/grpc/api/login.ts @@ -4,14 +4,13 @@ import bcrypt from 'bcrypt'; import { getPNIDByUsername, getPNIDByTokenAuth } from '@/database'; import { nintendoPasswordHash, generateToken} from '@/util'; import { config } from '@/config-manager'; -import type { TokenOptions } from '@/types/common/token-options'; import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; export async function login(request: LoginRequest): Promise> { - const grantType: string = request.grantType?.trim(); - const username: string | undefined = request.username?.trim(); - const password: string | undefined = request.password?.trim(); - const refreshToken: string | undefined = request.refreshToken?.trim(); + const grantType = request.grantType?.trim(); + const username = request.username?.trim(); + const password = request.password?.trim(); + const refreshToken = request.refreshToken?.trim(); if (!['password', 'refresh_token'].includes(grantType)) { throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid grant type'); @@ -38,7 +37,7 @@ export async function login(request: LoginRequest): Promise> { - const email: string = request.email?.trim(); - const username: string = request.username?.trim(); - const miiName: string = request.miiName?.trim(); - const password: string = request.password?.trim(); - const passwordConfirm: string = request.passwordConfirm?.trim(); - const captchaResponse: string | undefined = request.captchaResponse?.trim(); + const email = request.email?.trim(); + const username = request.username?.trim(); + const miiName = request.miiName?.trim(); + const password = request.password?.trim(); + const passwordConfirm = request.passwordConfirm?.trim(); + const captchaResponse = request.captchaResponse?.trim(); // * Only validate the captcha if that's enabled if (!disabledFeatures.captcha) { @@ -45,7 +43,7 @@ export async function register(request: RegisterRequest): Promise 0x14) { throw new ServerError(Status.INVALID_ARGUMENT, 'Mii name too long'); @@ -128,14 +126,14 @@ export async function register(request: RegisterRequest): Promise { - const password: string = request.password.trim(); - const passwordConfirm: string = request.passwordConfirm.trim(); - const token: string = request.token.trim(); + const password = request.password.trim(); + const passwordConfirm = request.passwordConfirm.trim(); + const token = request.token.trim(); if (!token) { throw new ServerError(Status.INVALID_ARGUMENT, 'Missing token'); @@ -24,7 +23,7 @@ export async function resetPassword(request: ResetPasswordRequest): Promise{ // * This is asserted in authentication-middleware, we know this is never null - const pnid: HydratedPNIDDocument = context.pnid!; + const pnid = context.pnid!; try { pnid.connections.discord.id = request.id; await pnid.save(); } catch (error) { - let message: string = 'Unknown Mongo error'; + let message = 'Unknown Mongo error'; if (error instanceof Error) { message = error.message; diff --git a/src/services/grpc/api/set-stripe-connection-data.ts b/src/services/grpc/api/set-stripe-connection-data.ts index 0994848..2af96b8 100644 --- a/src/services/grpc/api/set-stripe-connection-data.ts +++ b/src/services/grpc/api/set-stripe-connection-data.ts @@ -3,7 +3,6 @@ import { SetStripeConnectionDataRequest } from '@pretendonetwork/grpc/api/set_st import { PNID } from '@/models/pnid'; import type { Empty } from '@pretendonetwork/grpc/api/google/protobuf/empty'; import type { AuthenticationCallContextExt } from '@/services/grpc/api/authentication-middleware'; -import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; type StripeMongoUpdateScheme = { access_level?: number; @@ -18,7 +17,7 @@ type StripeMongoUpdateScheme = { export async function setStripeConnectionData(request: SetStripeConnectionDataRequest, context: CallContext & AuthenticationCallContextExt): Promise{ // * This is asserted in authentication-middleware, we know this is never null - const pnid: HydratedPNIDDocument = context.pnid!; + const pnid = context.pnid!; const updateData: StripeMongoUpdateScheme = { 'connections.stripe.latest_webhook_timestamp': Number(request.timestamp) @@ -78,7 +77,7 @@ export async function setStripeConnectionData(request: SetStripeConnectionDataRe }, { upsert: true }).exec(); } } catch (error) { - let message: string = 'Unknown Mongo error'; + let message = 'Unknown Mongo error'; if (error instanceof Error) { message = error.message; diff --git a/src/services/grpc/api/update-user-data.ts b/src/services/grpc/api/update-user-data.ts index bb82887..a842f38 100644 --- a/src/services/grpc/api/update-user-data.ts +++ b/src/services/grpc/api/update-user-data.ts @@ -2,12 +2,11 @@ import { CallContext } from 'nice-grpc'; import { UpdateUserDataRequest, DeepPartial } from '@pretendonetwork/grpc/api/update_user_data_rpc'; import { GetUserDataResponse } from '@pretendonetwork/grpc/api/get_user_data_rpc'; import { config } from '@/config-manager'; -import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; import type { AuthenticationCallContextExt } from '@/services/grpc/api/authentication-middleware'; export async function updateUserData(_request: UpdateUserDataRequest, context: CallContext & AuthenticationCallContextExt): Promise> { // * This is asserted in authentication-middleware, we know this is never null - const pnid: HydratedPNIDDocument = context.pnid!; + const pnid = context.pnid!; // TODO - STUBBED, DO SOMETHING HERE diff --git a/src/services/grpc/server.ts b/src/services/grpc/server.ts index af03741..3032034 100644 --- a/src/services/grpc/server.ts +++ b/src/services/grpc/server.ts @@ -1,4 +1,4 @@ -import { createServer, Server } from 'nice-grpc'; +import { createServer } from 'nice-grpc'; import { AccountDefinition } from '@pretendonetwork/grpc/account/account_service'; import { APIDefinition } from '@pretendonetwork/grpc/api/api_service'; @@ -12,7 +12,7 @@ import { apiServiceImplementation } from '@/services/grpc/api/implementation'; import { config } from '@/config-manager'; export async function startGRPCServer(): Promise { - const server: Server = createServer(); + const server = createServer(); server.with(accountApiKeyMiddleware).add(AccountDefinition, accountServiceImplementation); server.with(apiApiKeyMiddleware).with(apiAuthenticationMiddleware).add(APIDefinition, apiServiceImplementation); diff --git a/src/services/local-cdn/index.ts b/src/services/local-cdn/index.ts index c1b2963..7cd59d3 100644 --- a/src/services/local-cdn/index.ts +++ b/src/services/local-cdn/index.ts @@ -5,13 +5,13 @@ import { LOG_INFO } from '@/logger'; import get from '@/services/local-cdn/routes/get'; -const router: express.Router = express.Router(); +const router = express.Router(); if (disabledFeatures.s3) { // * s3 disabled, setup local CDN // * Router to handle the subdomain - const localcdn: express.Router = express.Router(); + const localcdn = express.Router(); // * Setup routes LOG_INFO('[LOCAL-CDN] Applying imported routes'); diff --git a/src/services/local-cdn/routes/get.ts b/src/services/local-cdn/routes/get.ts index acd4570..c98b586 100644 --- a/src/services/local-cdn/routes/get.ts +++ b/src/services/local-cdn/routes/get.ts @@ -1,12 +1,12 @@ import express from 'express'; import { getLocalCDNFile } from '@/cache'; -const router: express.Router = express.Router(); +const router = express.Router(); router.get('/*', async (request: express.Request, response: express.Response): Promise => { - const filePath: string = request.params[0]; + const filePath = request.params[0]; - const file: Buffer = await getLocalCDNFile(filePath); + const file = await getLocalCDNFile(filePath); if (file) { response.send(file); diff --git a/src/services/nasc/index.ts b/src/services/nasc/index.ts index 29d1148..aac663b 100644 --- a/src/services/nasc/index.ts +++ b/src/services/nasc/index.ts @@ -8,7 +8,7 @@ import { LOG_INFO } from '@/logger'; import ac from '@/services/nasc/routes/ac'; // Router to handle the subdomain restriction -const nasc: express.Router = express.Router(); +const nasc = express.Router(); LOG_INFO('[NASC] Importing middleware'); nasc.use(NASCMiddleware); @@ -18,7 +18,7 @@ LOG_INFO('[NASC] Applying imported routes'); nasc.use('/ac', ac); // Main router for endpoints -const router: express.Router = express.Router(); +const router = express.Router(); // Create subdomains LOG_INFO('[NASC] Creating \'nasc\' subdomain'); diff --git a/src/services/nasc/routes/ac.ts b/src/services/nasc/routes/ac.ts index e556434..a4e35f2 100644 --- a/src/services/nasc/routes/ac.ts +++ b/src/services/nasc/routes/ac.ts @@ -1,12 +1,10 @@ import express from 'express'; import { nintendoBase64Encode, nintendoBase64Decode, nascError, generateToken } from '@/util'; import { getServerByTitleID } from '@/database'; -import { TokenOptions } from '@/types/common/token-options'; import { NASCRequestParams } from '@/types/services/nasc/request-params'; -import { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; import { HydratedServerDocument } from '@/types/mongoose/server'; -const router: express.Router = express.Router(); +const router = express.Router(); /** * [POST] @@ -15,10 +13,10 @@ const router: express.Router = express.Router(); */ router.post('/', async (request: express.Request, response: express.Response): Promise => { const requestParams: NASCRequestParams = request.body; - const action: string = nintendoBase64Decode(requestParams.action).toString(); - const titleID: string = nintendoBase64Decode(requestParams.titleid).toString(); - const nexAccount: HydratedNEXAccountDocument | null = request.nexAccount; - let responseData: URLSearchParams = nascError('null'); + const action = nintendoBase64Decode(requestParams.action).toString(); + const titleID = nintendoBase64Decode(requestParams.titleid).toString(); + const nexAccount = request.nexAccount; + let responseData = nascError('null'); if (!nexAccount) { response.status(200).send(responseData.toString()); @@ -28,12 +26,12 @@ router.post('/', async (request: express.Request, response: express.Response): P // TODO: REMOVE AFTER PUBLIC LAUNCH // * LET EVERYONE IN THE `test` FRIENDS SERVER // * THAT WAY EVERYONE CAN GET AN ASSIGNED PID - let serverAccessLevel: string = 'test'; + let serverAccessLevel = 'test'; if (titleID !== '0004013000003202') { serverAccessLevel = nexAccount.server_access_level; } - const server: HydratedServerDocument | null = await getServerByTitleID(titleID, serverAccessLevel); + const server = await getServerByTitleID(titleID, serverAccessLevel); if (!server || !server.aes_key) { response.status(200).send(nascError('110').toString()); @@ -66,7 +64,7 @@ router.post('/', async (request: express.Request, response: express.Response): P }); async function processLoginRequest(server: HydratedServerDocument, pid: number, titleID: string): Promise { - const tokenOptions: TokenOptions = { + const tokenOptions = { system_type: 0x2, // * 3DS token_type: 0x3, // * NEX token pid: pid, @@ -77,8 +75,8 @@ async function processLoginRequest(server: HydratedServerDocument, pid: number, // TODO - Handle null tokens - const nexTokenBuffer: Buffer | null = await generateToken(server.aes_key, tokenOptions); - const nexToken: string = nintendoBase64Encode(nexTokenBuffer || ''); + const nexTokenBuffer = await generateToken(server.aes_key, tokenOptions); + const nexToken = nintendoBase64Encode(nexTokenBuffer || ''); return new URLSearchParams({ locator: nintendoBase64Encode(`${server.ip}:${server.port}`), @@ -90,7 +88,7 @@ async function processLoginRequest(server: HydratedServerDocument, pid: number, } async function processServiceTokenRequest(server: HydratedServerDocument, pid: number, titleID: string): Promise { - const tokenOptions: TokenOptions = { + const tokenOptions = { system_type: 0x2, // * 3DS token_type: 0x4, // * Service token pid: pid, @@ -101,8 +99,8 @@ async function processServiceTokenRequest(server: HydratedServerDocument, pid: n // TODO - Handle null tokens - const serviceTokenBuffer: Buffer | null = await generateToken(server.aes_key, tokenOptions); - const serviceToken: string = nintendoBase64Encode(serviceTokenBuffer || ''); + const serviceTokenBuffer = await generateToken(server.aes_key, tokenOptions); + const serviceToken = nintendoBase64Encode(serviceTokenBuffer || ''); return new URLSearchParams({ retry: nintendoBase64Encode('0'), diff --git a/src/services/nnas/index.ts b/src/services/nnas/index.ts index c90d5eb..5086c14 100644 --- a/src/services/nnas/index.ts +++ b/src/services/nnas/index.ts @@ -17,7 +17,7 @@ import provider from '@/services/nnas/routes/provider'; import support from '@/services/nnas/routes/support'; // Router to handle the subdomain restriction -const nnas: express.Router = express.Router(); +const nnas = express.Router(); LOG_INFO('[NNAS] Importing middleware'); nnas.use(clientHeaderCheck); diff --git a/src/services/nnas/routes/admin.ts b/src/services/nnas/routes/admin.ts index 3476e6b..c08c356 100644 --- a/src/services/nnas/routes/admin.ts +++ b/src/services/nnas/routes/admin.ts @@ -2,9 +2,8 @@ import express from 'express'; import xmlbuilder from 'xmlbuilder'; import { getValueFromQueryString } from '@/util'; import { PNID } from '@/models/pnid'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; -const router: express.Router = express.Router(); +const router = express.Router(); /** * [GET] @@ -12,9 +11,9 @@ const router: express.Router = express.Router(); * Description: Maps between NNID usernames and PIDs */ router.get('/mapped_ids', async (request: express.Request, response: express.Response): Promise => { - const inputType: string | undefined = getValueFromQueryString(request.query, 'input_type'); - const outputType: string | undefined = getValueFromQueryString(request.query, 'output_type'); - const input: string | undefined = getValueFromQueryString(request.query, 'input'); + const inputType = getValueFromQueryString(request.query, 'input_type'); + const outputType = getValueFromQueryString(request.query, 'output_type'); + const input = getValueFromQueryString(request.query, 'input'); if (!inputType || !outputType || !input) { response.status(400).send(xmlbuilder.create({ @@ -30,7 +29,7 @@ router.get('/mapped_ids', async (request: express.Request, response: express.Res return; } - let inputList: string[] = input.split(','); + let inputList = input.split(','); let queryInput: string; let queryOutput: string; @@ -57,7 +56,7 @@ router.get('/mapped_ids', async (request: express.Request, response: express.Res in_id: string; out_id: string; }[] = []; - const allowedTypes: string[] = ['pid', 'user_id']; + const allowedTypes = ['pid', 'user_id']; for (const input of inputList) { const result: { @@ -88,7 +87,7 @@ router.get('/mapped_ids', async (request: express.Request, response: express.Res } } - const searchResult: HydratedPNIDDocument | null = await PNID.findOne(query); + const searchResult = await PNID.findOne(query); if (searchResult) { result.out_id = searchResult.get(queryOutput); diff --git a/src/services/nnas/routes/content.ts b/src/services/nnas/routes/content.ts index db5100d..751728a 100644 --- a/src/services/nnas/routes/content.ts +++ b/src/services/nnas/routes/content.ts @@ -1,10 +1,8 @@ import express from 'express'; import xmlbuilder from 'xmlbuilder'; import timezones from '@/services/nnas/timezones.json'; -import { RegionLanguages } from '@/types/services/nnas/region-languages'; -import { RegionTimezones } from '@/types/services/nnas/region-timezones'; -const router: express.Router = express.Router(); +const router = express.Router(); /** * [GET] @@ -151,11 +149,11 @@ router.get('/time_zones/:countryCode/:language', (request: express.Request, resp }); */ - const countryCode: string = request.params.countryCode; - const language: string = request.params.language; + const countryCode = request.params.countryCode; + const language = request.params.language; - const regionLanguages: RegionLanguages = timezones[countryCode as keyof typeof timezones]; - const regionTimezones: RegionTimezones = regionLanguages[language] ? regionLanguages[language] : Object.values(regionLanguages)[0]; + const regionLanguages = timezones[countryCode as keyof typeof timezones]; + const regionTimezones = regionLanguages[language as keyof typeof regionLanguages] ? regionLanguages[language as keyof typeof regionLanguages] : Object.values(regionLanguages)[0]; response.send(xmlbuilder.create({ timezones: { diff --git a/src/services/nnas/routes/devices.ts b/src/services/nnas/routes/devices.ts index c770795..f46e6a4 100644 --- a/src/services/nnas/routes/devices.ts +++ b/src/services/nnas/routes/devices.ts @@ -1,7 +1,7 @@ import express from 'express'; import xmlbuilder from 'xmlbuilder'; -const router: express.Router = express.Router(); +const router = express.Router(); /** * [GET] diff --git a/src/services/nnas/routes/miis.ts b/src/services/nnas/routes/miis.ts index 3496a13..85487bc 100644 --- a/src/services/nnas/routes/miis.ts +++ b/src/services/nnas/routes/miis.ts @@ -3,10 +3,9 @@ import xmlbuilder from 'xmlbuilder'; import { getValueFromQueryString } from '@/util'; import { PNID } from '@/models/pnid'; import { config } from '@/config-manager'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; import { YesNoBoolString } from '@/types/common/yes-no-bool-string'; -const router: express.Router = express.Router(); +const router = express.Router(); /** * [GET] @@ -14,7 +13,7 @@ const router: express.Router = express.Router(); * Description: Returns a list of NNID miis */ router.get('/', async (request: express.Request, response: express.Response): Promise => { - const input: string | undefined = getValueFromQueryString(request.query, 'pids'); + const input = getValueFromQueryString(request.query, 'pids'); if (!input) { response.status(400).send(xmlbuilder.create({ @@ -30,7 +29,7 @@ router.get('/', async (request: express.Request, response: express.Response): Pr return; } - const pids: number[] = input.split(',').map(pid => Number(pid)).filter(pid => !isNaN(pid)); + const pids = input.split(',').map(pid => Number(pid)).filter(pid => !isNaN(pid)); const miis: { data: string; @@ -51,7 +50,7 @@ router.get('/', async (request: express.Request, response: express.Response): Pr for (const pid of pids) { // TODO - Replace this with a single query again somehow? Maybe aggregation? - const pnid: HydratedPNIDDocument | null = await PNID.findOne({ pid }); + const pnid = await PNID.findOne({ pid }); if (pnid) { miis.push({ diff --git a/src/services/nnas/routes/oauth.ts b/src/services/nnas/routes/oauth.ts index 20f92ad..7d25b75 100644 --- a/src/services/nnas/routes/oauth.ts +++ b/src/services/nnas/routes/oauth.ts @@ -6,11 +6,9 @@ import consoleStatusVerificationMiddleware from '@/middleware/console-status-ver import { getPNIDByTokenAuth, getPNIDByUsername } from '@/database'; import { generateToken } from '@/util'; import { config } from '@/config-manager'; -import { TokenOptions } from '@/types/common/token-options'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; import { Device } from '@/models/device'; -const router: express.Router = express.Router(); +const router = express.Router(); /** * [POST] @@ -18,10 +16,10 @@ const router: express.Router = express.Router(); * Description: Generates an access token for a user */ router.post('/access_token/generate', deviceCertificateMiddleware, consoleStatusVerificationMiddleware, async (request: express.Request, response: express.Response): Promise => { - const grantType: string = request.body.grant_type; - const username: string | undefined = request.body.user_id; - const password: string | undefined = request.body.password; - const refreshToken: string | undefined = request.body.refresh_token; + const grantType = request.body.grant_type; + const username = request.body.user_id; + const password = request.body.password; + const refreshToken = request.body.refresh_token; if (!['password', 'refresh_token'].includes(grantType)) { response.status(400).send(xmlbuilder.create({ @@ -35,7 +33,7 @@ router.post('/access_token/generate', deviceCertificateMiddleware, consoleStatus return; } - let pnid: HydratedPNIDDocument | null = null; + let pnid = null; if (grantType === 'password') { if (!username || username.trim() === '') { @@ -141,25 +139,25 @@ router.post('/access_token/generate', deviceCertificateMiddleware, consoleStatus return; } - const accessTokenOptions: TokenOptions = { + const accessTokenOptions = { system_type: 0x1, // * WiiU token_type: 0x1, // * OAuth Access pid: pnid.pid, expire_time: BigInt(Date.now() + (3600 * 1000)) }; - const refreshTokenOptions: TokenOptions = { + const refreshTokenOptions = { system_type: 0x1, // * WiiU token_type: 0x2, // * OAuth Refresh pid: pnid.pid, expire_time: BigInt(Date.now() + (3600 * 1000)) }; - const accessTokenBuffer: Buffer | null = await generateToken(config.aes_key, accessTokenOptions); - const refreshTokenBuffer: Buffer | null = await generateToken(config.aes_key, refreshTokenOptions); + const accessTokenBuffer = await generateToken(config.aes_key, accessTokenOptions); + const refreshTokenBuffer = await generateToken(config.aes_key, refreshTokenOptions); - const accessToken: string = accessTokenBuffer ? accessTokenBuffer.toString('hex') : ''; - const newRefreshToken: string = refreshTokenBuffer ? refreshTokenBuffer.toString('hex') : ''; + const accessToken = accessTokenBuffer ? accessTokenBuffer.toString('hex') : ''; + const newRefreshToken = refreshTokenBuffer ? refreshTokenBuffer.toString('hex') : ''; // TODO - Handle null tokens diff --git a/src/services/nnas/routes/people.ts b/src/services/nnas/routes/people.ts index c4b8bcd..ee3d9ba 100644 --- a/src/services/nnas/routes/people.ts +++ b/src/services/nnas/routes/people.ts @@ -3,7 +3,6 @@ import express from 'express'; import xmlbuilder from 'xmlbuilder'; import bcrypt from 'bcrypt'; import moment from 'moment'; -import mongoose from 'mongoose'; import deviceCertificateMiddleware from '@/middleware/device-certificate'; import ratelimit from '@/middleware/ratelimit'; import { connection as databaseConnection, doesPNIDExist, getPNIDProfileJSONByPID } from '@/database'; @@ -11,17 +10,13 @@ import { getValueFromHeaders, nintendoPasswordHash, sendConfirmationEmail, sendP import { PNID } from '@/models/pnid'; import { NEXAccount } from '@/models/nex-account'; import { LOG_ERROR } from '@/logger'; - import timezones from '@/services/nnas/timezones.json'; import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; import { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; -import { RegionLanguages } from '@/types/services/nnas/region-languages'; -import { RegionTimezone, RegionTimezones } from '@/types/services/nnas/region-timezones'; import { Person } from '@/types/services/nnas/person'; -import { PNIDProfile } from '@/types/services/nnas/pnid-profile'; -const router: express.Router = express.Router(); +const router = express.Router(); /** * [GET] @@ -29,9 +24,9 @@ const router: express.Router = express.Router(); * Description: Checks if a username is in use */ router.get('/:username', async (request: express.Request, response: express.Response): Promise => { - const username: string = request.params.username; + const username = request.params.username; - const userExists: boolean = await doesPNIDExist(username); + const userExists = await doesPNIDExist(username); if (userExists) { response.status(400).send(xmlbuilder.create({ @@ -70,7 +65,7 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request: express const person: Person = request.body.person; - const userExists: boolean = await doesPNIDExist(person.user_id); + const userExists = await doesPNIDExist(person.user_id); if (userExists) { response.status(400).send(xmlbuilder.create({ @@ -85,11 +80,11 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request: express return; } - const creationDate: string = moment().format('YYYY-MM-DDTHH:MM:SS'); + const creationDate = moment().format('YYYY-MM-DDTHH:MM:SS'); let pnid: HydratedPNIDDocument; let nexAccount: HydratedNEXAccountDocument; - const session: mongoose.ClientSession = await databaseConnection().startSession(); + const session = await databaseConnection().startSession(); await session.startTransaction(); try { @@ -109,16 +104,16 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request: express await nexAccount.save({ session }); - const primaryPasswordHash: string = nintendoPasswordHash(person.password, nexAccount.pid); - const passwordHash: string = await bcrypt.hash(primaryPasswordHash, 10); + const primaryPasswordHash = nintendoPasswordHash(person.password, nexAccount.pid); + const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); - const countryCode: string = person.country; - const language: string = person.language; - const timezoneName: string = person.tz_name; + const countryCode = person.country; + const language = person.language; + const timezoneName = person.tz_name; - const regionLanguages: RegionLanguages = timezones[countryCode as keyof typeof timezones]; - const regionTimezones: RegionTimezones = regionLanguages[language] ? regionLanguages[language] : Object.values(regionLanguages)[0]; - let timezone: RegionTimezone | undefined = regionTimezones.find(tz => tz.area === timezoneName); + const regionLanguages = timezones[countryCode as keyof typeof timezones]; + const regionTimezones = regionLanguages[language as keyof typeof regionLanguages] ? regionLanguages[language as keyof typeof regionLanguages] : Object.values(regionLanguages)[0]; + let timezone = regionTimezones.find(tz => tz.area === timezoneName); if (!timezone) { // TODO - Change this, handle the error @@ -221,7 +216,7 @@ router.get('/@me/profile', async (request: express.Request, response: express.Re response.set('Server', 'Nintendo 3DS (http)'); response.set('X-Nintendo-Date', new Date().getTime().toString()); - const pnid: HydratedPNIDDocument | null = request.pnid; + const pnid = request.pnid; if (!pnid) { // TODO - Research this error more @@ -238,7 +233,7 @@ router.get('/@me/profile', async (request: express.Request, response: express.Re return; } - const person: PNIDProfile | null = await getPNIDProfileJSONByPID(pnid.pid); + const person = await getPNIDProfileJSONByPID(pnid.pid); if (!person) { // TODO - Research this error more @@ -276,7 +271,7 @@ router.post('/@me/devices', async (request: express.Request, response: express.R // TODO - CHANGE THIS. WE NEED TO SAVE CONSOLE DETAILS !!! - const pnid: HydratedPNIDDocument | null = request.pnid; + const pnid = request.pnid; if (!pnid) { // TODO - Research this error more @@ -293,7 +288,7 @@ router.post('/@me/devices', async (request: express.Request, response: express.R return; } - const person: PNIDProfile | null = await getPNIDProfileJSONByPID(pnid.pid); + const person = await getPNIDProfileJSONByPID(pnid.pid); if (!person) { // TODO - Research this error more @@ -325,13 +320,13 @@ router.get('/@me/devices', async (request: express.Request, response: express.Re response.set('Server', 'Nintendo 3DS (http)'); response.set('X-Nintendo-Date', new Date().getTime().toString()); - const pnid: HydratedPNIDDocument | null = request.pnid; - const deviceId: string | undefined = getValueFromHeaders(request.headers, 'x-nintendo-device-id'); - const acceptLanguage: string | undefined = getValueFromHeaders(request.headers, 'accept-language'); - const platformId: string | undefined = getValueFromHeaders(request.headers, 'x-nintendo-platform-id'); - const region: string | undefined = getValueFromHeaders(request.headers, 'x-nintendo-region'); - const serialNumber: string | undefined = getValueFromHeaders(request.headers, 'x-nintendo-serial-number'); - const systemVersion: string | undefined = getValueFromHeaders(request.headers, 'x-nintendo-system-version'); + const pnid = request.pnid; + const deviceId = getValueFromHeaders(request.headers, 'x-nintendo-device-id'); + const acceptLanguage = getValueFromHeaders(request.headers, 'accept-language'); + const platformId = getValueFromHeaders(request.headers, 'x-nintendo-platform-id'); + const region = getValueFromHeaders(request.headers, 'x-nintendo-region'); + const serialNumber = getValueFromHeaders(request.headers, 'x-nintendo-serial-number'); + const systemVersion = getValueFromHeaders(request.headers, 'x-nintendo-system-version'); if (!deviceId || !acceptLanguage || !platformId || !region || !serialNumber || !systemVersion) { // TODO - Research these error more @@ -394,7 +389,7 @@ router.get('/@me/devices/owner', async (request: express.Request, response: expr response.set('Server', 'Nintendo 3DS (http)'); response.set('X-Nintendo-Date', moment().add(5, 'h').toString()); - const pnid: HydratedPNIDDocument | null = request.pnid; + const pnid = request.pnid; if (!pnid) { // TODO - Research this error more @@ -411,7 +406,7 @@ router.get('/@me/devices/owner', async (request: express.Request, response: expr return; } - const person: PNIDProfile | null = await getPNIDProfileJSONByPID(pnid.pid); + const person = await getPNIDProfileJSONByPID(pnid.pid); if (!person) { // TODO - Research this error more @@ -455,7 +450,7 @@ router.get('/@me/devices/status', async (_request: express.Request, response: ex * Description: Updates a users Mii */ router.put('/@me/miis/@primary', async (request: express.Request, response: express.Response): Promise => { - const pnid: HydratedPNIDDocument | null = request.pnid; + const pnid = request.pnid; if (!pnid) { // TODO - Research this error more @@ -480,9 +475,9 @@ router.put('/@me/miis/@primary', async (request: express.Request, response: expr // TODO - Better checks - const name: string = mii.name; - const primary: string = mii.primary; - const data: string = mii.data; + const name = mii.name; + const primary = mii.primary; + const data = mii.data; await pnid.updateMii({ name, primary, data }); @@ -498,7 +493,7 @@ router.put('/@me/devices/@current/inactivate', async (request: express.Request, response.set('Server', 'Nintendo 3DS (http)'); response.set('X-Nintendo-Date', new Date().getTime().toString()); - const pnid: HydratedPNIDDocument | null = request.pnid; + const pnid = request.pnid; if (!pnid) { response.status(400).send(xmlbuilder.create({ @@ -523,7 +518,7 @@ router.put('/@me/devices/@current/inactivate', async (request: express.Request, * Description: Deletes a NNID */ router.post('/@me/deletion', async (request: express.Request, response: express.Response): Promise => { - const pnid: HydratedPNIDDocument | null = request.pnid; + const pnid = request.pnid; if (!pnid) { response.status(400).send(xmlbuilder.create({ @@ -539,7 +534,7 @@ router.post('/@me/deletion', async (request: express.Request, response: express. return; } - const email: string = pnid.email.address; + const email = pnid.email.address; await pnid.scrub(); await pnid.save(); @@ -559,7 +554,7 @@ router.post('/@me/deletion', async (request: express.Request, response: express. * Description: Updates a PNIDs account details */ router.put('/@me', async (request: express.Request, response: express.Response): Promise => { - const pnid: HydratedPNIDDocument | null = request.pnid; + const pnid = request.pnid; const person: Person = request.body.person; if (!pnid) { @@ -576,11 +571,11 @@ router.put('/@me', async (request: express.Request, response: express.Response): return; } - const gender: string = person.gender ? person.gender : pnid.gender; - const region: number = person.region ? person.region : pnid.region; - const countryCode: string = person.country ? person.country : pnid.country; - const language: string = person.language ? person.language : pnid.language; - let timezoneName: string = person.tz_name ? person.tz_name : pnid.timezone.name; + const gender = person.gender ? person.gender : pnid.gender; + const region = person.region ? person.region : pnid.region; + const countryCode = person.country ? person.country : pnid.country; + const language = person.language ? person.language : pnid.language; + let timezoneName = person.tz_name ? person.tz_name : pnid.timezone.name; // * Fix for 3DS sending empty person.tz_name, which is interpreted as an empty object // TODO - See if there's a cleaner way to do this? @@ -589,12 +584,12 @@ router.put('/@me', async (request: express.Request, response: express.Response): timezoneName = pnid.timezone.name; } - const marketingFlag: boolean = person.marketing_flag ? person.marketing_flag === 'Y' : pnid.flags.marketing; - const offDeviceFlag: boolean = person.off_device_flag ? person.off_device_flag === 'Y' : pnid.flags.off_device; + const marketingFlag = person.marketing_flag ? person.marketing_flag === 'Y' : pnid.flags.marketing; + const offDeviceFlag = person.off_device_flag ? person.off_device_flag === 'Y' : pnid.flags.off_device; - const regionLanguages: RegionLanguages = timezones[countryCode as keyof typeof timezones]; - const regionTimezones: RegionTimezones = regionLanguages[language] ? regionLanguages[language] : Object.values(regionLanguages)[0]; - let timezone: RegionTimezone | undefined = regionTimezones.find(tz => tz.area === timezoneName); + const regionLanguages = timezones[countryCode as keyof typeof timezones]; + const regionTimezones = regionLanguages[language as keyof typeof regionLanguages] ? regionLanguages[language as keyof typeof regionLanguages] : Object.values(regionLanguages)[0]; + let timezone = regionTimezones.find(tz => tz.area === timezoneName); if (!timezone) { // TODO - Change this, handle the error @@ -608,8 +603,8 @@ router.put('/@me', async (request: express.Request, response: express.Response): } if (person.password) { - const primaryPasswordHash: string = nintendoPasswordHash(person.password, pnid.pid); - const passwordHash: string = await bcrypt.hash(primaryPasswordHash, 10); + const primaryPasswordHash = nintendoPasswordHash(person.password, pnid.pid); + const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); pnid.password = passwordHash; } @@ -632,7 +627,7 @@ router.put('/@me', async (request: express.Request, response: express.Response): * Description: Gets a list (why?) of PNID emails */ router.get('/@me/emails', async (request: express.Request, response: express.Response): Promise => { - const pnid: HydratedPNIDDocument | null = request.pnid; + const pnid = request.pnid; if (!pnid) { response.status(400).send(xmlbuilder.create({ @@ -673,7 +668,7 @@ router.get('/@me/emails', async (request: express.Request, response: express.Res * Description: Updates a users email address */ router.put('/@me/emails/@primary', async (request: express.Request, response: express.Response): Promise => { - const pnid: HydratedPNIDDocument | null = request.pnid; + const pnid = request.pnid; const email: { address: string; diff --git a/src/services/nnas/routes/provider.ts b/src/services/nnas/routes/provider.ts index 6b7f69f..794c6cf 100644 --- a/src/services/nnas/routes/provider.ts +++ b/src/services/nnas/routes/provider.ts @@ -3,12 +3,8 @@ import xmlbuilder from 'xmlbuilder'; import { getServerByClientID, getServerByGameServerID } from '@/database'; import { generateToken, getValueFromHeaders, getValueFromQueryString } from '@/util'; import { NEXAccount } from '@/models/nex-account'; -import { TokenOptions } from '@/types/common/token-options'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; -import { HydratedServerDocument } from '@/types/mongoose/server'; -import { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; -const router: express.Router = express.Router(); +const router = express.Router(); /** * [GET] @@ -16,7 +12,7 @@ const router: express.Router = express.Router(); * Description: Gets a service token */ router.get('/service_token/@me', async (request: express.Request, response: express.Response): Promise => { - const pnid: HydratedPNIDDocument | null = request.pnid; + const pnid = request.pnid; if (!pnid) { response.status(400).send(xmlbuilder.create({ @@ -32,7 +28,7 @@ router.get('/service_token/@me', async (request: express.Request, response: expr return; } - const clientID: string | undefined = getValueFromQueryString(request.query, 'client_id'); + const clientID = getValueFromQueryString(request.query, 'client_id'); if (!clientID) { // TODO - Research this error more @@ -48,7 +44,7 @@ router.get('/service_token/@me', async (request: express.Request, response: expr return; } - const titleID: string | undefined = getValueFromHeaders(request.headers, 'x-nintendo-title-id'); + const titleID = getValueFromHeaders(request.headers, 'x-nintendo-title-id'); if (!titleID) { // TODO - Research this error more @@ -64,8 +60,8 @@ router.get('/service_token/@me', async (request: express.Request, response: expr return; } - const serverAccessLevel: string = pnid.server_access_level; - const server: HydratedServerDocument | null = await getServerByClientID(clientID, serverAccessLevel); + const serverAccessLevel = pnid.server_access_level; + const server = await getServerByClientID(clientID, serverAccessLevel); if (!server || !server.aes_key) { response.send(xmlbuilder.create({ @@ -93,7 +89,7 @@ router.get('/service_token/@me', async (request: express.Request, response: expr return; } - const tokenOptions: TokenOptions = { + const tokenOptions = { system_type: server.device, token_type: 0x4, // * Service token pid: pnid.pid, @@ -102,8 +98,8 @@ router.get('/service_token/@me', async (request: express.Request, response: expr expire_time: BigInt(Date.now() + (3600 * 1000)) }; - const serviceTokenBuffer: Buffer | null = await generateToken(server.aes_key, tokenOptions); - let serviceToken: string = serviceTokenBuffer ? serviceTokenBuffer.toString('base64') : ''; + const serviceTokenBuffer = await generateToken(server.aes_key, tokenOptions); + let serviceToken = serviceTokenBuffer ? serviceTokenBuffer.toString('base64') : ''; if (request.isCemu) { serviceToken = Buffer.from(serviceToken, 'base64').toString('hex'); @@ -122,7 +118,7 @@ router.get('/service_token/@me', async (request: express.Request, response: expr * Description: Gets a NEX server address and token */ router.get('/nex_token/@me', async (request: express.Request, response: express.Response): Promise => { - const pnid: HydratedPNIDDocument | null = request.pnid; + const pnid = request.pnid; if (!pnid) { response.status(400).send(xmlbuilder.create({ @@ -138,7 +134,7 @@ router.get('/nex_token/@me', async (request: express.Request, response: express. return; } - const nexAccount: HydratedNEXAccountDocument | null = await NEXAccount.findOne({ + const nexAccount = await NEXAccount.findOne({ owning_pid: pnid.pid }); @@ -156,7 +152,7 @@ router.get('/nex_token/@me', async (request: express.Request, response: express. return; } - const gameServerID: string | undefined = getValueFromQueryString(request.query, 'game_server_id'); + const gameServerID = getValueFromQueryString(request.query, 'game_server_id'); if (!gameServerID) { response.send(xmlbuilder.create({ @@ -171,8 +167,8 @@ router.get('/nex_token/@me', async (request: express.Request, response: express. return; } - const serverAccessLevel: string = pnid.server_access_level; - const server: HydratedServerDocument | null = await getServerByGameServerID(gameServerID, serverAccessLevel); + const serverAccessLevel = pnid.server_access_level; + const server = await getServerByGameServerID(gameServerID, serverAccessLevel); if (!server || !server.aes_key) { response.send(xmlbuilder.create({ @@ -200,7 +196,7 @@ router.get('/nex_token/@me', async (request: express.Request, response: express. return; } - const titleID: string | undefined = getValueFromHeaders(request.headers, 'x-nintendo-title-id'); + const titleID = getValueFromHeaders(request.headers, 'x-nintendo-title-id'); if (!titleID) { // TODO - Research this error more @@ -216,7 +212,7 @@ router.get('/nex_token/@me', async (request: express.Request, response: express. return; } - const tokenOptions: TokenOptions = { + const tokenOptions = { system_type: server.device, token_type: 0x3, // nex token, pid: pnid.pid, @@ -225,8 +221,8 @@ router.get('/nex_token/@me', async (request: express.Request, response: express. expire_time: BigInt(Date.now() + (3600 * 1000)) }; - const nexTokenBuffer: Buffer | null = await generateToken(server.aes_key, tokenOptions); - let nexToken: string = nexTokenBuffer ? nexTokenBuffer.toString('base64') : ''; + const nexTokenBuffer = await generateToken(server.aes_key, tokenOptions); + let nexToken = nexTokenBuffer ? nexTokenBuffer.toString('base64') : ''; if (request.isCemu) { nexToken = Buffer.from(nexToken || '', 'base64').toString('hex'); diff --git a/src/services/nnas/routes/support.ts b/src/services/nnas/routes/support.ts index a7e163d..46522a8 100644 --- a/src/services/nnas/routes/support.ts +++ b/src/services/nnas/routes/support.ts @@ -4,9 +4,8 @@ import xmlbuilder from 'xmlbuilder'; import moment from 'moment'; import { getPNIDByPID } from '@/database'; import { sendEmailConfirmedEmail, sendConfirmationEmail, sendForgotPasswordEmail } from '@/util'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; -const router: express.Router = express.Router(); +const router = express.Router(); /** * [POST] @@ -14,7 +13,7 @@ const router: express.Router = express.Router(); * Description: Verifies a provided email address is valid */ router.post('/validate/email', async (request: express.Request, response: express.Response): Promise => { - const email: string = request.body.email; + const email = request.body.email; if (!email) { response.send(xmlbuilder.create({ @@ -30,7 +29,7 @@ router.post('/validate/email', async (request: express.Request, response: expres return; } - const domain: string = email.split('@')[1]; + const domain = email.split('@')[1]; dns.resolveMx(domain, (error: NodeJS.ErrnoException | null) => { if (error) { @@ -54,10 +53,10 @@ router.post('/validate/email', async (request: express.Request, response: expres * Description: Verifies a users email via 6 digit code */ router.put('/email_confirmation/:pid/:code', async (request: express.Request, response: express.Response): Promise => { - const code: string = request.params.code; - const pid: number = Number(request.params.pid); + const code = request.params.code; + const pid = Number(request.params.pid); - const pnid: HydratedPNIDDocument | null = await getPNIDByPID(pid); + const pnid = await getPNIDByPID(pid); if (!pnid) { response.status(400).send(xmlbuilder.create({ @@ -84,7 +83,7 @@ router.put('/email_confirmation/:pid/:code', async (request: express.Request, re return; } - const validatedDate: string = moment().format('YYYY-MM-DDTHH:MM:SS'); + const validatedDate = moment().format('YYYY-MM-DDTHH:MM:SS'); pnid.email.reachable = true; pnid.email.validated = true; @@ -103,9 +102,9 @@ router.put('/email_confirmation/:pid/:code', async (request: express.Request, re * Description: Resends a users confirmation email */ router.get('/resend_confirmation', async (request: express.Request, response: express.Response): Promise => { - const pid: number = Number(request.headers['x-nintendo-pid']); + const pid = Number(request.headers['x-nintendo-pid']); - const pnid: HydratedPNIDDocument | null = await getPNIDByPID(pid); + const pnid = await getPNIDByPID(pid); if (!pnid) { // TODO - Unsure if this is the right error @@ -133,9 +132,9 @@ router.get('/resend_confirmation', async (request: express.Request, response: ex * NOTE: On NN this was a temp password that expired after 24 hours. We do not do that */ router.get('/forgotten_password/:pid', async (request: express.Request, response: express.Response): Promise => { - const pid: number = Number(request.params.pid); + const pid = Number(request.params.pid); - const pnid: HydratedPNIDDocument | null = await getPNIDByPID(pid); + const pnid = await getPNIDByPID(pid); if (!pnid) { // TODO - Better errors diff --git a/src/types/common/config.ts b/src/types/common/config.ts index 9c11436..82606fc 100644 --- a/src/types/common/config.ts +++ b/src/types/common/config.ts @@ -46,11 +46,4 @@ export interface Config { stripe?: { secret_key: string; }; -} - -export interface DisabledFeatures { - redis: boolean; - email: boolean; - captcha: boolean; - s3: boolean } \ No newline at end of file diff --git a/src/types/services/nnas/region-languages.ts b/src/types/services/nnas/region-languages.ts deleted file mode 100644 index fd4bbf9..0000000 --- a/src/types/services/nnas/region-languages.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { RegionTimezones } from '@/types/services/nnas/region-timezones'; - -export interface RegionLanguages { - [myKey: string]: RegionTimezones -} \ No newline at end of file diff --git a/src/types/services/nnas/region-timezones.ts b/src/types/services/nnas/region-timezones.ts deleted file mode 100644 index c904aaa..0000000 --- a/src/types/services/nnas/region-timezones.ts +++ /dev/null @@ -1,9 +0,0 @@ -export interface RegionTimezone { - area: string; - language: string; - name: string; - utc_offset: string; - order: string; -} - -export type RegionTimezones = RegionTimezone[]; \ No newline at end of file diff --git a/src/util.ts b/src/util.ts index 25558cf..f5d8b18 100644 --- a/src/util.ts +++ b/src/util.ts @@ -13,7 +13,6 @@ import { config, disabledFeatures } from '@/config-manager'; import { TokenOptions } from '@/types/common/token-options'; import { Token } from '@/types/common/token'; import { IPNID, IPNIDMethods } from '@/types/mongoose/pnid'; -import { MailerOptions } from '@/types/common/mailer-options'; import { SafeQs } from '@/types/common/safe-qs'; let s3: aws.S3; @@ -27,10 +26,10 @@ if (!disabledFeatures.s3) { } export function nintendoPasswordHash(password: string, pid: number): string { - const pidBuffer: Buffer = Buffer.alloc(4); + const pidBuffer = Buffer.alloc(4); pidBuffer.writeUInt32LE(pid); - const unpacked: Buffer = Buffer.concat([ + const unpacked = Buffer.concat([ pidBuffer, Buffer.from('\x02\x65\x43\x46'), Buffer.from(password) @@ -45,12 +44,12 @@ export function nintendoBase64Decode(encoded: string): Buffer { } export function nintendoBase64Encode(decoded: string | Buffer): string { - const encoded: string = Buffer.from(decoded).toString('base64'); + const encoded = Buffer.from(decoded).toString('base64'); return encoded.replaceAll('+', '.').replaceAll('/', '-').replaceAll('=', '*'); } export function generateToken(key: string, options: TokenOptions): Buffer | null { - let dataBuffer: Buffer = Buffer.alloc(1 + 1 + 4 + 8); + let dataBuffer = Buffer.alloc(1 + 1 + 4 + 8); dataBuffer.writeUInt8(options.system_type, 0x0); dataBuffer.writeUInt8(options.token_type, 0x1); @@ -73,19 +72,19 @@ export function generateToken(key: string, options: TokenOptions): Buffer | null dataBuffer.writeInt8(options.access_level, 0x16); } - const iv: Buffer = Buffer.alloc(16); - const cipher: crypto.Cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key, 'hex'), iv); + const iv = Buffer.alloc(16); + const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key, 'hex'), iv); const encrypted = Buffer.concat([ cipher.update(dataBuffer), cipher.final() ]); - let final: Buffer = encrypted; + let final = encrypted; if ((options.token_type !== 0x1 && options.token_type !== 0x2) || options.system_type === 0x3) { // * Access and refresh tokens don't get a checksum due to size constraints - const checksum: Buffer = crc32(dataBuffer); + const checksum = crc32(dataBuffer); final = Buffer.concat([ checksum, @@ -98,7 +97,7 @@ export function generateToken(key: string, options: TokenOptions): Buffer | null export function decryptToken(token: Buffer): Buffer { let encryptedBody: Buffer; - let expectedChecksum: number = 0; + let expectedChecksum = 0; if (token.length === 16) { // * Token is an access/refresh token, no checksum @@ -108,10 +107,10 @@ export function decryptToken(token: Buffer): Buffer { encryptedBody = token.subarray(4); } - const iv: Buffer = Buffer.alloc(16); - const decipher: crypto.Decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(config.aes_key, 'hex'), iv); + const iv = Buffer.alloc(16); + const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(config.aes_key, 'hex'), iv); - const decrypted: Buffer = Buffer.concat([ + const decrypted = Buffer.concat([ decipher.update(encryptedBody), decipher.final() ]); @@ -140,9 +139,9 @@ export function unpackToken(token: Buffer): Token { } export function fullUrl(request: express.Request): string { - const protocol: string = request.protocol; - const host: string = request.host; - const opath: string = request.originalUrl; + const protocol = request.protocol; + const host = request.host; + const opath = request.originalUrl; return `${protocol}://${host}${opath}`; } @@ -161,8 +160,8 @@ export async function uploadCDNAsset(bucket: string, key: string, data: Buffer, } export async function writeLocalCDNFile(key: string, data: Buffer): Promise { - const filePath: string = config.cdn.disk_path; - const folder: string = path.dirname(filePath); + const filePath = config.cdn.disk_path; + const folder = path.dirname(filePath); await fs.ensureDir(folder); await fs.writeFile(filePath, data); @@ -177,7 +176,7 @@ export function nascError(errorCode: string): URLSearchParams { } export async function sendConfirmationEmail(pnid: mongoose.HydratedDocument): Promise { - const options: MailerOptions = { + const options = { to: pnid.email.address, subject: '[Pretendo Network] Please confirm your email address', username: pnid.username, @@ -192,7 +191,7 @@ export async function sendConfirmationEmail(pnid: mongoose.HydratedDocument): Promise { - const options: MailerOptions = { + const options = { to: pnid.email.address, subject: '[Pretendo Network] Email address confirmed', username: pnid.username, @@ -204,7 +203,7 @@ export async function sendEmailConfirmedEmail(pnid: mongoose.HydratedDocument): Promise { - const tokenOptions: TokenOptions = { + const tokenOptions = { system_type: 0xF, // * API token_type: 0x5, // * Password reset pid: pnid.pid, @@ -213,12 +212,12 @@ export async function sendForgotPasswordEmail(pnid: mongoose.HydratedDocument { - const options: MailerOptions = { + const options = { to: email, subject: '[Pretendo Network] PNID Deleted', username: username, @@ -265,8 +264,8 @@ export function makeSafeQs(query: ParsedQs): SafeQs { } export function getValueFromQueryString(qs: ParsedQs, key: string): string | undefined { - let property: string | ParsedQs | string[] | ParsedQs[] | SafeQs | undefined = qs[key]; - let value: string | undefined; + let property = qs[key]; + let value; if (property) { if (Array.isArray(property)) { @@ -285,8 +284,8 @@ export function getValueFromQueryString(qs: ParsedQs, key: string): string | und } export function getValueFromHeaders(headers: IncomingHttpHeaders, key: string): string | undefined { - let header: string | string[] | undefined = headers[key]; - let value: string | undefined; + let header = headers[key]; + let value; if (header) { if (!Array.isArray(header)) { From 6d3f516612f78cd7ff226eb0304c1726e7ce65d5 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 14 Apr 2024 19:19:37 -0400 Subject: [PATCH 3/7] chore: update Id -> ID --- src/middleware/client-header.ts | 8 ++++---- src/nintendo-certificate.ts | 6 +++--- src/server.ts | 16 ++++++++-------- src/services/nnas/routes/people.ts | 10 +++++----- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/middleware/client-header.ts b/src/middleware/client-header.ts index 851317f..483f8dc 100644 --- a/src/middleware/client-header.ts +++ b/src/middleware/client-header.ts @@ -14,14 +14,14 @@ function nintendoClientHeaderCheck(request: express.Request, response: express.R response.set('Server', 'Nintendo 3DS (http)'); response.set('X-Nintendo-Date', new Date().getTime().toString()); - const clientId = getValueFromHeaders(request.headers, 'x-nintendo-client-id'); + const clientID = getValueFromHeaders(request.headers, 'x-nintendo-client-id'); const clientSecret = getValueFromHeaders(request.headers, 'x-nintendo-client-secret'); if ( - !clientId || + !clientID || !clientSecret || - !VALID_CLIENT_ID_SECRET_PAIRS[clientId] || - clientSecret !== VALID_CLIENT_ID_SECRET_PAIRS[clientId] + !VALID_CLIENT_ID_SECRET_PAIRS[clientID] || + clientSecret !== VALID_CLIENT_ID_SECRET_PAIRS[clientID] ) { response.send(xmlbuilder.create({ errors: { diff --git a/src/nintendo-certificate.ts b/src/nintendo-certificate.ts index da1741c..8d5dce8 100644 --- a/src/nintendo-certificate.ts +++ b/src/nintendo-certificate.ts @@ -77,7 +77,7 @@ class NintendoCertificate { issuer: string; keyType: number; certificateName: string; - ngKeyId: number; + ngKeyID: number; publicKey: Buffer; valid: boolean; publicKeyData: Buffer; @@ -91,7 +91,7 @@ class NintendoCertificate { this.issuer = ''; this.keyType = 0; this.certificateName = ''; - this.ngKeyId = 0; + this.ngKeyID = 0; this.publicKey = Buffer.alloc(0); this.valid = false; this.publicKeyData = Buffer.alloc(0); @@ -128,7 +128,7 @@ class NintendoCertificate { this.issuer = this._certificate.subarray(0x80, 0xC0).toString().split('\0')[0]; this.keyType = this._certificate.readUInt32BE(0xC0); this.certificateName = this._certificate.subarray(0xC4, 0x104).toString().split('\0')[0]; - this.ngKeyId = this._certificate.readUInt32BE(0x104); + this.ngKeyID = this._certificate.readUInt32BE(0x104); this.publicKeyData = this._certificate.subarray(0x108); if (this.issuer === 'Root-CA00000003-MS00000012') { diff --git a/src/server.ts b/src/server.ts index e496b74..4d90d63 100644 --- a/src/server.ts +++ b/src/server.ts @@ -52,13 +52,13 @@ app.use(assets); LOG_INFO('Creating 404 status handler'); app.use((request: express.Request, response: express.Response): void => { const url = fullUrl(request); - let deviceId = getValueFromHeaders(request.headers, 'X-Nintendo-Device-ID'); + let deviceID = getValueFromHeaders(request.headers, 'X-Nintendo-Device-ID'); - if (!deviceId) { - deviceId = 'Unknown'; + if (!deviceID) { + deviceID = 'Unknown'; } - LOG_WARN(`HTTP 404 at ${url} from ${deviceId}`); + LOG_WARN(`HTTP 404 at ${url} from ${deviceID}`); response.set('Content-Type', 'text/xml'); response.set('Server', 'Nintendo 3DS (http)'); @@ -80,13 +80,13 @@ LOG_INFO('Creating non-404 status handler'); app.use((error: any, request: express.Request, response: express.Response, _next: express.NextFunction): void => { const status = error.status || 500; const url = fullUrl(request); - let deviceId = getValueFromHeaders(request.headers, 'X-Nintendo-Device-ID'); + let deviceID = getValueFromHeaders(request.headers, 'X-Nintendo-Device-ID'); - if (!deviceId) { - deviceId = 'Unknown'; + if (!deviceID) { + deviceID = 'Unknown'; } - LOG_WARN(`HTTP ${status} at ${url} from ${deviceId}: ${error.message}`); + LOG_WARN(`HTTP ${status} at ${url} from ${deviceID}: ${error.message}`); response.status(status).json({ app: 'api', diff --git a/src/services/nnas/routes/people.ts b/src/services/nnas/routes/people.ts index ee3d9ba..5d0bf3d 100644 --- a/src/services/nnas/routes/people.ts +++ b/src/services/nnas/routes/people.ts @@ -321,14 +321,14 @@ router.get('/@me/devices', async (request: express.Request, response: express.Re response.set('X-Nintendo-Date', new Date().getTime().toString()); const pnid = request.pnid; - const deviceId = getValueFromHeaders(request.headers, 'x-nintendo-device-id'); + const deviceID = getValueFromHeaders(request.headers, 'x-nintendo-device-id'); const acceptLanguage = getValueFromHeaders(request.headers, 'accept-language'); - const platformId = getValueFromHeaders(request.headers, 'x-nintendo-platform-id'); + const platformID = getValueFromHeaders(request.headers, 'x-nintendo-platform-id'); const region = getValueFromHeaders(request.headers, 'x-nintendo-region'); const serialNumber = getValueFromHeaders(request.headers, 'x-nintendo-serial-number'); const systemVersion = getValueFromHeaders(request.headers, 'x-nintendo-system-version'); - if (!deviceId || !acceptLanguage || !platformId || !region || !serialNumber || !systemVersion) { + if (!deviceID || !acceptLanguage || !platformID || !region || !serialNumber || !systemVersion) { // TODO - Research these error more response.status(400).send(xmlbuilder.create({ errors: { @@ -362,11 +362,11 @@ router.get('/@me/devices', async (request: express.Request, response: express.Re devices: [ { device: { - device_id: deviceId, + device_id: deviceID, language: acceptLanguage, updated: moment().format('YYYY-MM-DDTHH:MM:SS'), pid: pnid.pid, - platform_id: platformId, + platform_id: platformID, region: region, serial_number: serialNumber, status: 'ACTIVE', From 82d353357bc8d8cfc1a63fb6d64f43a7b7292482 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 14 Apr 2024 19:41:47 -0400 Subject: [PATCH 4/7] chore: updated comments to use Better Comments syntax --- src/database.ts | 6 +-- src/middleware/nasc.ts | 20 ++++----- src/middleware/xml-parser.ts | 2 +- src/models/device.ts | 4 +- src/models/nex-account.ts | 8 ++-- src/models/pnid.ts | 14 +++--- src/nintendo-certificate.ts | 10 ++--- src/server.ts | 12 ++--- src/services/api/index.ts | 8 ++-- src/services/api/routes/v1/register.ts | 50 ++++++++++----------- src/services/api/routes/v1/resetPassword.ts | 2 +- src/services/assets/index.ts | 10 ++--- src/services/cbvc/index.ts | 10 ++--- src/services/conntest/index.ts | 12 ++--- src/services/datastore/index.ts | 8 ++-- src/services/datastore/routes/upload.ts | 2 +- src/services/grpc/api/register.ts | 48 ++++++++++---------- src/services/grpc/api/reset-password.ts | 2 +- src/services/nasc/index.ts | 10 ++--- src/services/nasc/routes/ac.ts | 2 +- src/services/nnas/index.ts | 10 ++--- src/services/nnas/routes/content.ts | 4 +- src/services/nnas/routes/people.ts | 28 ++++++------ src/services/nnas/routes/provider.ts | 2 +- src/types/mongoose/pnid.ts | 2 +- src/types/services/nnas/pnid-profile.ts | 2 +- src/util.ts | 2 +- 27 files changed, 145 insertions(+), 145 deletions(-) diff --git a/src/database.ts b/src/database.ts index 4f0e7a2..b6d443e 100644 --- a/src/database.ts +++ b/src/database.ts @@ -17,7 +17,7 @@ import { DiscordConnectionData } from '@/types/services/api/discord-connection-d const connection_string = config.mongoose.connection_string; const options = config.mongoose.options; -// TODO: Extend this later with more settings +// TODO - Extend this later with more settings const discordConnectionSchema = joi.object({ id: joi.string() }); @@ -116,7 +116,7 @@ export async function getPNIDByTokenAuth(token: string): Promise({ linked_pids: [Number], access_level: { type: Number, - default: 0 // 0: standard, 1: tester, 2: mod?, 3: dev + default: 0 // * 0: standard, 1: tester, 2: mod?, 3: dev }, server_access_level: { type: String, - default: 'prod' // everyone is in production by default + default: 'prod' // * everyone is in production by default }, certificate_hash: String }); diff --git a/src/models/nex-account.ts b/src/models/nex-account.ts index 9372ac6..c731f07 100644 --- a/src/models/nex-account.ts +++ b/src/models/nex-account.ts @@ -6,7 +6,7 @@ const NEXAccountSchema = new Schema { - const min = 1000000000; // The console (WiiU) seems to not accept PIDs smaller than this + const min = 1000000000; // * The console (WiiU) seems to not accept PIDs smaller than this const max = 1799999999; const pid = Math.floor(Math.random() * (max - min + 1) + min); diff --git a/src/models/pnid.ts b/src/models/pnid.ts index 1e19629..5e2cc34 100644 --- a/src/models/pnid.ts +++ b/src/models/pnid.ts @@ -33,11 +33,11 @@ const PNIDSchema = new Schema({ }, access_level: { type: Number, - default: 0 // 0: standard, 1: tester, 2: mod?, 3: dev + default: 0 // * 0: standard, 1: tester, 2: mod?, 3: dev }, server_access_level: { type: String, - default: 'prod' // everyone is in production by default + default: 'prod' // * everyone is in production by default }, pid: { type: Number, @@ -89,7 +89,7 @@ const PNIDSchema = new Schema({ off_device: Boolean }, devices: [DeviceSchema], - identification: { // user identification tokens + identification: { // * user identification tokens email_code: { type: String, unique: true @@ -133,7 +133,7 @@ PNIDSchema.plugin(uniqueValidator, {message: '{PATH} already in use.'}); and the next few accounts counting down seem to be admin, service and internal test accounts */ PNIDSchema.method('generatePID', async function generatePID(): Promise { - const min = 1000000000; // The console (WiiU) seems to not accept PIDs smaller than this + const min = 1000000000; // * The console (WiiU) seems to not accept PIDs smaller than this const max = 1799999999; const pid = Math.floor(Math.random() * (max - min + 1) + min); @@ -150,9 +150,9 @@ PNIDSchema.method('generatePID', async function generatePID(): Promise { }); PNIDSchema.method('generateEmailValidationCode', async function generateEmailValidationCode(): Promise { - // WiiU passes the PID along with the email code - // Does not actually need to be unique to all users - const code = Math.random().toFixed(6).split('.')[1]; // Dirty one-liner to generate numbers of 6 length and padded 0 + // * WiiU passes the PID along with the email code + // * Does not actually need to be unique to all users + const code = Math.random().toFixed(6).split('.')[1]; // * Dirty one-liner to generate numbers of 6 length and padded 0 this.identification.email_code = code; }); diff --git a/src/nintendo-certificate.ts b/src/nintendo-certificate.ts index 8d5dce8..38e7a1a 100644 --- a/src/nintendo-certificate.ts +++ b/src/nintendo-certificate.ts @@ -41,7 +41,7 @@ const CTR_LFCS_B_PUB = Buffer.from([ 0xAF, 0x07, 0xEB, 0x9C, 0xBF, 0xA9, 0xC9 ]); -// Signature options +// * Signature options const SIGNATURE_SIZES = { RSA_4096_SHA1: { SIZE: 0x200, @@ -201,10 +201,10 @@ class NintendoCertificate { this.valid = publicKey.verify(this._certificateBody, this.signature); } - // Huge thanks to Myria for helping get ECDSA working - // with Nodes native crypto module and getting the keys - // from bytes to PEM! - // https://github.com/Myriachan + // * Huge thanks to Myria for helping get ECDSA working + // * with Nodes native crypto module and getting the keys + // * from bytes to PEM! + // * https://github.com/Myriachan _verifySignatureECDSA(): void { const pem = this.consoleType === 'wiiu' ? WIIU_DEVICE_PUB_PEM : CTR_DEVICE_PUB_PEM; const key = { diff --git a/src/server.ts b/src/server.ts index 4d90d63..6919a55 100644 --- a/src/server.ts +++ b/src/server.ts @@ -27,9 +27,9 @@ import { config } from '@/config-manager'; const app = express(); -// START APPLICATION +// * START APPLICATION -// Create router +// * Create router LOG_INFO('Setting up Middleware'); app.use(morgan('dev')); app.use(express.json()); @@ -38,7 +38,7 @@ app.use(express.urlencoded({ })); app.use(xmlparser); -// import the servers into one +// * import the servers into one app.use(conntest); app.use(cbvc); app.use(nnas); @@ -48,7 +48,7 @@ app.use(api); app.use(localcdn); app.use(assets); -// 404 handler +// * 404 handler LOG_INFO('Creating 404 status handler'); app.use((request: express.Request, response: express.Response): void => { const url = fullUrl(request); @@ -75,7 +75,7 @@ app.use((request: express.Request, response: express.Response): void => { }).end()); }); -// non-404 error handler +// * non-404 error handler LOG_INFO('Creating non-404 status handler'); app.use((error: any, request: express.Request, response: express.Response, _next: express.NextFunction): void => { const status = error.status || 500; @@ -96,7 +96,7 @@ app.use((error: any, request: express.Request, response: express.Response, _next }); async function main(): Promise { - // Starts the server + // * Starts the server LOG_INFO('Starting server'); await connectDatabase(); diff --git a/src/services/api/index.ts b/src/services/api/index.ts index 45efc53..f699f79 100644 --- a/src/services/api/index.ts +++ b/src/services/api/index.ts @@ -6,7 +6,7 @@ import { LOG_INFO } from '@/logger'; import { V1 } from '@/services/api/routes'; -// Router to handle the subdomain restriction +// * Router to handle the subdomain restriction const api = express.Router(); LOG_INFO('[USER API] Importing middleware'); @@ -14,7 +14,7 @@ api.use(APIMiddleware); api.use(cors()); api.options('*', cors()); -// Setup routes +// * Setup routes LOG_INFO('[USER API] Applying imported routes'); api.use('/v1/connections', V1.CONNECTIONS); api.use('/v1/email', V1.EMAIL); @@ -25,10 +25,10 @@ api.use('/v1/reset-password', V1.RESET_PASSWORD); api.use('/v1/user', V1.USER); -// Main router for endpoints +// * Main router for endpoints const router = express.Router(); -// Create subdomains +// * Create subdomains LOG_INFO('[USER API] Creating \'api\' subdomain'); router.use(subdomain('api', api)); diff --git a/src/services/api/routes/v1/register.ts b/src/services/api/routes/v1/register.ts index 12a1b5e..2b1928b 100644 --- a/src/services/api/routes/v1/register.ts +++ b/src/services/api/routes/v1/register.ts @@ -22,7 +22,7 @@ const PNID_PUNCTUATION_START_REGEX = /^[_\-.]/; const PNID_PUNCTUATION_END_REGEX = /[_\-.]$/; const PNID_PUNCTUATION_DUPLICATE_REGEX = /[_\-.]{2,}/; -// This sucks +// * This sucks const PASSWORD_WORD_OR_NUMBER_REGEX = /(?=.*[a-zA-Z])(?=.*\d).*/; const PASSWORD_WORD_OR_PUNCTUATION_REGEX = /(?=.*[a-zA-Z])(?=.*[_\-.]).*/; const PASSWORD_NUMBER_OR_PUNCTUATION_REGEX = /(?=.*\d)(?=.*[_\-.]).*/; @@ -250,7 +250,7 @@ router.post('/', async (request: express.Request, response: express.Response): P return; } - const miiNameBuffer = Buffer.from(miiName, 'utf16le'); // UTF8 to UTF16 + const miiNameBuffer = Buffer.from(miiName, 'utf16le'); // * UTF8 to UTF16 if (miiNameBuffer.length > 0x14) { response.status(400).json({ @@ -282,11 +282,11 @@ router.post('/', async (request: express.Request, response: express.Response): P await nexAccount.generatePID(); await nexAccount.generatePassword(); - // Quick hack to get the PIDs to match - // TODO: Change this maybe? - // NN with a NNID will always use the NNID PID - // even if the provided NEX PID is different - // To fix this we make them the same PID + // * Quick hack to get the PIDs to match + // TODO - Change this maybe? + // * NN with a NNID will always use the NNID PID + // * even if the provided NEX PID is different + // * To fix this we make them the same PID nexAccount.owning_pid = nexAccount.pid; await nexAccount.save({ session }); @@ -301,40 +301,40 @@ router.post('/', async (request: express.Request, response: express.Response): P username: username, usernameLower: username.toLowerCase(), password: passwordHash, - birthdate: '1990-01-01', // TODO: Change this - gender: 'M', // TODO: Change this - country: 'US', // TODO: Change this - language: 'en', // TODO: Change this + birthdate: '1990-01-01', // TODO - Change this + gender: 'M', // TODO - Change this + country: 'US', // TODO - Change this + language: 'en', // TODO - Change this email: { address: email.toLowerCase(), - primary: true, // TODO: Change this - parent: true, // TODO: Change this - reachable: false, // TODO: Change this - validated: false, // TODO: Change this + primary: true, // TODO - Change this + parent: true, // TODO - Change this + reachable: false, // TODO - Change this + validated: false, // TODO - Change this id: crypto.randomBytes(4).readUInt32LE() }, - region: 0x310B0000, // TODO: Change this + region: 0x310B0000, // TODO - Change this timezone: { - name: 'America/New_York', // TODO: Change this - offset: -14400 // TODO: Change this + name: 'America/New_York', // TODO - Change this + offset: -14400 // TODO - Change this }, mii: { name: miiName, - primary: true, // TODO: Change this + primary: true, // TODO - Change this data: mii.encode().toString('base64'), id: crypto.randomBytes(4).readUInt32LE(), hash: crypto.randomBytes(7).toString('hex'), - image_url: '', // deprecated, will be removed in the future + image_url: '', // * deprecated, will be removed in the future image_id: crypto.randomBytes(4).readUInt32LE() }, flags: { - active: true, // TODO: Change this - marketing: true, // TODO: Change this - off_device: true // TODO: Change this + active: true, // TODO - Change this + marketing: true, // TODO - Change this + off_device: true // TODO - Change this }, identification: { - email_code: 1, // will be overwritten before saving - email_token: '' // will be overwritten before saving + email_code: 1, // * will be overwritten before saving + email_token: '' // * will be overwritten before saving } }); diff --git a/src/services/api/routes/v1/resetPassword.ts b/src/services/api/routes/v1/resetPassword.ts index 025ca64..ad401fb 100644 --- a/src/services/api/routes/v1/resetPassword.ts +++ b/src/services/api/routes/v1/resetPassword.ts @@ -6,7 +6,7 @@ import { Token } from '@/types/common/token'; const router = express.Router(); -// This sucks +// * This sucks const PASSWORD_WORD_OR_NUMBER_REGEX = /(?=.*[a-zA-Z])(?=.*\d).*/; const PASSWORD_WORD_OR_PUNCTUATION_REGEX = /(?=.*[a-zA-Z])(?=.*[_\-.]).*/; const PASSWORD_NUMBER_OR_PUNCTUATION_REGEX = /(?=.*\d)(?=.*[_\-.]).*/; diff --git a/src/services/assets/index.ts b/src/services/assets/index.ts index 22be241..a20b710 100644 --- a/src/services/assets/index.ts +++ b/src/services/assets/index.ts @@ -1,21 +1,21 @@ -// handles serving assets +// * handles serving assets import path from 'node:path'; import express from 'express'; import subdomain from 'express-subdomain'; import { LOG_INFO } from '@/logger'; -// Router to handle the subdomain restriction +// * Router to handle the subdomain restriction const assets = express.Router(); -// Setup public folder +// * Setup public folder LOG_INFO('[assets] Setting up public folder'); assets.use(express.static(path.join(__dirname, '../../assets'))); -// Main router for endpoints +// * Main router for endpoints const router = express.Router(); -// Create subdomains +// * Create subdomains LOG_INFO('[conntest] Creating \'assets\' subdomain'); router.use(subdomain('assets', assets)); diff --git a/src/services/cbvc/index.ts b/src/services/cbvc/index.ts index 5116f93..8dd395b 100644 --- a/src/services/cbvc/index.ts +++ b/src/services/cbvc/index.ts @@ -1,13 +1,13 @@ -// handles CBVC (CTR Browser Version Check?) endpoints +// * handles CBVC (CTR Browser Version Check?) endpoints import express from 'express'; import subdomain from 'express-subdomain'; import { LOG_INFO } from '@/logger'; -// Router to handle the subdomain restriction +// * Router to handle the subdomain restriction const cbvc = express.Router(); -// Setup route +// * Setup route LOG_INFO('[cbvc] Applying imported routes'); cbvc.get('/:consoleType/:unknown/:region', (request: express.Request, response: express.Response): void => { response.set('Content-Type', 'text/plain'); @@ -21,10 +21,10 @@ cbvc.get('/:consoleType/:unknown/:region', (request: express.Request, response: response.send('0'); }); -// Main router for endpoints +// * Main router for endpoints const router = express.Router(); -// Create subdomains +// * Create subdomains LOG_INFO('[cbvc] Creating \'cbvc\' subdomain'); router.use(subdomain('cbvc.cdn', cbvc)); diff --git a/src/services/conntest/index.ts b/src/services/conntest/index.ts index 8b5f68a..47c353e 100644 --- a/src/services/conntest/index.ts +++ b/src/services/conntest/index.ts @@ -1,20 +1,20 @@ -// handles conntest endpoints +// * handles conntest endpoints import express from 'express'; import subdomain from 'express-subdomain'; import { LOG_INFO } from '@/logger'; -// Router to handle the subdomain restriction +// * Router to handle the subdomain restriction const conntest = express.Router(); -// Setup route +// * Setup route LOG_INFO('[conntest] Applying imported routes'); conntest.get('/', (request: express.Request, response: express.Response): void => { response.set('Content-Type', 'text/html'); response.set('X-Organization', 'Nintendo'); response.send(` - + HTML Page @@ -26,10 +26,10 @@ This is test.html page `); }); -// Main router for endpoints +// * Main router for endpoints const router = express.Router(); -// Create subdomains +// * Create subdomains LOG_INFO('[conntest] Creating \'conntest\' subdomain'); router.use(subdomain('conntest', conntest)); diff --git a/src/services/datastore/index.ts b/src/services/datastore/index.ts index 35b9ade..c8c3d01 100644 --- a/src/services/datastore/index.ts +++ b/src/services/datastore/index.ts @@ -4,17 +4,17 @@ import { LOG_INFO } from '@/logger'; import upload from '@/services/datastore/routes/upload'; -// Router to handle the subdomain +// * Router to handle the subdomain const datastore = express.Router(); -// Setup routes +// * Setup routes LOG_INFO('[DATASTORE] Applying imported routes'); datastore.use(upload); -// Main router for endpoints +// * Main router for endpoints const router = express.Router(); -// Create subdomains +// * Create subdomains LOG_INFO('[DATASTORE] Creating \'datastore\' subdomain'); router.use(subdomain('datastore', datastore)); diff --git a/src/services/datastore/routes/upload.ts b/src/services/datastore/routes/upload.ts index 09119d6..6e3585e 100644 --- a/src/services/datastore/routes/upload.ts +++ b/src/services/datastore/routes/upload.ts @@ -75,7 +75,7 @@ router.post('/upload', multipartParser, async (request: express.Request, respons const date = request.files.date.toString(); const signature = request.files.signature.toString(); - // Signatures only good for 1 minute + // * Signatures only good for 1 minute const minute = 1000 * 60; const minuteAgo = Date.now() - minute; diff --git a/src/services/grpc/api/register.ts b/src/services/grpc/api/register.ts index f381499..566c5a1 100644 --- a/src/services/grpc/api/register.ts +++ b/src/services/grpc/api/register.ts @@ -21,7 +21,7 @@ const PNID_PUNCTUATION_START_REGEX = /^[_\-.]/; const PNID_PUNCTUATION_END_REGEX = /[_\-.]$/; const PNID_PUNCTUATION_DUPLICATE_REGEX = /[_\-.]{2,}/; -// This sucks +// * This sucks const PASSWORD_WORD_OR_NUMBER_REGEX = /(?=.*[a-zA-Z])(?=.*\d).*/; const PASSWORD_WORD_OR_PUNCTUATION_REGEX = /(?=.*[a-zA-Z])(?=.*[_\-.]).*/; const PASSWORD_NUMBER_OR_PUNCTUATION_REGEX = /(?=.*\d)(?=.*[_\-.]).*/; @@ -146,11 +146,11 @@ export async function register(request: RegisterRequest): Promise { diff --git a/src/services/nnas/routes/people.ts b/src/services/nnas/routes/people.ts index 5d0bf3d..4e7549b 100644 --- a/src/services/nnas/routes/people.ts +++ b/src/services/nnas/routes/people.ts @@ -51,7 +51,7 @@ router.get('/:username', async (request: express.Request, response: express.Resp */ router.post('/', ratelimit, deviceCertificateMiddleware, async (request: express.Request, response: express.Response): Promise => { if (!request.certificate || !request.certificate.valid) { - // TODO: Change this to a different error + // TODO - Change this to a different error response.status(400).send(xmlbuilder.create({ error: { cause: 'Bad Request', @@ -95,11 +95,11 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request: express await nexAccount.generatePID(); await nexAccount.generatePassword(); - // Quick hack to get the PIDs to match - // TODO: Change this maybe? - // NN with a NNID will always use the NNID PID - // even if the provided NEX PID is different - // To fix this we make them the same PID + // * Quick hack to get the PIDs to match + // TODO - Change this maybe? + // * NN with a NNID will always use the NNID PID + // * even if the provided NEX PID is different + // * To fix this we make them the same PID nexAccount.owning_pid = nexAccount.pid; await nexAccount.save({ session }); @@ -156,7 +156,7 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request: express data: person.mii.data, id: crypto.randomBytes(4).readUInt32LE(), hash: crypto.randomBytes(7).toString('hex'), - image_url: '', // deprecated, will be removed in the future + image_url: '', // * deprecated, will be removed in the future image_id: crypto.randomBytes(4).readUInt32LE() }, flags: { @@ -165,8 +165,8 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request: express off_device: person.off_device_flag === 'Y' }, identification: { - email_code: 1, // will be overwritten before saving - email_token: '' // will be overwritten before saving + email_code: 1, // * will be overwritten before saving + email_token: '' // * will be overwritten before saving } }); @@ -265,9 +265,9 @@ router.post('/@me/devices', async (request: express.Request, response: express.R response.set('Server', 'Nintendo 3DS (http)'); response.set('X-Nintendo-Date', new Date().getTime().toString()); - // We don't care about the device attributes - // The console ignores them and PNIDs are not tied to consoles anyway - // So the server also ignores them and does not save the ones posted here + // * We don't care about the device attributes + // * The console ignores them and PNIDs are not tied to consoles anyway + // * So the server also ignores them and does not save the ones posted here // TODO - CHANGE THIS. WE NEED TO SAVE CONSOLE DETAILS !!! @@ -652,8 +652,8 @@ router.get('/@me/emails', async (request: express.Request, response: express.Res parent: pnid.email.parent ? 'Y' : 'N', primary: pnid.email.primary ? 'Y' : 'N', reachable: pnid.email.reachable ? 'Y' : 'N', - type: 'DEFAULT', // what is this? - updated_by: 'USER', // need to actually update this + type: 'DEFAULT', // * what is this? + updated_by: 'USER', // * need to actually update this validated: pnid.email.validated ? 'Y' : 'N', validated_date: pnid.email.validated_date, } diff --git a/src/services/nnas/routes/provider.ts b/src/services/nnas/routes/provider.ts index 794c6cf..1f87e8d 100644 --- a/src/services/nnas/routes/provider.ts +++ b/src/services/nnas/routes/provider.ts @@ -214,7 +214,7 @@ router.get('/nex_token/@me', async (request: express.Request, response: express. const tokenOptions = { system_type: server.device, - token_type: 0x3, // nex token, + token_type: 0x3, // * nex token, pid: pnid.pid, access_level: pnid.access_level, title_id: BigInt(parseInt(titleID, 16)), diff --git a/src/types/mongoose/pnid.ts b/src/types/mongoose/pnid.ts index 37ab267..3252c44 100644 --- a/src/types/mongoose/pnid.ts +++ b/src/types/mongoose/pnid.ts @@ -48,7 +48,7 @@ export interface IPNID { off_device: boolean; }; devices: Types.DocumentArray; - identification: { // user identification tokens + identification: { // * user identification tokens email_code: string; email_token: string; access_token: { diff --git a/src/types/services/nnas/pnid-profile.ts b/src/types/services/nnas/pnid-profile.ts index cb02669..70adea5 100644 --- a/src/types/services/nnas/pnid-profile.ts +++ b/src/types/services/nnas/pnid-profile.ts @@ -1,7 +1,7 @@ import { YesNoBoolString } from '@/types/common/yes-no-bool-string'; export interface PNIDProfile { - //accounts: {}; // * We need to figure this out; no idea what these values mean or what they do + // *accounts: {}; // * We need to figure this out; no idea what these values mean or what they do active_flag: YesNoBoolString; birth_date: string; country: string; diff --git a/src/util.ts b/src/util.ts index f5d8b18..42b0b33 100644 --- a/src/util.ts +++ b/src/util.ts @@ -209,7 +209,7 @@ export async function sendForgotPasswordEmail(pnid: mongoose.HydratedDocument Date: Sun, 14 Apr 2024 20:56:33 -0400 Subject: [PATCH 5/7] nnas: link 3ds device certificate to document from NASC --- src/middleware/console-status-verification.ts | 138 ++++++++++-------- 1 file changed, 78 insertions(+), 60 deletions(-) diff --git a/src/middleware/console-status-verification.ts b/src/middleware/console-status-verification.ts index 90d5cb3..a8c98a4 100644 --- a/src/middleware/console-status-verification.ts +++ b/src/middleware/console-status-verification.ts @@ -68,70 +68,88 @@ async function consoleStatusVerificationMiddleware(request: express.Request, res return; } - // * This is kinda temp for now. Needs to be redone to handle linking this data to existing 3DS devices in the DB - // TODO - 3DS consoles are created in the NASC middleware. They need special handling to link them up with the data in the NNID API! - if (request.certificate.consoleType === 'wiiu') { - const certificateDeviceID = parseInt(request.certificate.certificateName.slice(2), 16); + let device = await Device.findOne({ + serial: serialNumber, + }); - if (deviceID !== certificateDeviceID) { - // TODO - Change this to a different error - response.status(400).send(xmlbuilder.create({ - error: { - cause: 'Bad Request', - code: '1600', - message: 'Unable to process request' - } - }).end()); + if (!device && request.certificate.consoleType === '3ds') { + // * A 3DS console document will ALWAYS be created by NASC before + // * Hitting the NNAS server. NASC stores the serial number at + // * the time the device document was created. Therefore we can + // * know that serial tampering happened on the 3DS if this fails + // * to find a device document. + response.status(400).send(xmlbuilder.create({ + error: { + code: '0002', + message: 'serialNumber format is invalid' + } + }).end()); - return; - } - - // * Only store a hash of the certificate in case of a breach - const certificateHash = crypto.createHash('sha256').update(request.certificate._certificate).digest('base64'); - - let device = await Device.findOne({ - certificate_hash: certificateHash, - }); - - if (!device) { - device = await Device.create({ - model: 'wup', - device_id: deviceID, - serial: serialNumber, - linked_pids: [], - certificate_hash: certificateHash - }); - } - - if (device.serial !== serialNumber) { - // TODO - Change this to a different error - response.status(400).send(xmlbuilder.create({ - error: { - cause: 'Bad Request', - code: '1600', - message: 'Unable to process request' - } - }).end()); - - return; - } - - if (device.access_level < 0) { - response.status(400).send(xmlbuilder.create({ - errors: { - error: { - code: '0012', - message: 'Device has been banned by game server' // TODO - This is not the right error message - } - } - }).end()); - - return; - } - - request.device = device; + return; } + const certificateHash = crypto.createHash('sha256').update(request.certificate._certificate).digest('base64'); + + if (!device) { + // * Device must be a fresh Wii U + device = await Device.create({ + model: 'wup', + device_id: deviceID, + serial: serialNumber, + linked_pids: [], + certificate_hash: certificateHash + }); + } + + if (!device.certificate_hash && request.certificate.consoleType === '3ds') { + device.certificate_hash = certificateHash; + + await device.save(); + } + + if (device.serial !== serialNumber) { + // TODO - Change this to a different error + response.status(400).send(xmlbuilder.create({ + error: { + cause: 'Bad Request', + code: '1600', + message: 'Unable to process request' + } + }).end()); + + return; + } + + const certificateDeviceID = parseInt(request.certificate.certificateName.slice(2).split('-')[0], 16); + + if (deviceID !== certificateDeviceID) { + // TODO - Change this to a different error + response.status(400).send(xmlbuilder.create({ + error: { + cause: 'Bad Request', + code: '1600', + message: 'Unable to process request' + } + }).end()); + + return; + } + + if (device.access_level < 0) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0012', + message: 'Device has been banned by game server' // TODO - This is not the right error message + } + } + }).end()); + + return; + } + + request.device = device; + return next(); } From eb0b4aba00c0b955726f3e1341cc9cad079c39b4 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 14 Apr 2024 21:17:12 -0400 Subject: [PATCH 6/7] nnas: update console status middleware --- src/middleware/console-status-verification.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/middleware/console-status-verification.ts b/src/middleware/console-status-verification.ts index a8c98a4..a26d9b6 100644 --- a/src/middleware/console-status-verification.ts +++ b/src/middleware/console-status-verification.ts @@ -72,6 +72,8 @@ async function consoleStatusVerificationMiddleware(request: express.Request, res serial: serialNumber, }); + const certificateHash = crypto.createHash('sha256').update(request.certificate._certificate).digest('base64'); + if (!device && request.certificate.consoleType === '3ds') { // * A 3DS console document will ALWAYS be created by NASC before // * Hitting the NNAS server. NASC stores the serial number at @@ -86,9 +88,15 @@ async function consoleStatusVerificationMiddleware(request: express.Request, res }).end()); return; + } else if (device && !device.certificate_hash && request.certificate.consoleType === '3ds') { + device.certificate_hash = certificateHash; + + await device.save(); } - const certificateHash = crypto.createHash('sha256').update(request.certificate._certificate).digest('base64'); + device = await Device.findOne({ + certificate_hash: certificateHash, + }); if (!device) { // * Device must be a fresh Wii U @@ -101,12 +109,6 @@ async function consoleStatusVerificationMiddleware(request: express.Request, res }); } - if (!device.certificate_hash && request.certificate.consoleType === '3ds') { - device.certificate_hash = certificateHash; - - await device.save(); - } - if (device.serial !== serialNumber) { // TODO - Change this to a different error response.status(400).send(xmlbuilder.create({ From ca5ea2e30219e209bfda88ca54eee54540576b51 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Tue, 16 Apr 2024 12:22:12 -0400 Subject: [PATCH 7/7] nasc: remove MAC check. MAC is allowed to be changed --- src/middleware/nasc.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/middleware/nasc.ts b/src/middleware/nasc.ts index 812446a..64fc2bd 100644 --- a/src/middleware/nasc.ts +++ b/src/middleware/nasc.ts @@ -135,11 +135,6 @@ async function NASCMiddleware(request: express.Request, response: express.Respon response.status(200).send(nascError('102').toString()); return; } - - if (device.mac_hash !== macAddressHash) { - response.status(200).send(nascError('102').toString()); - return; - } } // * Workaround for edge case on system transfers