diff --git a/migrations/add-console-type-to-nex-account.js b/migrations/add-console-type-to-nex-account.js index b92f208..c18ed4b 100644 --- a/migrations/add-console-type-to-nex-account.js +++ b/migrations/add-console-type-to-nex-account.js @@ -31,4 +31,4 @@ database.connect().then(async function () { console.log('Migrated accounts'); process.exit(0); -}); \ No newline at end of file +}); diff --git a/migrations/add-missing-friendcodes.js b/migrations/add-missing-friendcodes.js index 4ac5aff..4d63e72 100644 --- a/migrations/add-missing-friendcodes.js +++ b/migrations/add-missing-friendcodes.js @@ -11,7 +11,6 @@ database.connect().then(async function () { }); for (const nexAccount of nexAccountsToBeChanged) { - if (!nexAccount.friend_code) { const pid = nexAccount.pid; const pidBuffer = Buffer.alloc(4); @@ -33,4 +32,4 @@ database.connect().then(async function () { console.log('Migrated accounts'); process.exit(0); -}); \ No newline at end of file +}); diff --git a/migrations/add-missing-server-aes-keys.js b/migrations/add-missing-server-aes-keys.js index 7a47379..fd87ef6 100644 --- a/migrations/add-missing-server-aes-keys.js +++ b/migrations/add-missing-server-aes-keys.js @@ -10,7 +10,6 @@ database.connect().then(async function () { }); for (const server of servers) { - if (!server.aes_key) { server.aes_key = crypto.randomBytes(32).toString('hex'); @@ -21,4 +20,4 @@ database.connect().then(async function () { console.log('Migrated accounts'); process.exit(0); -}); \ No newline at end of file +}); diff --git a/pnid-scrub.js b/pnid-scrub.js index d1abadf..6909d42 100644 --- a/pnid-scrub.js +++ b/pnid-scrub.js @@ -1,38 +1,41 @@ +const { confirm, input } = require('@inquirer/prompts'); const { connect } = require('./dist/database'); const { PNID } = require('./dist/models/pnid'); -const { confirm, input } = require('@inquirer/prompts'); async function bootstrap() { - await connect(); - - const pnidName = await input({ message: 'What PNID do you want to delete?' }); - const pnid = await PNID.findOne({ username:pnidName.trim() }); - if (!pnid) { - console.log("Could not find PNID"); - process.exit(1); - } + await connect(); - console.log('Before:', pnid); - - if (pnid.deleted) { - console.log("PNID is already marked as deleted"); - process.exit(1); - } + const pnidName = await input({ message: 'What PNID do you want to delete?' }); + const pnid = await PNID.findOne({ username: pnidName.trim() }); + if (!pnid) { + console.log('Could not find PNID'); + process.exit(1); + } - const confirmed = await confirm({ message: 'Do you want to delete this PNID',default: false }); - if (!confirmed) { - console.log("Aborted"); - process.exit(1); - } - - await pnid.scrub(); - await pnid.save(); - - console.log('After:', pnid); - if (pnid.deleted) console.log("SUCCESSFULLY DELETED"); - else console.log("COULD NOT DELETE"); - - process.exit(0); + console.log('Before:', pnid); + + if (pnid.deleted) { + console.log('PNID is already marked as deleted'); + process.exit(1); + } + + const confirmed = await confirm({ message: 'Do you want to delete this PNID', default: false }); + if (!confirmed) { + console.log('Aborted'); + process.exit(1); + } + + await pnid.scrub(); + await pnid.save(); + + console.log('After:', pnid); + if (pnid.deleted) { + console.log('SUCCESSFULLY DELETED'); + } else { + console.log('COULD NOT DELETE'); + } + + process.exit(0); } bootstrap(); diff --git a/src/cache.ts b/src/cache.ts index 7515446..49a72a3 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -11,7 +11,7 @@ const LOCAL_CDN_BASE = `${__dirname}/../cdn`; export async function connect(): Promise { if (!disabledFeatures.redis) { client = redis.createClient(config.redis.client); - client.on('error', (err) => console.log('Redis Client Error', err)); + client.on('error', err => console.log('Redis Client Error', err)); await client.connect(); } @@ -58,4 +58,4 @@ export async function getLocalCDNFile(name: string, encoding?: BufferEncoding): export async function setLocalCDNFile(name: string, value: Buffer): Promise { await setCachedFile(`local_cdn:${name}`, value); -} \ No newline at end of file +} diff --git a/src/config-manager.ts b/src/config-manager.ts index dc3080d..1573146 100644 --- a/src/config-manager.ts +++ b/src/config-manager.ts @@ -1,9 +1,10 @@ import fs from 'fs-extra'; -import mongoose from 'mongoose'; import dotenv from 'dotenv'; import isValidHostname from 'is-valid-hostname'; import { LOG_INFO, LOG_WARN, LOG_ERROR, formatHostnames } from '@/logger'; -import { type Config, domainServices, optionalDomainServices } from '@/types/common/config'; +import { domainServices, optionalDomainServices } from '@/types/common/config'; +import type mongoose from 'mongoose'; +import type { Config } from '@/types/common/config'; dotenv.config(); @@ -74,9 +75,9 @@ export const config: Config = { grpc: { master_api_keys: { account: process.env.PN_ACT_CONFIG_GRPC_MASTER_API_KEY_ACCOUNT || '', - api: process.env.PN_ACT_CONFIG_GRPC_MASTER_API_KEY_API || '', + api: process.env.PN_ACT_CONFIG_GRPC_MASTER_API_KEY_API || '' }, - port: Number(process.env.PN_ACT_CONFIG_GRPC_PORT || ''), + port: Number(process.env.PN_ACT_CONFIG_GRPC_PORT || '') }, server_environment: process.env.PN_ACT_CONFIG_SERVER_ENVIRONMENT || '', datastore: { @@ -90,7 +91,7 @@ export const config: Config = { datastore: (process.env.PN_ACT_CONFIG_DOMAINS_DATASTORE || 'datastore.pretendo.cc').split(','), local_cdn: (process.env.PN_ACT_CONFIG_DOMAINS_LOCAL_CDN || '').split(','), nasc: (process.env.PN_ACT_CONFIG_DOMAINS_NASC || 'nasc.pretendo.cc').split(','), - nnas: (process.env.PN_ACT_CONFIG_DOMAINS_NNAS || 'c.account.pretendo.cc,account.pretendo.cc').split(','), + nnas: (process.env.PN_ACT_CONFIG_DOMAINS_NNAS || 'c.account.pretendo.cc,account.pretendo.cc').split(',') } }; @@ -116,7 +117,11 @@ for (const service of domainServices) { const uniqueDomains = [...new Set(config.domains[service])]; for (const domain of uniqueDomains) { - isValidHostname(domain) ? validDomains.push(domain) : invalidDomains.push(domain); + if (isValidHostname(domain)) { + validDomains.push(domain); + } else { + invalidDomains.push(domain); + } } if (validDomains.length === 0 && !optionalDomainServices.includes(service)) { @@ -230,7 +235,7 @@ if (disabledFeatures.s3) { if (disabledFeatures.redis) { LOG_WARN('Both S3 and Redis are disabled. Large CDN files will use the in-memory cache, which may result in high memory use. Please enable S3 if you\'re running a production server.'); } - } + } } if (!config.aes_key) { @@ -270,4 +275,4 @@ if (!config.datastore.signature_secret) { if (!configValid) { LOG_ERROR('Config is invalid. Exiting'); process.exit(0); -} \ No newline at end of file +} diff --git a/src/database.ts b/src/database.ts index 72c1f7e..cbee9bc 100644 --- a/src/database.ts +++ b/src/database.ts @@ -6,13 +6,13 @@ import { PNID } from '@/models/pnid'; import { Server } from '@/models/server'; import { LOG_ERROR } from '@/logger'; import { config } from '@/config-manager'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; -import { IDeviceAttribute } from '@/types/mongoose/device-attribute'; -import { HydratedServerDocument } from '@/types/mongoose/server'; -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'; +import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; +import type { IDeviceAttribute } from '@/types/mongoose/device-attribute'; +import type { HydratedServerDocument } from '@/types/mongoose/server'; +import type { PNIDProfile } from '@/types/services/nnas/pnid-profile'; +import type { ConnectionData } from '@/types/services/api/connection-data'; +import type { ConnectionResponse } from '@/types/services/api/connection-response'; +import type { DiscordConnectionData } from '@/types/services/api/discord-connection-data'; const connection_string = config.mongoose.connection_string; const options = config.mongoose.options; @@ -202,7 +202,7 @@ export async function getPNIDProfileJSONByPID(pid: number): Promise s.access_mode === mode); - if (server) return server; + if (server) { + return server; + } } return null; @@ -237,7 +239,9 @@ export async function getServerByTitleID(titleID: string, accessMode: string): P for (const mode of searchModes) { const server = servers.find(s => s.access_mode === mode); - if (server) return server; + if (server) { + return server; + } } return null; @@ -253,7 +257,9 @@ export async function getServerByClientID(clientID: string, accessMode: string): for (const mode of searchModes) { const server = servers.find(s => s.access_mode === mode); - if (server) return server; + if (server) { + return server; + } } return null; @@ -306,4 +312,4 @@ export async function removePNIDConnectionDiscord(pnid: HydratedPNIDDocument): P app: 'api', status: 200 }; -} \ No newline at end of file +} diff --git a/src/logger.ts b/src/logger.ts index c31a44b..db662af 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -53,4 +53,4 @@ export function LOG_INFO(input: string): void { export function formatHostnames(hostnames: string[]): string { return hostnames.map(d => `'${d}'`).join(', '); -} \ No newline at end of file +} diff --git a/src/mailer.ts b/src/mailer.ts index 10efd10..0744e14 100644 --- a/src/mailer.ts +++ b/src/mailer.ts @@ -3,7 +3,7 @@ import fs from 'node:fs'; import nodemailer from 'nodemailer'; import * as aws from '@aws-sdk/client-ses'; import { config, disabledFeatures } from '@/config-manager'; -import { MailerOptions } from '@/types/common/mailer-options'; +import type { MailerOptions } from '@/types/common/mailer-options'; const genericEmailTemplate = fs.readFileSync(path.join(__dirname, './assets/emails/genericTemplate.html'), 'utf8'); const confirmationEmailTemplate = fs.readFileSync(path.join(__dirname, './assets/emails/confirmationTemplate.html'), 'utf8'); @@ -30,7 +30,7 @@ if (!disabledFeatures.email) { export async function sendMail(options: MailerOptions): Promise { if (!disabledFeatures.email) { - const { to, subject, username, paragraph, preview, text, link, confirmation } = options; + const { to, subject, username, paragraph, preview, text, link, confirmation } = options; let html = confirmation ? confirmationEmailTemplate : genericEmailTemplate; diff --git a/src/middleware/api.ts b/src/middleware/api.ts index 6bb257f..f4fd312 100644 --- a/src/middleware/api.ts +++ b/src/middleware/api.ts @@ -1,7 +1,7 @@ -import express from 'express'; import { getValueFromHeaders } from '@/util'; import { getPNIDByTokenAuth } from '@/database'; import { LOG_ERROR } from '@/logger'; +import type express from 'express'; async function APIMiddleware(request: express.Request, _response: express.Response, next: express.NextFunction): Promise { const authHeader = getValueFromHeaders(request.headers, 'authorization'); @@ -16,10 +16,12 @@ async function APIMiddleware(request: express.Request, _response: express.Respon request.pnid = pnid; } catch (error: any) { LOG_ERROR('api middleware - decode pnid: ' + error); - if (error.stack) console.error(error.stack); + if (error.stack) { + console.error(error.stack); + } } return next(); } -export default APIMiddleware; \ No newline at end of file +export default APIMiddleware; diff --git a/src/middleware/cemu.ts b/src/middleware/cemu.ts index 6edca3b..e736a90 100644 --- a/src/middleware/cemu.ts +++ b/src/middleware/cemu.ts @@ -1,4 +1,4 @@ -import express from 'express'; +import type express from 'express'; function CemuMiddleware(request: express.Request, _response: express.Response, next: express.NextFunction): void { const subdomain = request.subdomains.reverse().join('.'); @@ -8,4 +8,4 @@ function CemuMiddleware(request: express.Request, _response: express.Response, n return next(); } -export default CemuMiddleware; \ No newline at end of file +export default CemuMiddleware; diff --git a/src/middleware/client-header.ts b/src/middleware/client-header.ts index 483f8dc..3db6085 100644 --- a/src/middleware/client-header.ts +++ b/src/middleware/client-header.ts @@ -1,12 +1,12 @@ -import express from 'express'; import xmlbuilder from 'xmlbuilder'; import { getValueFromHeaders } from '@/util'; +import type express from 'express'; 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? - 'ea25c66c26b403376b4c5ed94ab9cdea': 'd137be62cb6a2b831cad8c013b92fb55', // * Possibly 3DS exclusive? + a2efa818a34fa16b8afbc8a74eba3eda: 'c91cdb5658bd4954ade78533a339cf9a', // * Possibly WiiU exclusive? + daf6227853bcbdce3d75baee8332b: '3eff548eac636e2bf45bb7b375e7b6b0', // * Possibly 3DS exclusive? + ea25c66c26b403376b4c5ed94ab9cdea: 'd137be62cb6a2b831cad8c013b92fb55' // * Possibly 3DS exclusive? }; function nintendoClientHeaderCheck(request: express.Request, response: express.Response, next: express.NextFunction): void { @@ -39,4 +39,4 @@ function nintendoClientHeaderCheck(request: express.Request, response: express.R return next(); } -export default nintendoClientHeaderCheck; \ No newline at end of file +export default nintendoClientHeaderCheck; diff --git a/src/middleware/console-status-verification.ts b/src/middleware/console-status-verification.ts index a26d9b6..c67c86e 100644 --- a/src/middleware/console-status-verification.ts +++ b/src/middleware/console-status-verification.ts @@ -1,8 +1,8 @@ import crypto from 'node:crypto'; -import express from 'express'; import xmlbuilder from 'xmlbuilder'; import { Device } from '@/models/device'; import { getValueFromHeaders } from '@/util'; +import type express from 'express'; async function consoleStatusVerificationMiddleware(request: express.Request, response: express.Response, next: express.NextFunction): Promise { if (!request.certificate || !request.certificate.valid) { @@ -69,7 +69,7 @@ async function consoleStatusVerificationMiddleware(request: express.Request, res } let device = await Device.findOne({ - serial: serialNumber, + serial: serialNumber }); const certificateHash = crypto.createHash('sha256').update(request.certificate._certificate).digest('base64'); @@ -95,7 +95,7 @@ async function consoleStatusVerificationMiddleware(request: express.Request, res } device = await Device.findOne({ - certificate_hash: certificateHash, + certificate_hash: certificateHash }); if (!device) { @@ -155,4 +155,4 @@ async function consoleStatusVerificationMiddleware(request: express.Request, res return next(); } -export default consoleStatusVerificationMiddleware; \ No newline at end of file +export default consoleStatusVerificationMiddleware; diff --git a/src/middleware/device-certificate.ts b/src/middleware/device-certificate.ts index 4080d89..8a628ff 100644 --- a/src/middleware/device-certificate.ts +++ b/src/middleware/device-certificate.ts @@ -1,6 +1,6 @@ -import express from 'express'; import NintendoCertificate from '@/nintendo-certificate'; import { getValueFromHeaders } from '@/util'; +import type express from 'express'; function deviceCertificateMiddleware(request: express.Request, _response: express.Response, next: express.NextFunction): void { const certificate = getValueFromHeaders(request.headers, 'x-nintendo-device-cert'); @@ -14,4 +14,4 @@ function deviceCertificateMiddleware(request: express.Request, _response: expres return next(); } -export default deviceCertificateMiddleware; \ No newline at end of file +export default deviceCertificateMiddleware; diff --git a/src/middleware/host-limit.ts b/src/middleware/host-limit.ts index c23e49e..cafbf8f 100644 --- a/src/middleware/host-limit.ts +++ b/src/middleware/host-limit.ts @@ -1,4 +1,4 @@ -import express from 'express'; +import type express from 'express'; export function restrictHostnames( allowedHostnames: string[], @@ -11,4 +11,4 @@ export function restrictHostnames( return next(); }; -} \ No newline at end of file +} diff --git a/src/middleware/nasc.ts b/src/middleware/nasc.ts index 7ef7053..4a40640 100644 --- a/src/middleware/nasc.ts +++ b/src/middleware/nasc.ts @@ -1,12 +1,12 @@ import crypto from 'node:crypto'; -import express from 'express'; import { Device } from '@/models/device'; import { NEXAccount } from '@/models/nex-account'; import { nascError, nintendoBase64Decode } from '@/util'; 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 type express from 'express'; +import type { NASCRequestParams } from '@/types/services/nasc/request-params'; async function NASCMiddleware(request: express.Request, response: express.Response, next: express.NextFunction): Promise { const requestParams: NASCRequestParams = request.body; @@ -103,9 +103,8 @@ async function NASCMiddleware(request: express.Request, response: express.Respon } } - let device = await Device.findOne({ - fcdcert_hash: fcdcertHash, + fcdcert_hash: fcdcertHash }); if (device) { diff --git a/src/middleware/pnid.ts b/src/middleware/pnid.ts index b473cd9..7312b18 100644 --- a/src/middleware/pnid.ts +++ b/src/middleware/pnid.ts @@ -1,8 +1,8 @@ -import express from 'express'; import xmlbuilder from 'xmlbuilder'; import { getValueFromHeaders } from '@/util'; import { getPNIDByBasicAuth, getPNIDByTokenAuth } from '@/database'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; +import type express from 'express'; +import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; async function PNIDMiddleware(request: express.Request, response: express.Response, next: express.NextFunction): Promise { const authHeader = getValueFromHeaders(request.headers, 'authorization'); @@ -84,4 +84,4 @@ async function PNIDMiddleware(request: express.Request, response: express.Respon return next(); } -export default PNIDMiddleware; \ No newline at end of file +export default PNIDMiddleware; diff --git a/src/middleware/ratelimit.ts b/src/middleware/ratelimit.ts index c12f7f1..c63cc66 100644 --- a/src/middleware/ratelimit.ts +++ b/src/middleware/ratelimit.ts @@ -1,7 +1,7 @@ import crypto from 'node:crypto'; -import express from 'express'; import ratelimit from 'express-rate-limit'; import { getValueFromHeaders } from '@/util'; +import type express from 'express'; export default ratelimit({ windowMs: 60 * 1000, @@ -15,4 +15,4 @@ export default ratelimit({ return crypto.createHash('md5').update(data).digest('hex'); } -}); \ No newline at end of file +}); diff --git a/src/middleware/xml-parser.ts b/src/middleware/xml-parser.ts index 9732053..d1ed545 100644 --- a/src/middleware/xml-parser.ts +++ b/src/middleware/xml-parser.ts @@ -1,7 +1,7 @@ -import express from 'express'; import xmlbuilder from 'xmlbuilder'; import { document as xmlParser } from 'xmlbuilder2'; import { getValueFromHeaders, mapToObject } from '@/util'; +import type express from 'express'; function XMLMiddleware(request: express.Request, response: express.Response, next: express.NextFunction): void { if (request.method == 'POST' || request.method == 'PUT') { @@ -33,7 +33,7 @@ function XMLMiddleware(request: express.Request, response: express.Response, nex request.body = xmlParser(body); request.body = request.body.toObject(); request.body = mapToObject(request.body); - } catch (error) { + } catch { // TODO - This is not a real error code, check to see if better one exists return response.status(401).send(xmlbuilder.create({ errors: { @@ -52,4 +52,4 @@ function XMLMiddleware(request: express.Request, response: express.Response, nex } } -export default XMLMiddleware; \ No newline at end of file +export default XMLMiddleware; diff --git a/src/models/device.ts b/src/models/device.ts index 61dbfbb..6fd130b 100644 --- a/src/models/device.ts +++ b/src/models/device.ts @@ -1,6 +1,6 @@ import { Schema, model } from 'mongoose'; -import { IDeviceAttribute, IDeviceAttributeMethods, DeviceAttributeModel } from '@/types/mongoose/device-attribute'; -import { IDevice, IDeviceMethods, DeviceModel } from '@/types/mongoose/device'; +import type { IDeviceAttribute, IDeviceAttributeMethods, DeviceAttributeModel } from '@/types/mongoose/device-attribute'; +import type { IDevice, IDeviceMethods, DeviceModel } from '@/types/mongoose/device'; const DeviceAttributeSchema = new Schema({ created_date: String, @@ -18,7 +18,7 @@ export const DeviceSchema = new Schema({ 'ftr', // * Nintendo 2DS 'ktr', // * New Nintendo 3DS 'red', // * New Nintendo 3DS XL - 'jan' // * New Nintendo 2DS XL + 'jan' // * New Nintendo 2DS XL ] }, device_id: Number, @@ -27,15 +27,15 @@ export const DeviceSchema = new Schema({ device_attributes: [DeviceAttributeSchema], soap: { token: String, - account_id: Number, + account_id: Number }, environment: String, - mac_hash: String, // * 3DS-specific + mac_hash: String, // * 3DS-specific fcdcert_hash: String, // * 3DS-specific 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, @@ -44,4 +44,4 @@ export const DeviceSchema = new Schema({ certificate_hash: String }); -export const Device = model('Device', DeviceSchema); \ No newline at end of file +export const Device = model('Device', DeviceSchema); diff --git a/src/models/nex-account.ts b/src/models/nex-account.ts index c731f07..6f08d83 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 { INEXAccount, INEXAccountMethods, NEXAccountModel } from '@/types/mongoose/nex-account'; +import type { INEXAccount, INEXAccountMethods, NEXAccountModel } from '@/types/mongoose/nex-account'; const NEXAccountSchema = new Schema({ device_type: { @@ -8,7 +8,7 @@ const NEXAccountSchema = new Schema('NEXAccount', NEXAccountSchema); \ No newline at end of file +export const NEXAccount = model('NEXAccount', NEXAccountSchema); diff --git a/src/models/pnid.ts b/src/models/pnid.ts index a5509d0..d3f4bd8 100644 --- a/src/models/pnid.ts +++ b/src/models/pnid.ts @@ -9,16 +9,16 @@ import Stripe from 'stripe'; import { DeviceSchema } from '@/models/device'; import { uploadCDNAsset } from '@/util'; import { LOG_ERROR, LOG_WARN } from '@/logger'; -import { IPNID, IPNIDMethods, PNIDModel } from '@/types/mongoose/pnid'; -import { PNIDPermissionFlag } from '@/types/common/permission-flags'; import { config } from '@/config-manager'; +import type { IPNID, IPNIDMethods, PNIDModel } from '@/types/mongoose/pnid'; +import type { PNIDPermissionFlag } from '@/types/common/permission-flags'; let stripe: Stripe; if (config.stripe?.secret_key) { stripe = new Stripe(config.stripe.secret_key, { apiVersion: '2022-11-15', - typescript: true, + typescript: true }); } @@ -33,7 +33,7 @@ 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, @@ -81,7 +81,7 @@ const PNIDSchema = new Schema({ id: Number, hash: String, image_url: String, - image_id: Number, + image_id: Number }, flags: { active: Boolean, @@ -122,7 +122,7 @@ const PNIDSchema = new Schema({ } }, { id: false }); -PNIDSchema.plugin(uniqueValidator, {message: '{PATH} already in use.'}); +PNIDSchema.plugin(uniqueValidator, { message: '{PATH} already in use.' }); /* According to http://pf2m.com/tools/rank.php Nintendo PID's start at 1,800,000,000 and count down with each account @@ -136,7 +136,7 @@ PNIDSchema.method('generatePID', async function generatePID(): Promise { 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); + const pid = Math.floor(Math.random() * (max - min + 1) + min); const inuse = await PNID.findOne({ pid @@ -171,7 +171,7 @@ PNIDSchema.method('generateEmailValidationToken', async function generateEmailVa } }); -PNIDSchema.method('updateMii', async function updateMii({ name, primary, data }: { name: string; primary: string; data: string; }): Promise { +PNIDSchema.method('updateMii', async function updateMii({ name, primary, data }: { name: string; primary: string; data: string }): Promise { this.mii.name = name; this.mii.primary = primary === 'Y'; this.mii.data = data; @@ -190,7 +190,7 @@ PNIDSchema.method('generateMiiImages', async function generateMiiImages(): Promi const miiStudioUrl = mii.studioUrl({ type: 'face', width: 128, - instanceCount: 1, + instanceCount: 1 }); const miiStudioNormalFaceImageData = await got(miiStudioUrl).buffer(); const pngData = await imagePixels(miiStudioNormalFaceImageData); @@ -207,7 +207,7 @@ PNIDSchema.method('generateMiiImages', async function generateMiiImages(): Promi type: 'face', expression: expression, width: 128, - instanceCount: 1, + instanceCount: 1 }); const miiStudioExpressionImageData = await got(miiStudioExpressionUrl).buffer(); await uploadCDNAsset(config.s3.bucket, `${userMiiKey}/${expression}.png`, miiStudioExpressionImageData, 'public-read'); @@ -216,7 +216,7 @@ PNIDSchema.method('generateMiiImages', async function generateMiiImages(): Promi const miiStudioBodyUrl = mii.studioUrl({ type: 'all_body', width: 270, - instanceCount: 1, + instanceCount: 1 }); const miiStudioBodyImageData = await got(miiStudioBodyUrl).buffer(); await uploadCDNAsset(config.s3.bucket, `${userMiiKey}/body.png`, miiStudioBodyImageData, 'public-read'); @@ -290,4 +290,4 @@ PNIDSchema.method('clearPermission', function clearPermission(flag: PNIDPermissi this.permissions &= ~flag; }); -export const PNID = model('PNID', PNIDSchema); \ No newline at end of file +export const PNID = model('PNID', PNIDSchema); diff --git a/src/models/server.ts b/src/models/server.ts index 3ab6fce..8639281 100644 --- a/src/models/server.ts +++ b/src/models/server.ts @@ -1,6 +1,6 @@ import { Schema, model } from 'mongoose'; import uniqueValidator from 'mongoose-unique-validator'; -import { IServer, IServerMethods, ServerModel } from '@/types/mongoose/server'; +import type { IServer, IServerMethods, ServerModel } from '@/types/mongoose/server'; const ServerSchema = new Schema({ client_id: String, @@ -18,4 +18,4 @@ const ServerSchema = new Schema({ ServerSchema.plugin(uniqueValidator, { message: '{PATH} already in use.' }); -export const Server = model('Server', ServerSchema); \ No newline at end of file +export const Server = model('Server', ServerSchema); diff --git a/src/nintendo-certificate.ts b/src/nintendo-certificate.ts index 2e2f31f..dd14ade 100644 --- a/src/nintendo-certificate.ts +++ b/src/nintendo-certificate.ts @@ -1,6 +1,6 @@ import crypto from 'node:crypto'; import NodeRSA from 'node-rsa'; -import { SignatureSize } from '@/types/common/signature-size'; +import type { SignatureSize } from '@/types/common/signature-size'; const WIIU_DEVICE_PUB_PEM = `-----BEGIN PUBLIC KEY----- MFIwEAYHKoZIzj0CAQYFK4EEABsDPgAEAP1WBBgs8XUJIQDDCK5IOZEbb5+h1TqV @@ -229,11 +229,11 @@ class NintendoCertificate { publicKey.importKey({ n: CTR_LFCS_B_PUB, - e: 65537, + e: 65537 }, 'components-public'); this.valid = publicKey.verify(this._certificateBody, this.signature); } } -export default NintendoCertificate; \ No newline at end of file +export default NintendoCertificate; diff --git a/src/server.ts b/src/server.ts index 4d63d04..c864b9d 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,12 +1,3 @@ -process.title = 'Pretendo - Account'; -process.on('uncaughtException', (err, origin) => { - console.log(err); - console.log(origin); -}); -process.on('SIGTERM', () => { - process.exit(0); -}); - import express from 'express'; import morgan from 'morgan'; import xmlbuilder from 'xmlbuilder'; @@ -16,7 +7,6 @@ import { connect as connectDatabase } from '@/database'; import { startGRPCServer } from '@/services/grpc/server'; import { fullUrl, getValueFromHeaders } from '@/util'; import { LOG_INFO, LOG_SUCCESS, LOG_WARN } from '@/logger'; - import conntest from '@/services/conntest'; import cbvc from '@/services/cbvc'; import nnas from '@/services/nnas'; @@ -25,9 +15,17 @@ import datastore from '@/services/datastore'; import api from '@/services/api'; import localcdn from '@/services/local-cdn'; import assets from '@/services/assets'; - import { config, disabledFeatures } from '@/config-manager'; +process.title = 'Pretendo - Account'; +process.on('uncaughtException', (err, origin) => { + console.log(err); + console.log(origin); +}); +process.on('SIGTERM', () => { + process.exit(0); +}); + const app = express(); // * START APPLICATION diff --git a/src/services/api/index.ts b/src/services/api/index.ts index b7ad859..9420158 100644 --- a/src/services/api/index.ts +++ b/src/services/api/index.ts @@ -2,7 +2,6 @@ import express from 'express'; import cors from 'cors'; import APIMiddleware from '@/middleware/api'; import { formatHostnames, LOG_INFO } from '@/logger'; - import { V1 } from '@/services/api/routes'; import { config } from '@/config-manager'; import { restrictHostnames } from '@/middleware/host-limit'; @@ -25,7 +24,6 @@ api.use('/v1/register', V1.REGISTER); api.use('/v1/reset-password', V1.RESET_PASSWORD); api.use('/v1/user', V1.USER); - // * Main router for endpoints const router = express.Router(); @@ -33,4 +31,4 @@ const router = express.Router(); LOG_INFO(`[USER API] Registering api router with domains: ${formatHostnames(config.domains.api)}`); router.use(restrictHostnames(config.domains.api, api)); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/api/routes/index.ts b/src/services/api/routes/index.ts index 6f25c45..de8208b 100644 --- a/src/services/api/routes/index.ts +++ b/src/services/api/routes/index.ts @@ -14,4 +14,4 @@ export const V1 = { REGISTER: register_v1, RESET_PASSWORD: resetPassword_v1, USER: user_v1 -}; \ No newline at end of file +}; diff --git a/src/services/api/routes/v1/connections.ts b/src/services/api/routes/v1/connections.ts index 2a0612a..2ddf36d 100644 --- a/src/services/api/routes/v1/connections.ts +++ b/src/services/api/routes/v1/connections.ts @@ -102,4 +102,4 @@ router.delete('/remove/:type', async (request: express.Request, response: expres response.status(result.status).json(result); }); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/api/routes/v1/email.ts b/src/services/api/routes/v1/email.ts index fa306c5..9c70934 100644 --- a/src/services/api/routes/v1/email.ts +++ b/src/services/api/routes/v1/email.ts @@ -45,4 +45,4 @@ router.get('/verify', async (request: express.Request, response: express.Respons response.status(200).send('Email validated. You may close this window'); }); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/api/routes/v1/forgotPassword.ts b/src/services/api/routes/v1/forgotPassword.ts index 99f127d..9aebd63 100644 --- a/src/services/api/routes/v1/forgotPassword.ts +++ b/src/services/api/routes/v1/forgotPassword.ts @@ -4,7 +4,7 @@ import hcaptcha from 'hcaptcha'; import { getPNIDByEmailAddress, getPNIDByUsername } from '@/database'; import { sendForgotPasswordEmail } from '@/util'; import { config, disabledFeatures } from '@/config-manager'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; +import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; const router = express.Router(); @@ -17,7 +17,7 @@ router.post('/', async (request: express.Request, response: express.Response): P response.status(400).json({ app: 'api', status: 400, - error: 'Must fill in captcha', + error: 'Must fill in captcha' }); return; @@ -32,7 +32,7 @@ router.post('/', async (request: express.Request, response: express.Response): P response.status(400).json({ app: 'api', status: 400, - error: 'Captcha verification failed', + error: 'Captcha verification failed' }); return; @@ -67,4 +67,4 @@ router.post('/', async (request: express.Request, response: express.Response): P }); }); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/api/routes/v1/login.ts b/src/services/api/routes/v1/login.ts index 09e34e2..2efed2a 100644 --- a/src/services/api/routes/v1/login.ts +++ b/src/services/api/routes/v1/login.ts @@ -1,10 +1,10 @@ import express from 'express'; import bcrypt from 'bcrypt'; import { getPNIDByUsername, getPNIDByTokenAuth } from '@/database'; -import { nintendoPasswordHash, generateToken} from '@/util'; +import { nintendoPasswordHash, generateToken } from '@/util'; import { config } from '@/config-manager'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; import { LOG_ERROR } from '@/logger'; +import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; const router = express.Router(); @@ -127,9 +127,8 @@ router.post('/', async (request: express.Request, response: express.Response): P title_id: BigInt(0), expire_time: BigInt(Date.now() + (3600 * 1000)) }; - - try { + try { const accessTokenBuffer = await generateToken(config.aes_key, accessTokenOptions); const refreshTokenBuffer = await generateToken(config.aes_key, refreshTokenOptions); @@ -146,8 +145,10 @@ router.post('/', async (request: express.Request, response: express.Response): P }); } catch (error: any) { LOG_ERROR('/v1/login - token generation: ' + error); - if (error.stack) console.error(error.stack); - + if (error.stack) { + console.error(error.stack); + } + response.status(500).json({ app: 'api', status: 500, @@ -156,4 +157,4 @@ router.post('/', async (request: express.Request, response: express.Response): P } }); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/api/routes/v1/register.ts b/src/services/api/routes/v1/register.ts index a2aec5b..e1dc4bc 100644 --- a/src/services/api/routes/v1/register.ts +++ b/src/services/api/routes/v1/register.ts @@ -1,4 +1,3 @@ - import crypto from 'node:crypto'; import express from 'express'; import emailvalidator from 'email-validator'; @@ -12,8 +11,8 @@ import { LOG_ERROR } from '@/logger'; import { PNID } from '@/models/pnid'; import { NEXAccount } from '@/models/nex-account'; import { config, disabledFeatures } from '@/config-manager'; -import { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; +import type { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; +import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; const router = express.Router(); @@ -276,7 +275,7 @@ router.post('/', async (request: express.Request, response: express.Response): P // * PNIDs can only be registered from a Wii U // * So assume website users are WiiU NEX accounts nexAccount = new NEXAccount({ - device_type: 'wiiu', + device_type: 'wiiu' }); await nexAccount.generatePID(); @@ -347,7 +346,9 @@ router.post('/', async (request: express.Request, response: express.Response): P await session.commitTransaction(); } catch (error: any) { LOG_ERROR('[POST] /v1/register: ' + error); - if (error.stack) console.error(error.stack); + if (error.stack) { + console.error(error.stack); + } await session.abortTransaction(); @@ -401,7 +402,9 @@ router.post('/', async (request: express.Request, response: express.Response): P }); } catch (error: any) { LOG_ERROR('/v1/register - token generation: ' + error); - if (error.stack) console.error(error.stack); + if (error.stack) { + console.error(error.stack); + } response.status(500).json({ app: 'api', @@ -411,4 +414,4 @@ router.post('/', async (request: express.Request, response: express.Response): P } }); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/api/routes/v1/resetPassword.ts b/src/services/api/routes/v1/resetPassword.ts index ad401fb..b7c5dcc 100644 --- a/src/services/api/routes/v1/resetPassword.ts +++ b/src/services/api/routes/v1/resetPassword.ts @@ -2,7 +2,7 @@ import express from 'express'; import bcrypt from 'bcrypt'; import { PNID } from '@/models/pnid'; import { decryptToken, unpackToken, nintendoPasswordHash } from '@/util'; -import { Token } from '@/types/common/token'; +import type { Token } from '@/types/common/token'; const router = express.Router(); @@ -31,7 +31,7 @@ router.post('/', async (request: express.Request, response: express.Response): P try { const decryptedToken = await decryptToken(Buffer.from(token, 'hex')); unpackedToken = unpackToken(decryptedToken); - } catch (error) { + } catch { response.status(400).json({ app: 'api', status: 400, @@ -63,7 +63,6 @@ router.post('/', async (request: express.Request, response: express.Response): P return; } - if (!password || password === '') { response.status(400).json({ app: 'api', @@ -147,4 +146,4 @@ router.post('/', async (request: express.Request, response: express.Response): P }); }); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/api/routes/v1/user.ts b/src/services/api/routes/v1/user.ts index f024551..0d1dd2d 100644 --- a/src/services/api/routes/v1/user.ts +++ b/src/services/api/routes/v1/user.ts @@ -3,7 +3,7 @@ import { z } from 'zod'; import Mii from 'mii-js'; import { config } from '@/config-manager'; import { PNID } from '@/models/pnid'; -import { UpdateUserRequest } from '@/types/services/api/update-user-request'; +import type { UpdateUserRequest } from '@/types/services/api/update-user-request'; const router = express.Router(); @@ -12,7 +12,7 @@ const userSchema = z.object({ mii: z.object({ name: z.string().trim(), primary: z.enum(['Y', 'N']), - data: z.string(), + data: z.string() }).optional(), environment: z.enum(['prod', 'test', 'dev']).optional() }); @@ -46,7 +46,7 @@ router.get('/', async (request: express.Request, response: express.Response): Pr gender: pnid.gender, country: pnid.country, email: { - address: pnid.email.address, + address: pnid.email.address }, timezone: { name: pnid.timezone.name @@ -150,7 +150,7 @@ router.post('/', async (request: express.Request, response: express.Response): P const mii = new Mii(miiDataBuffer); mii.validate(); - } catch (_) { + } catch { response.status(400).json({ app: 'api', status: 400, @@ -208,7 +208,7 @@ router.post('/', async (request: express.Request, response: express.Response): P gender: pnid.gender, country: pnid.country, email: { - address: pnid.email.address, + address: pnid.email.address }, timezone: { name: pnid.timezone.name @@ -229,4 +229,4 @@ router.post('/', async (request: express.Request, response: express.Response): P }); }); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/assets/index.ts b/src/services/assets/index.ts index 72d1a52..abf67ba 100644 --- a/src/services/assets/index.ts +++ b/src/services/assets/index.ts @@ -1,4 +1,4 @@ -// * handles serving assets +// * handles serving assets import path from 'node:path'; import express from 'express'; @@ -20,4 +20,4 @@ const router = express.Router(); LOG_INFO(`[assets] Creating assets router with domains: ${formatHostnames(config.domains.assets)}`); router.use(restrictHostnames(config.domains.assets, assets)); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/conntest/index.ts b/src/services/conntest/index.ts index 738ad41..f46ad97 100644 --- a/src/services/conntest/index.ts +++ b/src/services/conntest/index.ts @@ -34,4 +34,4 @@ const router = express.Router(); LOG_INFO(`[conntest] Creating conntest router with domains: ${formatHostnames(config.domains.conntest)}`); router.use(restrictHostnames(config.domains.conntest, conntest)); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/datastore/index.ts b/src/services/datastore/index.ts index 296547d..d215a40 100644 --- a/src/services/datastore/index.ts +++ b/src/services/datastore/index.ts @@ -1,6 +1,5 @@ import express from 'express'; import { LOG_INFO, formatHostnames } from '@/logger'; - import upload from '@/services/datastore/routes/upload'; import { restrictHostnames } from '@/middleware/host-limit'; import { config } from '@/config-manager'; @@ -19,4 +18,4 @@ const router = express.Router(); LOG_INFO(`[DATASTORE] Creating datastore router with domains: ${formatHostnames(config.domains.datastore)}`); router.use(restrictHostnames(config.domains.datastore, datastore)); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/datastore/routes/upload.ts b/src/services/datastore/routes/upload.ts index 9827781..c9883a6 100644 --- a/src/services/datastore/routes/upload.ts +++ b/src/services/datastore/routes/upload.ts @@ -29,7 +29,7 @@ function multipartParser(request: express.Request, response: express.Response, n let fileBuffer = Buffer.alloc(0); let fileName = ''; - part.on('header', header => { + part.on('header', (header) => { const contentDisposition = header['content-disposition' as keyof object]; const regexResult = RE_FILE_NAME.exec(contentDisposition); @@ -97,4 +97,4 @@ router.post('/upload', multipartParser, async (request: express.Request, respons response.sendStatus(200); }); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/grpc/account/api-key-middleware.ts b/src/services/grpc/account/api-key-middleware.ts index 2a6158d..c79e0fb 100644 --- a/src/services/grpc/account/api-key-middleware.ts +++ b/src/services/grpc/account/api-key-middleware.ts @@ -1,9 +1,10 @@ -import { Status, ServerMiddlewareCall, CallContext, ServerError } from 'nice-grpc'; +import { Status, ServerError } from 'nice-grpc'; import { config } from '@/config-manager'; +import type { ServerMiddlewareCall, CallContext } from 'nice-grpc'; export async function* apiKeyMiddleware( call: ServerMiddlewareCall, - context: CallContext, + context: CallContext ): AsyncGenerator { const apiKey = context.metadata.get('X-API-Key'); @@ -12,4 +13,4 @@ export async function* apiKeyMiddleware( } return yield* call.next(call.request, context); -} \ No newline at end of file +} 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 347c4da..167b1ba 100644 --- a/src/services/grpc/account/exchange-token-for-user-data.ts +++ b/src/services/grpc/account/exchange-token-for-user-data.ts @@ -1,9 +1,9 @@ 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 { PNID_PERMISSION_FLAGS } from '@/types/common/permission-flags'; import { config } from '@/config-manager'; +import type { GetUserDataResponse } from '@pretendonetwork/grpc/account/get_user_data_rpc'; +import type { ExchangeTokenForUserDataRequest } from '@pretendonetwork/grpc/account/exchange_token_for_user_data'; export async function exchangeTokenForUserData(request: ExchangeTokenForUserDataRequest): Promise { if (!request.token.trim()) { @@ -25,7 +25,7 @@ export async function exchangeTokenForUserData(request: ExchangeTokenForUserData mii: { name: pnid.mii.name, data: pnid.mii.data, - url: `${config.cdn.base_url}/mii/${pnid.pid}/standard.tga`, + url: `${config.cdn.base_url}/mii/${pnid.pid}/standard.tga` }, creationDate: pnid.creation_date, birthdate: pnid.birthdate, @@ -59,4 +59,4 @@ export async function exchangeTokenForUserData(request: ExchangeTokenForUserData updatePnidPermissions: pnid.hasPermission(PNID_PERMISSION_FLAGS.UPDATE_PNID_PERMISSIONS) } }; -} \ No newline at end of file +} diff --git a/src/services/grpc/account/get-nex-data.ts b/src/services/grpc/account/get-nex-data.ts index 38a938d..b517e00 100644 --- a/src/services/grpc/account/get-nex-data.ts +++ b/src/services/grpc/account/get-nex-data.ts @@ -1,6 +1,6 @@ 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 type { GetNEXDataRequest, GetNEXDataResponse, DeepPartial } from '@pretendonetwork/grpc/account/get_nex_data_rpc'; export async function getNEXData(request: GetNEXDataRequest): Promise> { const nexAccount = await NEXAccount.findOne({ pid: request.pid }); @@ -8,7 +8,7 @@ export async function getNEXData(request: GetNEXDataRequest): Promise> { const nexAccount = await NEXAccount.findOne({ pid: request.pid }); @@ -8,7 +8,7 @@ export async function getNEXPassword(request: GetNEXPasswordRequest): Promise { const pnid = await getPNIDByPID(request.pid); @@ -10,7 +10,7 @@ export async function getUserData(request: GetUserDataRequest): Promise { @@ -10,14 +10,14 @@ export async function updatePNIDPermissions(request: UpdatePNIDPermissionsReques if (!pnid) { throw new ServerError( Status.INVALID_ARGUMENT, - 'No PNID found', + 'No PNID found' ); } if (!request.permissions) { throw new ServerError( Status.INVALID_ARGUMENT, - 'Permissions flags not found', + 'Permissions flags not found' ); } @@ -156,4 +156,4 @@ export async function updatePNIDPermissions(request: UpdatePNIDPermissionsReques await pnid.save(); return {}; -} \ No newline at end of file +} diff --git a/src/services/grpc/api/api-key-middleware.ts b/src/services/grpc/api/api-key-middleware.ts index 215df34..c88f5b1 100644 --- a/src/services/grpc/api/api-key-middleware.ts +++ b/src/services/grpc/api/api-key-middleware.ts @@ -1,9 +1,10 @@ -import { Status, ServerMiddlewareCall, CallContext, ServerError } from 'nice-grpc'; +import { Status, ServerError } from 'nice-grpc'; import { config } from '@/config-manager'; +import type { ServerMiddlewareCall, CallContext } from 'nice-grpc'; export async function* apiKeyMiddleware( call: ServerMiddlewareCall, - context: CallContext, + context: CallContext ): AsyncGenerator { const apiKey = context.metadata.get('X-API-Key'); @@ -12,4 +13,4 @@ export async function* apiKeyMiddleware( } return yield* call.next(call.request, context); -} \ No newline at end of file +} diff --git a/src/services/grpc/api/authentication-middleware.ts b/src/services/grpc/api/authentication-middleware.ts index c466c9e..d6434a6 100644 --- a/src/services/grpc/api/authentication-middleware.ts +++ b/src/services/grpc/api/authentication-middleware.ts @@ -1,5 +1,6 @@ -import { Status, ServerMiddlewareCall, CallContext, ServerError } from 'nice-grpc'; +import { Status, ServerError } from 'nice-grpc'; import { getPNIDByTokenAuth } from '@/database'; +import type { ServerMiddlewareCall, CallContext } from 'nice-grpc'; import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; // * These paths require that a token be present @@ -18,7 +19,7 @@ export type AuthenticationCallContextExt = { export async function* authenticationMiddleware( call: ServerMiddlewareCall, - context: CallContext, + context: CallContext ): AsyncGenerator { const token = context.metadata.get('X-Token')?.trim(); @@ -52,4 +53,4 @@ export async function* authenticationMiddleware( throw new ServerError(Status.INVALID_ARGUMENT, message); } -} \ No newline at end of file +} diff --git a/src/services/grpc/api/forgot-password.ts b/src/services/grpc/api/forgot-password.ts index 45b9b6e..30733cd 100644 --- a/src/services/grpc/api/forgot-password.ts +++ b/src/services/grpc/api/forgot-password.ts @@ -1,8 +1,8 @@ import { Status, ServerError } from 'nice-grpc'; import validator from 'validator'; -import { ForgotPasswordRequest } from '@pretendonetwork/grpc/api/forgot_password_rpc'; import { getPNIDByEmailAddress, getPNIDByUsername } from '@/database'; import { sendForgotPasswordEmail } from '@/util'; +import type { ForgotPasswordRequest } from '@pretendonetwork/grpc/api/forgot_password_rpc'; import type { Empty } from '@pretendonetwork/grpc/api/google/protobuf/empty'; import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; @@ -26,4 +26,4 @@ export async function forgotPassword(request: ForgotPasswordRequest): Promise> { @@ -86,4 +86,4 @@ export async function login(request: LoginRequest): Promise{ +export async function setDiscordConnectionData(request: SetDiscordConnectionDataRequest, context: CallContext & AuthenticationCallContextExt): Promise { // * This is asserted in authentication-middleware, we know this is never null const pnid = context.pnid!; @@ -22,4 +23,4 @@ export async function setDiscordConnectionData(request: SetDiscordConnectionData } return {}; -} \ No newline at end of file +} diff --git a/src/services/grpc/api/set-stripe-connection-data.ts b/src/services/grpc/api/set-stripe-connection-data.ts index 2af96b8..307a6a1 100644 --- a/src/services/grpc/api/set-stripe-connection-data.ts +++ b/src/services/grpc/api/set-stripe-connection-data.ts @@ -1,12 +1,13 @@ -import { Status, ServerError, CallContext } from 'nice-grpc'; -import { SetStripeConnectionDataRequest } from '@pretendonetwork/grpc/api/set_stripe_connection_data_rpc'; +import { Status, ServerError } from 'nice-grpc'; import { PNID } from '@/models/pnid'; +import type { CallContext } from 'nice-grpc'; +import type { SetStripeConnectionDataRequest } from '@pretendonetwork/grpc/api/set_stripe_connection_data_rpc'; import type { Empty } from '@pretendonetwork/grpc/api/google/protobuf/empty'; import type { AuthenticationCallContextExt } from '@/services/grpc/api/authentication-middleware'; type StripeMongoUpdateScheme = { - access_level?: number; - server_access_level?: string; + 'access_level'?: number; + 'server_access_level'?: string; 'connections.stripe.customer_id'?: string; 'connections.stripe.subscription_id'?: string; 'connections.stripe.price_id'?: string; @@ -15,7 +16,7 @@ type StripeMongoUpdateScheme = { 'connections.stripe.latest_webhook_timestamp': number; }; -export async function setStripeConnectionData(request: SetStripeConnectionDataRequest, context: CallContext & AuthenticationCallContextExt): Promise{ +export async function setStripeConnectionData(request: SetStripeConnectionDataRequest, context: CallContext & AuthenticationCallContextExt): Promise { // * This is asserted in authentication-middleware, we know this is never null const pnid = context.pnid!; @@ -61,7 +62,7 @@ export async function setStripeConnectionData(request: SetStripeConnectionDataRe if (pnid.connections.stripe.latest_webhook_timestamp && pnid.connections.stripe.customer_id) { // * Stripe customer data has already been initialized, update it await PNID.updateOne({ - pid: pnid.pid, + 'pid': pnid.pid, 'connections.stripe.latest_webhook_timestamp': { $lte: request.timestamp } @@ -87,4 +88,4 @@ export async function setStripeConnectionData(request: SetStripeConnectionDataRe } return {}; -} \ No newline at end of file +} diff --git a/src/services/grpc/api/update-user-data.ts b/src/services/grpc/api/update-user-data.ts index a842f38..1fc21d2 100644 --- a/src/services/grpc/api/update-user-data.ts +++ b/src/services/grpc/api/update-user-data.ts @@ -1,7 +1,7 @@ -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 { CallContext } from 'nice-grpc'; +import type { UpdateUserDataRequest, DeepPartial } from '@pretendonetwork/grpc/api/update_user_data_rpc'; +import type { GetUserDataResponse } from '@pretendonetwork/grpc/api/get_user_data_rpc'; import type { AuthenticationCallContextExt } from '@/services/grpc/api/authentication-middleware'; export async function updateUserData(_request: UpdateUserDataRequest, context: CallContext & AuthenticationCallContextExt): Promise> { @@ -21,7 +21,7 @@ export async function updateUserData(_request: UpdateUserDataRequest, context: C mii: { name: pnid.mii.name, data: pnid.mii.data, - url: `${config.cdn.base_url}/mii/${pnid.pid}/standard.tga`, + url: `${config.cdn.base_url}/mii/${pnid.pid}/standard.tga` }, birthday: pnid.birthdate, gender: pnid.gender, diff --git a/src/services/grpc/server.ts b/src/services/grpc/server.ts index 3032034..b4dee0d 100644 --- a/src/services/grpc/server.ts +++ b/src/services/grpc/server.ts @@ -1,14 +1,11 @@ import { createServer } from 'nice-grpc'; import { AccountDefinition } from '@pretendonetwork/grpc/account/account_service'; import { APIDefinition } from '@pretendonetwork/grpc/api/api_service'; - import { apiKeyMiddleware as accountApiKeyMiddleware } from '@/services/grpc/account/api-key-middleware'; import { apiKeyMiddleware as apiApiKeyMiddleware } from '@/services/grpc/api/api-key-middleware'; import { authenticationMiddleware as apiAuthenticationMiddleware } from '@/services/grpc/api/authentication-middleware'; - import { accountServiceImplementation } from '@/services/grpc/account/implementation'; import { apiServiceImplementation } from '@/services/grpc/api/implementation'; - import { config } from '@/config-manager'; export async function startGRPCServer(): Promise { @@ -18,4 +15,4 @@ export async function startGRPCServer(): Promise { server.with(apiApiKeyMiddleware).with(apiAuthenticationMiddleware).add(APIDefinition, apiServiceImplementation); await server.listen(`0.0.0.0:${config.grpc.port}`); -} \ No newline at end of file +} diff --git a/src/services/local-cdn/index.ts b/src/services/local-cdn/index.ts index 5c837ee..8dbe39b 100644 --- a/src/services/local-cdn/index.ts +++ b/src/services/local-cdn/index.ts @@ -1,7 +1,6 @@ import express from 'express'; import { config, disabledFeatures } from '@/config-manager'; import { LOG_INFO, formatHostnames } from '@/logger'; - import get from '@/services/local-cdn/routes/get'; import { restrictHostnames } from '@/middleware/host-limit'; @@ -24,4 +23,4 @@ if (disabledFeatures.s3) { LOG_INFO('[LOCAL-CDN] s3 enabled, skipping local CDN'); } -export default router; \ No newline at end of file +export default router; diff --git a/src/services/local-cdn/routes/get.ts b/src/services/local-cdn/routes/get.ts index c98b586..af6e1e8 100644 --- a/src/services/local-cdn/routes/get.ts +++ b/src/services/local-cdn/routes/get.ts @@ -15,4 +15,4 @@ router.get('/*', async (request: express.Request, response: express.Response): P } }); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/nasc/index.ts b/src/services/nasc/index.ts index 50cb0c8..660005a 100644 --- a/src/services/nasc/index.ts +++ b/src/services/nasc/index.ts @@ -3,7 +3,6 @@ import express from 'express'; import NASCMiddleware from '@/middleware/nasc'; import { LOG_INFO, formatHostnames } from '@/logger'; - import ac from '@/services/nasc/routes/ac'; import { restrictHostnames } from '@/middleware/host-limit'; import { config } from '@/config-manager'; @@ -25,4 +24,4 @@ const router = express.Router(); LOG_INFO(`[NASC] Creating nasc router with domains: ${formatHostnames(config.domains.nasc)}`); router.use(restrictHostnames(config.domains.nasc, nasc)); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/nasc/routes/ac.ts b/src/services/nasc/routes/ac.ts index 1a8c616..4385d9d 100644 --- a/src/services/nasc/routes/ac.ts +++ b/src/services/nasc/routes/ac.ts @@ -1,8 +1,8 @@ import express from 'express'; import { nintendoBase64Encode, nintendoBase64Decode, nascDateTime, nascError, generateToken } from '@/util'; import { getServerByTitleID } from '@/database'; -import { NASCRequestParams } from '@/types/services/nasc/request-params'; -import { HydratedServerDocument } from '@/types/mongoose/server'; +import type { NASCRequestParams } from '@/types/services/nasc/request-params'; +import type { HydratedServerDocument } from '@/types/mongoose/server'; const router = express.Router(); @@ -83,7 +83,7 @@ async function processLoginRequest(server: HydratedServerDocument, pid: number, retry: nintendoBase64Encode('0'), returncd: nintendoBase64Encode('001'), token: nexToken, - datetime: nintendoBase64Encode(nascDateTime()), + datetime: nintendoBase64Encode(nascDateTime()) }); } @@ -108,8 +108,8 @@ async function processServiceTokenRequest(server: HydratedServerDocument, pid: n servicetoken: serviceToken, statusdata: nintendoBase64Encode('Y'), svchost: nintendoBase64Encode('n/a'), - datetime: nintendoBase64Encode(nascDateTime()), + datetime: nintendoBase64Encode(nascDateTime()) }); } -export default router; \ No newline at end of file +export default router; diff --git a/src/services/nnas/index.ts b/src/services/nnas/index.ts index 2cacf1c..c23b408 100644 --- a/src/services/nnas/index.ts +++ b/src/services/nnas/index.ts @@ -6,7 +6,6 @@ import clientHeaderCheck from '@/middleware/client-header'; import cemuMiddleware from '@/middleware/cemu'; import pnidMiddleware from '@/middleware/pnid'; import { LOG_INFO, formatHostnames } from '@/logger'; - import admin from '@/services/nnas/routes/admin'; import content from '@/services/nnas/routes/content'; import devices from '@/services/nnas/routes/devices'; @@ -66,4 +65,4 @@ const router = express.Router(); LOG_INFO(`[NNAS] Creating nnas router with domains: ${formatHostnames(config.domains.nnas)}`); router.use(restrictHostnames(config.domains.nnas, nnas)); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/nnas/routes/account-settings.ts b/src/services/nnas/routes/account-settings.ts index 9cd74f1..3d614d2 100644 --- a/src/services/nnas/routes/account-settings.ts +++ b/src/services/nnas/routes/account-settings.ts @@ -6,15 +6,15 @@ import { getServerByClientID, getPNIDByPID } from '@/database'; import { LOG_ERROR } from '@/logger'; import { decryptToken, unpackToken, getValueFromHeaders, sendConfirmationEmail } from '@/util'; import { config } from '@/config-manager'; -import { HydratedServerDocument } from '@/types/mongoose/server'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; -import { AccountSettings } from '@/types/services/nnas/account-settings'; -import { Token } from '@/types/common/token'; -import { RegionLanguages } from '@/types/services/nnas/region-languages'; -import { RegionTimezone, RegionTimezones } from '@/types/services/nnas/region-timezones'; -import { Country, Region } from '@/types/services/nnas/regions'; import timezones from '@/services/nnas/timezones.json'; import regionsList from '@/services/nnas/regions.json'; +import type { HydratedServerDocument } from '@/types/mongoose/server'; +import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; +import type { AccountSettings } from '@/types/services/nnas/account-settings'; +import type { Token } from '@/types/common/token'; +import type { RegionLanguages } from '@/types/services/nnas/region-languages'; +import type { RegionTimezone, RegionTimezones } from '@/types/services/nnas/region-timezones'; +import type { Country, Region } from '@/types/services/nnas/regions'; const router = express.Router(); @@ -26,8 +26,8 @@ const accountSettingsSchema = z.object({ country: z.string(), email: z.string().email(), server_selection: z.enum(['prod', 'test', 'dev']), - marketing_flag: z.enum(['true', 'false']).transform((value) => value === 'true'), - off_device_flag: z.enum(['true', 'false']).transform((value) => value === 'true'), + marketing_flag: z.enum(['true', 'false']).transform(value => value === 'true'), + off_device_flag: z.enum(['true', 'false']).transform(value => value === 'true') }); /** @@ -63,7 +63,7 @@ router.get('/ui/profile', async function (request: express.Request, response: ex const regionLanguages: RegionLanguages = timezones[countryCode as keyof typeof timezones]; const regionTimezones: RegionTimezones = regionLanguages[language] ? regionLanguages[language] : Object.values(regionLanguages)[0]; - const region: Country | undefined = regionsList.find((region) => region.iso_code === countryCode); + const region: Country | undefined = regionsList.find(region => region.iso_code === countryCode); const miiFaces = ['normal_face', 'smile_open_mouth', 'sorrow', 'surprise_open_mouth', 'wink_left', 'frustrated']; const face = miiFaces[crypto.randomInt(5)]; @@ -78,7 +78,7 @@ router.get('/ui/profile', async function (request: express.Request, response: ex face, notice, accountLevel, - regions: region ? region.regions: [], + regions: region ? region.regions : [], regionsList }); } catch (error: any) { @@ -154,7 +154,7 @@ router.post('/update', async function (request: express.Request, response: expre const regionLanguages: RegionLanguages = timezones[pnid.country as keyof typeof timezones]; const regionTimezones: RegionTimezones = regionLanguages[pnid.language] ? regionLanguages[pnid.language] : Object.values(regionLanguages)[0]; const timezone: RegionTimezone | undefined = regionTimezones.find(tz => tz.area === timezoneName); - const country: Country | undefined = regionsList.find((region) => region.iso_code === pnid.country); + const country: Country | undefined = regionsList.find(region => region.iso_code === pnid.country); let notice = ''; if (!country) { @@ -163,7 +163,7 @@ router.post('/update', async function (request: express.Request, response: expre return; } - const regionObject: Region | undefined = country.regions.find((region) => region.id === person.data.region); + const regionObject: Region | undefined = country.regions.find(region => region.id === person.data.region); const region = regionObject ? regionObject.id : pnid.region; if (!timezone) { diff --git a/src/services/nnas/routes/admin.ts b/src/services/nnas/routes/admin.ts index c08c356..06e423f 100644 --- a/src/services/nnas/routes/admin.ts +++ b/src/services/nnas/routes/admin.ts @@ -117,5 +117,4 @@ router.get('/time', async (request: express.Request, response: express.Response) response.send(''); }); - -export default router; \ No newline at end of file +export default router; diff --git a/src/services/nnas/routes/content.ts b/src/services/nnas/routes/content.ts index a60cc30..6312c35 100644 --- a/src/services/nnas/routes/content.ts +++ b/src/services/nnas/routes/content.ts @@ -26,29 +26,29 @@ router.get('/agreements/:type/:region/:version', (request: express.Request, resp '@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', '@xsi:type': 'chunkedStoredAgreementText', - main_title: { + 'main_title': { '#cdata': 'Pretendo Network Services Agreement' }, - agree_text: { + 'agree_text': { '#cdata': 'I Accept' }, - non_agree_text: { + 'non_agree_text': { '#cdata': 'I Decline' }, - main_text: { + 'main_text': { '@index': '1', '#cdata': 'Welcome to Pretendo\'s Christmas public beta! This is supplied with no liability or warranty, and is a stress test of our current services.This test is not expected to last long- term, and the data may be kept for later testing; this data will not be shared outside of Pretendo, and will be deleted at the end of our testing period.' }, - sub_title: { + 'sub_title': { '#cdata': 'Privacy Policy' }, - sub_text: { + 'sub_text': { '@index': '1', '#cdata': 'Welcome to Pretendo\'s Christmas public beta! This is supplied with no liability or warranty, and is a stress test of our current services.This test is not expected to last long- term, and the data may be kept for later testing; this data will not be shared outside of Pretendo, and will be deleted at the end of our testing period.' - }, + } }, type: 'NINTENDO-NETWORK-EULA', - version: '0300', + version: '0300' }, { country: 'US', @@ -59,29 +59,29 @@ router.get('/agreements/:type/:region/:version', (request: express.Request, resp '@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', '@xsi:type': 'chunkedStoredAgreementText', - main_title: { + 'main_title': { '#cdata': 'Pretendo Network Services Agreement' }, - agree_text: { + 'agree_text': { '#cdata': 'I Accept' }, - non_agree_text: { + 'non_agree_text': { '#cdata': 'I Decline' }, - main_text: { + 'main_text': { '@index': '1', '#cdata': 'Welcome to Pretendo\'s Christmas public beta! This is supplied with no liability or warranty, and is a stress test of our current services.This test is not expected to last long- term, and the data may be kept for later testing; this data will not be shared outside of Pretendo, and will be deleted at the end of our testing period.' }, - sub_title: { + 'sub_title': { '#cdata': 'Privacy Policy' }, - sub_text: { + 'sub_text': { '@index': '1', '#cdata': 'Welcome to Pretendo\'s Christmas public beta! This is supplied with no liability or warranty, and is a stress test of our current services.This test is not expected to last long- term, and the data may be kept for later testing; this data will not be shared outside of Pretendo, and will be deleted at the end of our testing period.' - }, + } }, type: 'NINTENDO-NETWORK-EULA', - version: '0300', + version: '0300' }, { country: 'US', @@ -92,29 +92,29 @@ router.get('/agreements/:type/:region/:version', (request: express.Request, resp '@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', '@xsi:type': 'chunkedStoredAgreementText', - main_title: { + 'main_title': { '#cdata': 'Pretendo Network Services Agreement' }, - agree_text: { + 'agree_text': { '#cdata': 'I Accept' }, - non_agree_text: { + 'non_agree_text': { '#cdata': 'I Decline' }, - main_text: { + 'main_text': { '@index': '1', '#cdata': 'Welcome to Pretendo\'s Christmas public beta! This is supplied with no liability or warranty, and is a stress test of our current services.This test is not expected to last long- term, and the data may be kept for later testing; this data will not be shared outside of Pretendo, and will be deleted at the end of our testing period.' }, - sub_title: { + 'sub_title': { '#cdata': 'Privacy Policy' }, - sub_text: { + 'sub_text': { '@index': '1', '#cdata': 'Welcome to Pretendo\'s Christmas public beta! This is supplied with no liability or warranty, and is a stress test of our current services.This test is not expected to last long- term, and the data may be kept for later testing; this data will not be shared outside of Pretendo, and will be deleted at the end of our testing period.' - }, + } }, type: 'NINTENDO-NETWORK-EULA', - version: '0300', + version: '0300' } ] } @@ -162,4 +162,4 @@ router.get('/time_zones/:countryCode/:language', (request: express.Request, resp }).end()); }); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/nnas/routes/devices.ts b/src/services/nnas/routes/devices.ts index f46e6a4..4e4ae64 100644 --- a/src/services/nnas/routes/devices.ts +++ b/src/services/nnas/routes/devices.ts @@ -15,4 +15,4 @@ router.get('/@current/status', async (request: express.Request, response: expres }).end()); }); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/nnas/routes/miis.ts b/src/services/nnas/routes/miis.ts index 85487bc..c128658 100644 --- a/src/services/nnas/routes/miis.ts +++ b/src/services/nnas/routes/miis.ts @@ -3,7 +3,7 @@ import xmlbuilder from 'xmlbuilder'; import { getValueFromQueryString } from '@/util'; import { PNID } from '@/models/pnid'; import { config } from '@/config-manager'; -import { YesNoBoolString } from '@/types/common/yes-no-bool-string'; +import type { YesNoBoolString } from '@/types/common/yes-no-bool-string'; const router = express.Router(); @@ -40,7 +40,7 @@ router.get('/', async (request: express.Request, response: express.Response): Pr id: number; url: string; type: string; - }[] + }[]; }; name: string; pid: number; @@ -127,4 +127,4 @@ router.get('/', async (request: express.Request, response: express.Response): Pr } }); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/nnas/routes/oauth.ts b/src/services/nnas/routes/oauth.ts index 493ed4e..c9a7518 100644 --- a/src/services/nnas/routes/oauth.ts +++ b/src/services/nnas/routes/oauth.ts @@ -101,7 +101,7 @@ router.post('/access_token/generate', deviceCertificateMiddleware, consoleStatus return; } - } catch (error) { + } catch { response.status(400).send(xmlbuilder.create({ error: { cause: 'refresh_token', @@ -186,4 +186,4 @@ router.post('/access_token/generate', deviceCertificateMiddleware, consoleStatus }).end()); }); -export default router; \ No newline at end of file +export default router; diff --git a/src/services/nnas/routes/people.ts b/src/services/nnas/routes/people.ts index 2172b53..e6858d4 100644 --- a/src/services/nnas/routes/people.ts +++ b/src/services/nnas/routes/people.ts @@ -11,10 +11,9 @@ 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 { Person } from '@/types/services/nnas/person'; +import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; +import type { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; +import type { Person } from '@/types/services/nnas/person'; const router = express.Router(); @@ -89,7 +88,7 @@ router.post('/', ratelimit, deviceCertificateMiddleware, async (request: express try { nexAccount = new NEXAccount({ - device_type: 'wiiu', + device_type: 'wiiu' }); await nexAccount.generatePID(); @@ -443,7 +442,6 @@ router.get('/@me/devices/status', async (_request: express.Request, response: ex }).end()); }); - /** * [PUT] * Replacement for: https://account.nintendo.net/v1/api/people/@me/miis/@primary @@ -657,7 +655,7 @@ router.get('/@me/emails', async (request: express.Request, response: express.Res 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, + validated_date: pnid.email.validated_date } } ] diff --git a/src/services/nnas/routes/provider.ts b/src/services/nnas/routes/provider.ts index 1f87e8d..72f8f1f 100644 --- a/src/services/nnas/routes/provider.ts +++ b/src/services/nnas/routes/provider.ts @@ -239,4 +239,4 @@ router.get('/nex_token/@me', async (request: express.Request, response: express. }).end()); }); -export default router; \ No newline at end of file +export default router; diff --git a/src/types/common/config.ts b/src/types/common/config.ts index cc6390f..b8bd19e 100644 --- a/src/types/common/config.ts +++ b/src/types/common/config.ts @@ -1,4 +1,4 @@ -import mongoose from 'mongoose'; +import type mongoose from 'mongoose'; export const domainServices = ['api', 'assets', 'cbvc', 'conntest', 'datastore', 'nasc', 'nnas', 'local_cdn'] as const; export type DomainService = typeof domainServices[number]; @@ -16,7 +16,7 @@ export interface Config { redis: { client: { url: string; - } + }; }; email: { ses: { @@ -38,7 +38,7 @@ export interface Config { secret: string; }; cdn: { - /** + /** * @deprecated Use `domains.cdn` instead */ subdomain?: string; diff --git a/src/types/common/gender-types.ts b/src/types/common/gender-types.ts index 9d4ca82..0cd06a8 100644 --- a/src/types/common/gender-types.ts +++ b/src/types/common/gender-types.ts @@ -1 +1 @@ -export type GenderTypes = 'M' | 'F'; \ No newline at end of file +export type GenderTypes = 'M' | 'F'; diff --git a/src/types/common/mailer-options.ts b/src/types/common/mailer-options.ts index 265b42a..d3999f7 100644 --- a/src/types/common/mailer-options.ts +++ b/src/types/common/mailer-options.ts @@ -13,4 +13,4 @@ export interface MailerOptions { href: string; code: string; }; -} \ No newline at end of file +} diff --git a/src/types/common/permission-flags.ts b/src/types/common/permission-flags.ts index 7c22211..eb97d9f 100644 --- a/src/types/common/permission-flags.ts +++ b/src/types/common/permission-flags.ts @@ -1,26 +1,26 @@ export const PNID_PERMISSION_FLAGS = { - BANNED_ALL_PERMANENTLY: 1n << 0n, - BANNED_ALL_TEMPORARILY: 1n << 1n, - BETA_ACCESS: 1n << 2n, - ACCESS_ADMIN_PANEL: 1n << 3n, - CREATE_SERVER_CONFIGS: 1n << 4n, - MODIFY_SERVER_CONFIGS: 1n << 5n, - DEPLOY_SERVER: 1n << 6n, - MODIFY_PNIDS: 1n << 7n, - MODIFY_NEX_ACCOUNTS: 1n << 8n, - MODIFY_CONSOLES: 1n << 9n, - BAN_PNIDS: 1n << 10n, - BAN_NEX_ACCOUNTS: 1n << 11n, - BAN_CONSOLES: 1n << 12n, - MODERATE_MIIVERSE: 1n << 13n, - CREATE_API_KEYS: 1n << 14n, // * This applies to all services - CREATE_BOSS_TASKS: 1n << 15n, - UPDATE_BOSS_TASKS: 1n << 16n, - DELETE_BOSS_TASKS: 1n << 17n, - UPLOAD_BOSS_FILES: 1n << 18n, - UPDATE_BOSS_FILES: 1n << 18n, - DELETE_BOSS_FILES: 1n << 19n, + BANNED_ALL_PERMANENTLY: 1n << 0n, + BANNED_ALL_TEMPORARILY: 1n << 1n, + BETA_ACCESS: 1n << 2n, + ACCESS_ADMIN_PANEL: 1n << 3n, + CREATE_SERVER_CONFIGS: 1n << 4n, + MODIFY_SERVER_CONFIGS: 1n << 5n, + DEPLOY_SERVER: 1n << 6n, + MODIFY_PNIDS: 1n << 7n, + MODIFY_NEX_ACCOUNTS: 1n << 8n, + MODIFY_CONSOLES: 1n << 9n, + BAN_PNIDS: 1n << 10n, + BAN_NEX_ACCOUNTS: 1n << 11n, + BAN_CONSOLES: 1n << 12n, + MODERATE_MIIVERSE: 1n << 13n, + CREATE_API_KEYS: 1n << 14n, // * This applies to all services + CREATE_BOSS_TASKS: 1n << 15n, + UPDATE_BOSS_TASKS: 1n << 16n, + DELETE_BOSS_TASKS: 1n << 17n, + UPLOAD_BOSS_FILES: 1n << 18n, + UPDATE_BOSS_FILES: 1n << 18n, + DELETE_BOSS_FILES: 1n << 19n, UPDATE_PNID_PERMISSIONS: 1n << 20n } as const; -export type PNIDPermissionFlag = (typeof PNID_PERMISSION_FLAGS)[keyof typeof PNID_PERMISSION_FLAGS]; \ No newline at end of file +export type PNIDPermissionFlag = (typeof PNID_PERMISSION_FLAGS)[keyof typeof PNID_PERMISSION_FLAGS]; diff --git a/src/types/common/safe-qs.ts b/src/types/common/safe-qs.ts index a17df29..ff46ad2 100644 --- a/src/types/common/safe-qs.ts +++ b/src/types/common/safe-qs.ts @@ -1,3 +1,3 @@ export interface SafeQs { - [key: string]: string | undefined -} \ No newline at end of file + [key: string]: string | undefined; +} diff --git a/src/types/common/signature-size.ts b/src/types/common/signature-size.ts index c9f9bbf..19a3a83 100644 --- a/src/types/common/signature-size.ts +++ b/src/types/common/signature-size.ts @@ -1,4 +1,4 @@ export interface SignatureSize { SIZE: number; PADDING_SIZE: number; -} \ No newline at end of file +} diff --git a/src/types/common/token-options.ts b/src/types/common/token-options.ts index 6dcc85e..114a669 100644 --- a/src/types/common/token-options.ts +++ b/src/types/common/token-options.ts @@ -5,4 +5,4 @@ export interface TokenOptions { access_level?: number; title_id?: bigint; expire_time: bigint; -} \ No newline at end of file +} diff --git a/src/types/common/token.ts b/src/types/common/token.ts index 4c7c558..daf0eef 100644 --- a/src/types/common/token.ts +++ b/src/types/common/token.ts @@ -5,4 +5,4 @@ export interface Token { access_level?: number; title_id?: bigint; expire_time: bigint; -} \ No newline at end of file +} diff --git a/src/types/common/yes-no-bool-string.ts b/src/types/common/yes-no-bool-string.ts index 474aa6e..0088e31 100644 --- a/src/types/common/yes-no-bool-string.ts +++ b/src/types/common/yes-no-bool-string.ts @@ -1 +1 @@ -export type YesNoBoolString = 'Y' | 'N'; \ No newline at end of file +export type YesNoBoolString = 'Y' | 'N'; diff --git a/src/types/express.d.ts b/src/types/express.d.ts index d6980f3..3b03cf3 100644 --- a/src/types/express.d.ts +++ b/src/types/express.d.ts @@ -1,7 +1,7 @@ -import NintendoCertificate from '@/nintendo-certificate'; -import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; -import { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; -import { HydratedDeviceDocument } from '@/types/mongoose/device'; +import type NintendoCertificate from '@/nintendo-certificate'; +import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; +import type { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; +import type { HydratedDeviceDocument } from '@/types/mongoose/device'; declare global { namespace Express { @@ -14,4 +14,4 @@ declare global { device?: HydratedDeviceDocument; } } -} \ No newline at end of file +} diff --git a/src/types/image-pixels.d.ts b/src/types/image-pixels.d.ts index a738a3f..7676405 100644 --- a/src/types/image-pixels.d.ts +++ b/src/types/image-pixels.d.ts @@ -1,5 +1,5 @@ declare module 'image-pixels' { - import { NdArray } from 'ndarray'; + import type { NdArray } from 'ndarray'; export interface ImagePixelsOptions { source: ImageSource; @@ -29,4 +29,4 @@ declare module 'image-pixels' { export default function pixels( src: ImageSource | Promise ): ImageData; -} \ No newline at end of file +} diff --git a/src/types/mii-js.d.ts b/src/types/mii-js.d.ts index 55cc57f..65ffca6 100644 --- a/src/types/mii-js.d.ts +++ b/src/types/mii-js.d.ts @@ -97,4 +97,4 @@ type Mii = { studioUrl: (options: MiiStudioURLOptions) => string; encode: () => Buffer; validate: () => void; -}; \ No newline at end of file +}; diff --git a/src/types/mongoose-unique-validator.d.ts b/src/types/mongoose-unique-validator.d.ts index 0909028..f5b788f 100644 --- a/src/types/mongoose-unique-validator.d.ts +++ b/src/types/mongoose-unique-validator.d.ts @@ -1 +1 @@ -declare module 'mongoose-unique-validator'; \ No newline at end of file +declare module 'mongoose-unique-validator'; diff --git a/src/types/mongoose/device-attribute.ts b/src/types/mongoose/device-attribute.ts index e9eb87f..19301b6 100644 --- a/src/types/mongoose/device-attribute.ts +++ b/src/types/mongoose/device-attribute.ts @@ -1,4 +1,4 @@ -import { Model } from 'mongoose'; +import type { Model } from 'mongoose'; export interface IDeviceAttribute { created_date?: string; @@ -10,4 +10,4 @@ export interface IDeviceAttributeMethods {} interface IDeviceAttributeQueryHelpers {} -export interface DeviceAttributeModel extends Model {} \ No newline at end of file +export interface DeviceAttributeModel extends Model {} diff --git a/src/types/mongoose/device.ts b/src/types/mongoose/device.ts index dfc9d89..fd929e1 100644 --- a/src/types/mongoose/device.ts +++ b/src/types/mongoose/device.ts @@ -1,5 +1,5 @@ -import { Model, Types, HydratedDocument } from 'mongoose'; -import { IDeviceAttribute } from '@/types/mongoose/device-attribute'; +import type { Model, Types, HydratedDocument } from 'mongoose'; +import type { IDeviceAttribute } from '@/types/mongoose/device-attribute'; type MODEL = 'wup' | 'ctr' | 'spr' | 'ftr' | 'ktr' | 'red' | 'jan'; type ACCESS_LEVEL = -1 | 0 | 1 | 2 | 3; @@ -16,7 +16,7 @@ export interface IDevice { account_id: number; }; environment: string; - mac_hash: string; // * 3DS-specific + mac_hash: string; // * 3DS-specific fcdcert_hash: string; // * 3DS-specific linked_pids: number[]; access_level: ACCESS_LEVEL; @@ -30,4 +30,4 @@ interface IDeviceQueryHelpers {} export interface DeviceModel extends Model {} -export type HydratedDeviceDocument = HydratedDocument \ No newline at end of file +export type HydratedDeviceDocument = HydratedDocument; diff --git a/src/types/mongoose/nex-account.ts b/src/types/mongoose/nex-account.ts index e7fc997..f6596be 100644 --- a/src/types/mongoose/nex-account.ts +++ b/src/types/mongoose/nex-account.ts @@ -1,4 +1,4 @@ -import { Model, HydratedDocument } from 'mongoose'; +import type { Model, HydratedDocument } from 'mongoose'; type DEVICE = 'wiiu' | '3ds'; enum ACCESS_LEVEL { @@ -27,4 +27,4 @@ interface INEXAccountQueryHelpers {} export interface NEXAccountModel extends Model {} -export type HydratedNEXAccountDocument = HydratedDocument \ No newline at end of file +export type HydratedNEXAccountDocument = HydratedDocument; diff --git a/src/types/mongoose/pnid.ts b/src/types/mongoose/pnid.ts index 3252c44..440e23b 100644 --- a/src/types/mongoose/pnid.ts +++ b/src/types/mongoose/pnid.ts @@ -1,6 +1,6 @@ -import { Model, Types, HydratedDocument } from 'mongoose'; -import { IDevice } from '@/types/mongoose/device'; -import { PNIDPermissionFlag } from '@/types/common/permission-flags'; +import type { Model, Types, HydratedDocument } from 'mongoose'; +import type { IDevice } from '@/types/mongoose/device'; +import type { PNIDPermissionFlag } from '@/types/common/permission-flags'; export interface IPNID { deleted: boolean; @@ -58,7 +58,7 @@ export interface IPNID { refresh_token: { value: string; ttl: number; - } + }; }; connections: { discord: { @@ -79,7 +79,7 @@ export interface IPNIDMethods { generatePID(): Promise; generateEmailValidationCode(): Promise; generateEmailValidationToken(): Promise; - updateMii(mii: { name: string, primary: string, data: string}): Promise; + updateMii(mii: { name: string; primary: string; data: string }): Promise; generateMiiImages(): Promise; scrub(): Promise; hasPermission(flag: PNIDPermissionFlag): boolean; @@ -91,4 +91,4 @@ interface IPNIDQueryHelpers {} export interface PNIDModel extends Model {} -export type HydratedPNIDDocument = HydratedDocument \ No newline at end of file +export type HydratedPNIDDocument = HydratedDocument; diff --git a/src/types/mongoose/server.ts b/src/types/mongoose/server.ts index a7c8f6e..7984918 100644 --- a/src/types/mongoose/server.ts +++ b/src/types/mongoose/server.ts @@ -1,4 +1,4 @@ -import { Model, HydratedDocument } from 'mongoose'; +import type { Model, HydratedDocument } from 'mongoose'; export interface IServer { client_id: string; @@ -20,4 +20,4 @@ interface IServerQueryHelpers {} export interface ServerModel extends Model {} -export type HydratedServerDocument = HydratedDocument \ No newline at end of file +export type HydratedServerDocument = HydratedDocument; diff --git a/src/types/services/api/connection-data.ts b/src/types/services/api/connection-data.ts index 54fe992..67d47ce 100644 --- a/src/types/services/api/connection-data.ts +++ b/src/types/services/api/connection-data.ts @@ -1,4 +1,4 @@ -import { DiscordConnectionData } from '@/types/services/api/discord-connection-data'; +import type { DiscordConnectionData } from '@/types/services/api/discord-connection-data'; // TODO - This will be a union of all ConnectionData types when more connections are added -export type ConnectionData = DiscordConnectionData; \ No newline at end of file +export type ConnectionData = DiscordConnectionData; diff --git a/src/types/services/api/connection-response.ts b/src/types/services/api/connection-response.ts index 6baa9b0..80e2cab 100644 --- a/src/types/services/api/connection-response.ts +++ b/src/types/services/api/connection-response.ts @@ -2,4 +2,4 @@ export interface ConnectionResponse { app: string; status: number; error?: string; -} \ No newline at end of file +} diff --git a/src/types/services/api/discord-connection-data.ts b/src/types/services/api/discord-connection-data.ts index 0ee459a..8d08c84 100644 --- a/src/types/services/api/discord-connection-data.ts +++ b/src/types/services/api/discord-connection-data.ts @@ -1,3 +1,3 @@ export interface DiscordConnectionData { id: string; -} \ No newline at end of file +} diff --git a/src/types/services/api/update-user-request.ts b/src/types/services/api/update-user-request.ts index a525e98..cd095fd 100644 --- a/src/types/services/api/update-user-request.ts +++ b/src/types/services/api/update-user-request.ts @@ -3,5 +3,5 @@ export interface UpdateUserRequest { name: string; primary: string; data: string; - } -} \ No newline at end of file + }; +} diff --git a/src/types/services/nasc/request-params.ts b/src/types/services/nasc/request-params.ts index aafcda6..76bfd11 100644 --- a/src/types/services/nasc/request-params.ts +++ b/src/types/services/nasc/request-params.ts @@ -8,4 +8,4 @@ export interface NASCRequestParams { userid?: string; uidhmac?: string; passwd?: string; -} \ No newline at end of file +} diff --git a/src/types/services/nnas/account-settings.ts b/src/types/services/nnas/account-settings.ts index 5cef6aa..d2a14ec 100644 --- a/src/types/services/nnas/account-settings.ts +++ b/src/types/services/nnas/account-settings.ts @@ -1,4 +1,4 @@ -import { GenderTypes } from '@/types/common/gender-types'; +import type { GenderTypes } from '@/types/common/gender-types'; export interface AccountSettings { birthdate: string; @@ -9,4 +9,4 @@ export interface AccountSettings { server_selection: string; marketing_flag: boolean; off_device_flag: boolean; -} \ No newline at end of file +} diff --git a/src/types/services/nnas/person.ts b/src/types/services/nnas/person.ts index 00958e5..457dbf2 100644 --- a/src/types/services/nnas/person.ts +++ b/src/types/services/nnas/person.ts @@ -1,5 +1,5 @@ -import { YesNoBoolString } from '@/types/common/yes-no-bool-string'; -import { IDeviceAttribute } from '@/types/mongoose/device-attribute'; +import type { YesNoBoolString } from '@/types/common/yes-no-bool-string'; +import type { IDeviceAttribute } from '@/types/mongoose/device-attribute'; // TODO - Change this Map type to something more strongly typed export interface Person { @@ -38,7 +38,7 @@ export interface Person { region: number; marketing_flag: YesNoBoolString; device_attributes: { - device_attribute: IDeviceAttribute[] + device_attribute: IDeviceAttribute[]; }; off_device_flag: YesNoBoolString; -} \ No newline at end of file +} diff --git a/src/types/services/nnas/pnid-profile.ts b/src/types/services/nnas/pnid-profile.ts index 70adea5..25bd19c 100644 --- a/src/types/services/nnas/pnid-profile.ts +++ b/src/types/services/nnas/pnid-profile.ts @@ -1,4 +1,4 @@ -import { YesNoBoolString } from '@/types/common/yes-no-bool-string'; +import type { 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 @@ -41,7 +41,7 @@ export interface PNIDProfile { id: number; url: string; type: 'standard'; - } + }; }; name: string; primary: YesNoBoolString; @@ -50,4 +50,4 @@ export interface PNIDProfile { tz_name: string; user_id: string; utc_offset: number; -} \ No newline at end of file +} diff --git a/src/types/services/nnas/region-languages.ts b/src/types/services/nnas/region-languages.ts index fd4bbf9..8213e13 100644 --- a/src/types/services/nnas/region-languages.ts +++ b/src/types/services/nnas/region-languages.ts @@ -1,5 +1,5 @@ -import { RegionTimezones } from '@/types/services/nnas/region-timezones'; +import type { RegionTimezones } from '@/types/services/nnas/region-timezones'; export interface RegionLanguages { - [myKey: string]: RegionTimezones -} \ No newline at end of file + [myKey: string]: RegionTimezones; +} diff --git a/src/types/services/nnas/region-timezones.ts b/src/types/services/nnas/region-timezones.ts index c904aaa..33e5ca6 100644 --- a/src/types/services/nnas/region-timezones.ts +++ b/src/types/services/nnas/region-timezones.ts @@ -6,4 +6,4 @@ export interface RegionTimezone { order: string; } -export type RegionTimezones = RegionTimezone[]; \ No newline at end of file +export type RegionTimezones = RegionTimezone[]; diff --git a/src/types/tga.d.ts b/src/types/tga.d.ts index 16eb4a2..365a31e 100644 --- a/src/types/tga.d.ts +++ b/src/types/tga.d.ts @@ -55,4 +55,4 @@ declare module 'tga' { public pixels: Uint8Array; } -} \ No newline at end of file +} diff --git a/src/util.ts b/src/util.ts index 0361952..339d484 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,19 +1,20 @@ import crypto from 'node:crypto'; import path from 'node:path'; -import { IncomingHttpHeaders } from 'node:http'; -import { ObjectCannedACL, S3 } from '@aws-sdk/client-s3'; +import { S3 } from '@aws-sdk/client-s3'; import fs from 'fs-extra'; -import express from 'express'; -import mongoose from 'mongoose'; -import { ParsedQs } from 'qs'; -import crc32 from 'buffer-crc32'; -import crc from 'crc'; +import bufferCrc32 from 'buffer-crc32'; +import { crc32 } from 'crc'; import { sendMail } from '@/mailer'; 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 { SafeQs } from '@/types/common/safe-qs'; +import type { ParsedQs } from 'qs'; +import type mongoose from 'mongoose'; +import type express from 'express'; +import type { ObjectCannedACL } from '@aws-sdk/client-s3'; +import type { IncomingHttpHeaders } from 'node:http'; +import type { TokenOptions } from '@/types/common/token-options'; +import type { Token } from '@/types/common/token'; +import type { IPNID, IPNIDMethods } from '@/types/mongoose/pnid'; +import type { SafeQs } from '@/types/common/safe-qs'; let s3: S3; @@ -25,8 +26,8 @@ if (!disabledFeatures.s3) { credentials: { accessKeyId: config.s3.key, - secretAccessKey: config.s3.secret, - }, + secretAccessKey: config.s3.secret + } }); } @@ -89,7 +90,7 @@ export function generateToken(key: string, options: TokenOptions): Buffer | null 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 = crc32(dataBuffer); + const checksum = bufferCrc32(dataBuffer); final = Buffer.concat([ checksum, @@ -124,7 +125,7 @@ export function decryptToken(token: Buffer, key?: string): Buffer { decipher.final() ]); - if (expectedChecksum && (expectedChecksum !== crc.crc32(decrypted))) { + if (expectedChecksum && (expectedChecksum !== crc32(decrypted))) { throw new Error('Checksum did not match. Failed decrypt. Are you using the right key?'); } @@ -193,7 +194,7 @@ export function nascError(errorCode: string): URLSearchParams { return new URLSearchParams({ retry: nintendoBase64Encode('1'), returncd: errorCode == 'null' ? errorCode : nintendoBase64Encode(errorCode), - datetime: nintendoBase64Encode(nascDateTime()), + datetime: nintendoBase64Encode(nascDateTime()) }); } @@ -212,7 +213,7 @@ export async function sendConfirmationEmail(pnid: mongoose.HydratedDocument): Promise { +export async function sendEmailConfirmedEmail(pnid: mongoose.HydratedDocument): Promise { const options = { to: pnid.email.address, subject: '[Pretendo Network] Email address confirmed', @@ -224,7 +225,7 @@ export async function sendEmailConfirmedEmail(pnid: mongoose.HydratedDocument): Promise { +export async function sendEmailConfirmedParentalControlsEmail(pnid: mongoose.HydratedDocument): Promise { const options = { to: pnid.email.address, subject: '[Pretendo Network] Email address confirmed for Parental Controls', @@ -333,5 +334,5 @@ export function getValueFromHeaders(headers: IncomingHttpHeaders, key: string): } export function mapToObject(map: Map): object { - return Object.fromEntries(Array.from(map.entries(), ([ k, v ]) => v instanceof Map ? [ k, mapToObject(v) ] : [ k, v ])); -} \ No newline at end of file + return Object.fromEntries(Array.from(map.entries(), ([k, v]) => v instanceof Map ? [k, mapToObject(v)] : [k, v])); +}