From 8b5ca84ac8aeefeff52022a3b0d472a6e77cc3e1 Mon Sep 17 00:00:00 2001 From: Kevin Date: Fri, 14 Jun 2024 20:39:30 +1000 Subject: [PATCH 01/43] Added env to settingsSingleton --- src/settings.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/settings.ts b/src/settings.ts index 0617c4d45..bd6681be1 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -2,12 +2,21 @@ class Settings { private disableRegistration = false; + private readonly env: string; - getDisableRegistration(): boolean { + constructor() { + this.env = process.env.ENV; + } + + public getEnv() { + return this.env; + } + + public getDisableRegistration(): boolean { return this.disableRegistration; } - toggleDisableRegistration() { + public toggleDisableRegistration() { this.disableRegistration = !this.disableRegistration; } } From a8956b0db3a704f4ecf75894a1293879be589fa9 Mon Sep 17 00:00:00 2001 From: Kevin Date: Fri, 14 Jun 2024 20:45:27 +1000 Subject: [PATCH 02/43] Updated settingsSingleton to be a named export rather than default --- src/routes/index.js | 4 ++-- src/settings.ts | 4 +--- src/sockets/commands/mod/mtempenableregistration.ts | 10 +++++----- src/sockets/commands/mod/mtoggleregistration.ts | 6 +++--- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/routes/index.js b/src/routes/index.js index efd121793..f54cd2108 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -12,7 +12,7 @@ import { emailExists, validEmail } from '../routes/emailVerification'; import { sendEmailVerification } from '../myFunctions/sendEmailVerification'; import { disallowVPNs } from '../util/vpnDetection'; -import Settings from '../settings'; +import { settingsSingleton } from '../settings'; import { Alliance } from '../gameplay/types'; import { resRoles, rolesToAlliances, spyRoles } from '../gameplay/roles/roles'; import { sendResetPassword } from '../myFunctions/sendResetPassword'; @@ -963,7 +963,7 @@ function sanitiseEmail(req, res, next) { } function disableRegistrationMiddleware(req, res, next) { - if (Settings.getDisableRegistration()) { + if (settingsSingleton.getDisableRegistration()) { req.flash( 'error', 'Registration is temporarily disabled. Please contact a moderator via discord if you would like to create an account.', diff --git a/src/settings.ts b/src/settings.ts index bd6681be1..3e4fb67b3 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -21,6 +21,4 @@ class Settings { } } -const settingsSingleton = new Settings(); - -export default settingsSingleton; +export const settingsSingleton = new Settings(); diff --git a/src/sockets/commands/mod/mtempenableregistration.ts b/src/sockets/commands/mod/mtempenableregistration.ts index 5d37c4002..3ccf76a5a 100644 --- a/src/sockets/commands/mod/mtempenableregistration.ts +++ b/src/sockets/commands/mod/mtempenableregistration.ts @@ -1,11 +1,11 @@ import { Command } from '../types'; -import Settings from '../../../settings'; +import { settingsSingleton } from '../../../settings'; export const mtempenableregistration: Command = { command: 'mtempenableregistration', help: '/mtempenableregistration: Temporarily enables site registration for 5 minutes.', run: async (args, senderSocket) => { - const registrationStatus = Settings.getDisableRegistration(); + const registrationStatus = settingsSingleton.getDisableRegistration(); if (registrationStatus) { senderSocket.emit('messageCommandReturnStr', { @@ -17,7 +17,7 @@ export const mtempenableregistration: Command = { } // Enable registration - Settings.toggleDisableRegistration(); + settingsSingleton.toggleDisableRegistration(); senderSocket.emit('messageCommandReturnStr', { message: `Site registration was temporarily enabled for 5 minutes.`, @@ -27,10 +27,10 @@ export const mtempenableregistration: Command = { // Now disable registration after delay setTimeout(async () => { // Re-pull status in case it was already disabled separately. - const registrationStatus = Settings.getDisableRegistration(); + const registrationStatus = settingsSingleton.getDisableRegistration(); if (registrationStatus) { - Settings.toggleDisableRegistration(); + settingsSingleton.toggleDisableRegistration(); } }, 1000 * 60 * 5 /* 5 minutes */); }, diff --git a/src/sockets/commands/mod/mtoggleregistration.ts b/src/sockets/commands/mod/mtoggleregistration.ts index 6cb343565..2aa93de44 100644 --- a/src/sockets/commands/mod/mtoggleregistration.ts +++ b/src/sockets/commands/mod/mtoggleregistration.ts @@ -1,13 +1,13 @@ import { Command } from '../types'; -import Settings from '../../../settings'; +import { settingsSingleton } from '../../../settings'; export const mtoggleregistration: Command = { command: 'mtoggleregistration', help: '/mtoggleregistration: Toggles site registration.', run: async (args, senderSocket) => { - Settings.toggleDisableRegistration(); + settingsSingleton.toggleDisableRegistration(); - const descriptor = Settings.getDisableRegistration() + const descriptor = settingsSingleton.getDisableRegistration() ? 'disabled' : 'enabled'; From fe5b394489cb5331593800fde374d1c218901217 Mon Sep 17 00:00:00 2001 From: Kevin Date: Fri, 14 Jun 2024 20:55:47 +1000 Subject: [PATCH 03/43] Using config.ts instead of settings.ts for env variables --- src/config.ts | 57 ++++++++++++++++++++++++++++++++----------------- src/settings.ts | 9 -------- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/config.ts b/src/config.ts index 2c47f585c..7d8cd4140 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,22 +1,41 @@ -const VALID_ENVIRONMENTS = ['local', 'staging', 'prod']; -if (!VALID_ENVIRONMENTS.includes(process.env.ENV)) { - throw new Error(`Invalid settings: ENV=${process.env.ENV}`); -} +const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); -if ( - process.env.ENV === 'staging' && - process.env.S3_BUCKET_NAME !== 'proavalon-staging' -) { - throw new Error( - `Invalid settings: ENV=staging S3_BUCKET_NAME=${process.env.S3_BUCKET_NAME}`, - ); -} +// TODO-kev: Should i import this into app.ts? +class Config { + private readonly env: string; + + constructor() { + if (!VALID_ENVIRONMENTS.has(process.env.ENV)) { + // TODO-kev: Prefer the console.error then process exit or throw an error? + console.error(`Bad environment variable given: ${process.env.ENV}`); + throw new Error(`Invalid settings: ENV=${process.env.ENV}`); + process.exit(1); + } + + if ( + process.env.ENV === 'staging' && + process.env.S3_BUCKET_NAME !== 'proavalon-staging' + ) { + throw new Error( + `Invalid settings: ENV=staging S3_BUCKET_NAME=${process.env.S3_BUCKET_NAME}`, + ); + } -if ( - process.env.ENV === 'prod' && - process.env.S3_BUCKET_NAME !== 'proavalon' -) { - throw new Error( - `Invalid settings: ENV=prod S3_BUCKET_NAME=${process.env.S3_BUCKET_NAME}`, - ); + if ( + process.env.ENV === 'prod' && + process.env.S3_BUCKET_NAME !== 'proavalon' + ) { + throw new Error( + `Invalid settings: ENV=prod S3_BUCKET_NAME=${process.env.S3_BUCKET_NAME}`, + ); + } + + this.env = process.env.ENV; + } + + public getEnv() { + return this.env; + } } + +export const config = new Config(); diff --git a/src/settings.ts b/src/settings.ts index 3e4fb67b3..a171518e7 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -2,15 +2,6 @@ class Settings { private disableRegistration = false; - private readonly env: string; - - constructor() { - this.env = process.env.ENV; - } - - public getEnv() { - return this.env; - } public getDisableRegistration(): boolean { return this.disableRegistration; From 46bd5075badd0303577b6bb8f3dc41159ab5150d Mon Sep 17 00:00:00 2001 From: Kevin Date: Fri, 14 Jun 2024 20:58:25 +1000 Subject: [PATCH 04/43] replaced process.env.ENV mentions in app.ts --- src/app.ts | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/app.ts b/src/app.ts index d3946bbd8..d5cfb925b 100644 --- a/src/app.ts +++ b/src/app.ts @@ -20,6 +20,7 @@ import socket, { Server as SocketServer } from 'socket.io'; import createProxyMiddleware from 'http-proxy-middleware'; import morgan from 'morgan'; +import { config } from './config'; import { server as socketServer } from './sockets/sockets'; import User from './models/user'; import { emailVerified, isLoggedIn } from './routes/middleware'; @@ -38,16 +39,6 @@ import { SESSIONS_COLLECTION_NAME } from './constants'; const assetsPath = path.join(__dirname, '../assets'); -// Die if env var isn't given in -if ( - process.env.ENV !== 'local' && - process.env.ENV !== 'staging' && - process.env.ENV !== 'prod' -) { - console.error('Bad environment variable given.'); - process.exit(1); -} - const app = express(); app.use(compression()); app.use(express.static(assetsPath, { maxAge: 518400000 })); // expires in 7 days. @@ -84,7 +75,7 @@ app.use( ), ); -if (process.env.ENV === 'local') { +if (config.getEnv() === 'local') { console.log('Routing dist_webpack to localhost:3010.'); app.use( '/dist_webpack', From 58c6e1db7155f90d62a61f1a6b5cc111e7a39649 Mon Sep 17 00:00:00 2001 From: Kevin Date: Fri, 14 Jun 2024 21:54:33 +1000 Subject: [PATCH 05/43] Added process.env as part of config --- src/clients/discord/index.ts | 5 +++-- src/routes/forum/forumThreadCommentReplyRoutes.js | 4 +++- src/routes/forum/forumThreadCommentRoutes.js | 3 ++- src/routes/forum/forumThreadRoutes.js | 4 +++- src/routes/index.js | 12 +++++++----- src/routes/middleware.ts | 3 ++- src/sockets/commands/admin/acreatetestaccounts.ts | 3 ++- src/sockets/sockets.ts | 3 ++- src/util/captcha.ts | 3 ++- src/util/vpnDetection.ts | 3 ++- 10 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/clients/discord/index.ts b/src/clients/discord/index.ts index 3a86f4a2a..5e9f0d736 100644 --- a/src/clients/discord/index.ts +++ b/src/clients/discord/index.ts @@ -1,8 +1,9 @@ import Discord, { TextChannel } from 'discord.js'; +import { config } from '../../config'; const client = new Discord.Client(); -if (process.env.ENV === 'prod') { +if (config.getEnv() === 'prod') { client.login(process.env.discord_bot_token); } @@ -23,7 +24,7 @@ export function sendToDiscordMods(message: string, ping?: boolean): void { function sendToChannel(message: string, channelId: string): void { const channel = client.channels.cache.get(channelId) as TextChannel; - if (process.env.ENV === 'prod') { + if (config.getEnv() === 'prod') { channel.send(message); } } diff --git a/src/routes/forum/forumThreadCommentReplyRoutes.js b/src/routes/forum/forumThreadCommentReplyRoutes.js index 9166c329a..593f8722d 100644 --- a/src/routes/forum/forumThreadCommentReplyRoutes.js +++ b/src/routes/forum/forumThreadCommentReplyRoutes.js @@ -2,6 +2,8 @@ import { Router } from 'express'; import sanitizeHtml from 'sanitize-html'; import mongoose from 'mongoose'; import rateLimit from 'express-rate-limit'; + +import { config } from '../../config'; import forumThread from '../../models/forumThread'; import forumThreadComment from '../../models/forumThreadComment'; import forumThreadCommentReply from '../../models/forumThreadCommentReply'; @@ -38,7 +40,7 @@ const sanitizeHtmlAllowedAttributesForumThread = { }; const newReplyLimiter = - process.env.ENV === 'local' + config.getEnv() === 'local' ? rateLimit({ max: 0, // Disable if we are local }) diff --git a/src/routes/forum/forumThreadCommentRoutes.js b/src/routes/forum/forumThreadCommentRoutes.js index 2b7420c24..b5f41b300 100644 --- a/src/routes/forum/forumThreadCommentRoutes.js +++ b/src/routes/forum/forumThreadCommentRoutes.js @@ -12,11 +12,12 @@ import { allowedHtmlAttributes, allowedHtmlTags } from './sanitizeRestrictions'; import { createNotification } from '../../myFunctions/createNotification'; import REWARDS from '../../rewards/constants'; import { userHasReward } from '../../rewards/getRewards'; +import { config } from '../../config'; const router = new Router(); const newCommentLimiter = - process.env.ENV === 'local' + config.getEnv() === 'local' ? rateLimit({ max: 0, // Disable if we are local }) diff --git a/src/routes/forum/forumThreadRoutes.js b/src/routes/forum/forumThreadRoutes.js index 3ff553618..8c7e99b16 100644 --- a/src/routes/forum/forumThreadRoutes.js +++ b/src/routes/forum/forumThreadRoutes.js @@ -1,6 +1,8 @@ import { Router } from 'express'; import sanitizeHtml from 'sanitize-html'; import rateLimit from 'express-rate-limit'; + +import { config } from '../../config'; import { checkForumThreadOwnership, asyncMiddleware } from '../middleware'; import getTimeDiffInString from '../../util/getTimeDiffInString'; import lastIds from '../../models/lastIds'; @@ -128,7 +130,7 @@ lastIds.findOne({}).exec(async (err, returnedLastId) => { }); const newForumLimiter = - process.env.ENV === 'local' + config.getEnv() === 'local' ? rateLimit({ max: 0, // Disable if we are local }) diff --git a/src/routes/index.js b/src/routes/index.js index f54cd2108..b4ef50a91 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -4,6 +4,7 @@ import sanitizeHtml from 'sanitize-html'; import mongoose from 'mongoose'; import fs from 'fs'; import rateLimit from 'express-rate-limit'; + import User from '../models/user'; import myNotification from '../models/notification'; import gameRecord from '../models/gameRecord'; @@ -11,6 +12,7 @@ import statsCumulative from '../models/statsCumulative'; import { emailExists, validEmail } from '../routes/emailVerification'; import { sendEmailVerification } from '../myFunctions/sendEmailVerification'; +import { config } from '../config'; import { disallowVPNs } from '../util/vpnDetection'; import { settingsSingleton } from '../settings'; import { Alliance } from '../gameplay/types'; @@ -30,11 +32,11 @@ router.get('/', (req, res) => { // register route router.get('/register', (req, res) => { - res.render('register', { platform: process.env.ENV }); + res.render('register', { platform: config.getEnv() }); }); const registerLimiter = - process.env.ENV === 'local' + config.getEnv() === 'local' ? rateLimit({ max: 0, // Disable if we are local }) @@ -97,7 +99,7 @@ router.post( passport.authenticate('local')(req, res, () => { res.redirect('/lobby'); }); - if (process.env.ENV === 'prod') { + if (config.getEnv() === 'prod') { sendEmailVerification(user, req.body.emailAddress); } else { user.emailVerified = true; @@ -111,7 +113,7 @@ router.post( ); const loginLimiter = - process.env.ENV === 'local' + config.getEnv() === 'local' ? rateLimit({ max: 0, // Disable if we are local }) @@ -235,7 +237,7 @@ router.get('/statistics', (req, res) => { }); router.get('/resetPassword', (req, res) => { - res.render('resetPassword', { platform: process.env.ENV }); + res.render('resetPassword', { platform: config.getEnv() }); }); router.post( diff --git a/src/routes/middleware.ts b/src/routes/middleware.ts index 1e864c9b9..c3c117684 100644 --- a/src/routes/middleware.ts +++ b/src/routes/middleware.ts @@ -8,6 +8,7 @@ import { isMod } from '../modsadmins/mods'; import { isAdmin } from '../modsadmins/admins'; import { RequestHandler } from 'express'; +import { config } from '../config'; // return a function that wraps an async middleware export const asyncMiddleware = @@ -221,7 +222,7 @@ export const isAdminMiddleware = (req, res, next) => { }; export const emailVerified = (req, res, next) => { - if (req.user.emailVerified === true || process.env.ENV != 'prod') { + if (req.user.emailVerified === true || config.getEnv() != 'prod') { next(); } else { res.redirect('/emailVerification'); diff --git a/src/sockets/commands/admin/acreatetestaccounts.ts b/src/sockets/commands/admin/acreatetestaccounts.ts index 33e10ea3d..e8c82e536 100644 --- a/src/sockets/commands/admin/acreatetestaccounts.ts +++ b/src/sockets/commands/admin/acreatetestaccounts.ts @@ -2,12 +2,13 @@ import { sendReplyToCommand } from '../../sockets'; import { SocketUser } from '../../types'; import User from '../../../models/user'; import { Command } from '../types'; +import { config } from '../../../config'; export const acreatetestaccounts: Command = { command: 'acreatetestaccounts', help: '/acreatetestaccounts: Creates test accounts: 1 to 10. Passwords are the username.', run: async (args: string[], socket: SocketUser) => { - if (process.env.ENV === 'prod') { + if (config.getEnv() === 'prod') { sendReplyToCommand(socket, 'Cannot create test accounts in prod.'); return; } diff --git a/src/sockets/sockets.ts b/src/sockets/sockets.ts index b64d31c70..aa66b3804 100644 --- a/src/sockets/sockets.ts +++ b/src/sockets/sockets.ts @@ -46,6 +46,7 @@ import { Card } from '../gameplay/cards/types'; import { TOCommandsImported } from './commands/tournamentOrganisers'; import { PatreonAgent } from '../clients/patreon/patreonAgent'; import { PatreonController } from '../clients/patreon/patreonController'; +import { config } from '../config'; const chatSpamFilter = new ChatSpamFilter(); const createRoomFilter = new CreateRoomFilter(); @@ -1954,7 +1955,7 @@ function joinQueue(): boolean { return false; } - if (process.env.ENV !== 'local') { + if (config.getEnv() !== 'local') { if (this.request.user.totalGamesPlayed < 3) { this.emit('allChatToClient', { message: 'You require 3 games to join the ranked queue.', diff --git a/src/util/captcha.ts b/src/util/captcha.ts index 3ce6303f1..8af63c416 100644 --- a/src/util/captcha.ts +++ b/src/util/captcha.ts @@ -1,8 +1,9 @@ import { RequestHandler } from 'express'; import axios from 'axios'; +import { config } from '../config'; export const captchaMiddleware: RequestHandler = async (req, res, next) => { - if (process.env.ENV !== 'prod') { + if (config.getEnv() !== 'prod') { return next(); } diff --git a/src/util/vpnDetection.ts b/src/util/vpnDetection.ts index eb713ea68..22a00f9c0 100644 --- a/src/util/vpnDetection.ts +++ b/src/util/vpnDetection.ts @@ -1,4 +1,5 @@ import { RequestHandler } from 'express'; +import { config } from '../config'; const VPN_TIMEOUT = 1000 * 60 * 60 * 12; // 12 hours @@ -116,7 +117,7 @@ const isVpnCheck2 = async (ip: string): Promise => { }; export const disallowVPNs: RequestHandler = (req, res, next) => { - if (process.env.ENV === 'local') { + if (config.getEnv() === 'local') { next(); return; } From e0a747c2b7c227b65e22a377f175be2e4da9a05a Mon Sep 17 00:00:00 2001 From: Kevin Date: Fri, 14 Jun 2024 22:41:48 +1000 Subject: [PATCH 06/43] Added s3 env variables to config --- src/clients/s3/S3Controller.ts | 9 +++++---- src/config.ts | 26 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/clients/s3/S3Controller.ts b/src/clients/s3/S3Controller.ts index c7c1de3ee..087e44c28 100644 --- a/src/clients/s3/S3Controller.ts +++ b/src/clients/s3/S3Controller.ts @@ -8,6 +8,7 @@ import { S3Client, } from '@aws-sdk/client-s3'; import { IS3Controller } from './S3Agent'; +import { config } from '../../config'; export default class S3Controller implements IS3Controller { private client: S3Client; @@ -15,12 +16,12 @@ export default class S3Controller implements IS3Controller { private bucket: string; constructor() { - this.publicFileLinkPrefix = process.env.S3_PUBLIC_FILE_LINK_PREFIX; - this.bucket = process.env.S3_BUCKET_NAME; + this.publicFileLinkPrefix = config.getS3PublicFileLinkPrefix(); + this.bucket = config.getS3BucketName(); this.client = new S3Client({ - region: process.env.S3_REGION, - endpoint: process.env.S3_ENDPOINT, + region: config.getS3Region(), + endpoint: config.getS3Endpoint(), credentials: fromEnv(), }); } diff --git a/src/config.ts b/src/config.ts index 7d8cd4140..09cf4da32 100644 --- a/src/config.ts +++ b/src/config.ts @@ -4,6 +4,11 @@ const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); class Config { private readonly env: string; + private readonly s3PublicFileLinkPrefix: string; + private readonly s3BucketName: string; + private readonly s3Region: string; + private readonly s3Endpoint: string; + constructor() { if (!VALID_ENVIRONMENTS.has(process.env.ENV)) { // TODO-kev: Prefer the console.error then process exit or throw an error? @@ -31,11 +36,32 @@ class Config { } this.env = process.env.ENV; + + this.s3PublicFileLinkPrefix = process.env.S3_PUBLIC_FILE_LINK_PREFIX; + this.s3BucketName = process.env.S3_BUCKET_NAME; + this.s3Region = process.env.S3_REGION; + this.s3Endpoint = process.env.S3_ENDPOINT; } public getEnv() { return this.env; } + + public getS3PublicFileLinkPrefix() { + return this.s3PublicFileLinkPrefix; + } + + public getS3BucketName() { + return this.s3BucketName; + } + + public getS3Region() { + return this.s3Region; + } + + public getS3Endpoint() { + return this.s3Endpoint; + } } export const config = new Config(); From bd0fd227bb4ee2e9b1aa8ff240de5956c0f66fdd Mon Sep 17 00:00:00 2001 From: Kevin Date: Fri, 14 Jun 2024 22:44:44 +1000 Subject: [PATCH 07/43] Added google captcha --- src/config.ts | 8 ++++++++ src/util/captcha.ts | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index 09cf4da32..d3df4381a 100644 --- a/src/config.ts +++ b/src/config.ts @@ -4,6 +4,8 @@ const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); class Config { private readonly env: string; + private readonly googleCaptchaKey: string; + private readonly s3PublicFileLinkPrefix: string; private readonly s3BucketName: string; private readonly s3Region: string; @@ -37,6 +39,8 @@ class Config { this.env = process.env.ENV; + this.googleCaptchaKey = process.env.MY_SECRET_GOOGLE_CAPTCHA_KEY; + this.s3PublicFileLinkPrefix = process.env.S3_PUBLIC_FILE_LINK_PREFIX; this.s3BucketName = process.env.S3_BUCKET_NAME; this.s3Region = process.env.S3_REGION; @@ -47,6 +51,10 @@ class Config { return this.env; } + public getGoogleCaptchaKey() { + return this.googleCaptchaKey; + } + public getS3PublicFileLinkPrefix() { return this.s3PublicFileLinkPrefix; } diff --git a/src/util/captcha.ts b/src/util/captcha.ts index 8af63c416..4d8888157 100644 --- a/src/util/captcha.ts +++ b/src/util/captcha.ts @@ -19,7 +19,7 @@ export const captchaMiddleware: RequestHandler = async (req, res, next) => { return; } - const secretKey = process.env.MY_SECRET_GOOGLE_CAPTCHA_KEY; + const secretKey = config.getGoogleCaptchaKey(); const verifyUrl = `https://google.com/recaptcha/api/siteverify?secret=${secretKey}&response=${req.body.captcha}&remoteip=${req.connection.remoteAddress}`; const response = await axios.post(verifyUrl); From 1ab7e67bc0bc6813f8df37ea951148df7e285324 Mon Sep 17 00:00:00 2001 From: Kevin Date: Fri, 14 Jun 2024 22:55:48 +1000 Subject: [PATCH 08/43] Added patreon envs to config --- src/clients/patreon/patreonController.ts | 7 ++++--- src/config.ts | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/clients/patreon/patreonController.ts b/src/clients/patreon/patreonController.ts index 9123cfec1..fb419d26c 100644 --- a/src/clients/patreon/patreonController.ts +++ b/src/clients/patreon/patreonController.ts @@ -4,6 +4,7 @@ import { PaidPatronFullDetails, } from './patreonAgent'; import uuid from 'uuid'; +import { config } from '../../config'; const PATREON_URLS = { AUTHORIZATION_LINK: 'https://www.patreon.com/oauth2/authorize', @@ -12,9 +13,9 @@ const PATREON_URLS = { }; export class PatreonController implements IPatreonController { - private clientId = process.env.patreon_client_ID; - private clientSecret = process.env.patreon_client_secret; - private redirectUri = process.env.patreon_redirectURL; + private clientId = config.getPatreonClientId(); + private clientSecret = config.getPatreonClientSecret(); + private redirectUri = config.getPatreonRedirectUrl(); public async getPatreonUserTokens(code: string): Promise { const getPatreonUserTokensUrl = new URL(PATREON_URLS.GET_TOKENS); diff --git a/src/config.ts b/src/config.ts index d3df4381a..656cc6cfd 100644 --- a/src/config.ts +++ b/src/config.ts @@ -11,6 +11,10 @@ class Config { private readonly s3Region: string; private readonly s3Endpoint: string; + private readonly patreonClientId: string; + private readonly patreonClientSecret: string; + private readonly patreonRedirectUrl: string; + constructor() { if (!VALID_ENVIRONMENTS.has(process.env.ENV)) { // TODO-kev: Prefer the console.error then process exit or throw an error? @@ -45,6 +49,10 @@ class Config { this.s3BucketName = process.env.S3_BUCKET_NAME; this.s3Region = process.env.S3_REGION; this.s3Endpoint = process.env.S3_ENDPOINT; + + this.patreonClientId = process.env.patreon_client_ID; + this.patreonClientSecret = process.env.patreon_client_secret; + this.patreonRedirectUrl = process.env.patreon_redirectURL; } public getEnv() { @@ -70,6 +78,18 @@ class Config { public getS3Endpoint() { return this.s3Endpoint; } + + public getPatreonClientId() { + return this.patreonClientId; + } + + public getPatreonClientSecret() { + return this.patreonClientSecret; + } + + public getPatreonRedirectUrl() { + return this.patreonRedirectUrl; + } } export const config = new Config(); From d9d9c6b679df7291aae81643991f00db32f01256 Mon Sep 17 00:00:00 2001 From: Kevin Date: Fri, 14 Jun 2024 23:23:39 +1000 Subject: [PATCH 09/43] Added nodeEnv and databaseUrl --- src/app.ts | 2 +- src/config.ts | 12 ++++++++++++ src/gameplay/game.ts | 3 ++- src/routes/mod.js | 3 ++- src/sockets/commands/admin/asessions.ts | 3 ++- src/sockets/sockets.ts | 4 ++-- 6 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/app.ts b/src/app.ts index d5cfb925b..258311529 100644 --- a/src/app.ts +++ b/src/app.ts @@ -84,7 +84,7 @@ if (config.getEnv() === 'local') { } const port = process.env.PORT || 3000; -const dbLoc = process.env.DATABASEURL; +const dbLoc = config.getDatabaseUrl(); console.log(`Using database url: ${dbLoc}`); mongoose.connect(dbLoc, { diff --git a/src/config.ts b/src/config.ts index 656cc6cfd..d4fd48231 100644 --- a/src/config.ts +++ b/src/config.ts @@ -3,8 +3,10 @@ const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); // TODO-kev: Should i import this into app.ts? class Config { private readonly env: string; + private readonly nodeEnv: string; private readonly googleCaptchaKey: string; + private readonly databaseUrl: string; private readonly s3PublicFileLinkPrefix: string; private readonly s3BucketName: string; @@ -42,8 +44,10 @@ class Config { } this.env = process.env.ENV; + this.nodeEnv = process.env.NODE_ENV; this.googleCaptchaKey = process.env.MY_SECRET_GOOGLE_CAPTCHA_KEY; + this.databaseUrl = process.env.DATABASEURL; this.s3PublicFileLinkPrefix = process.env.S3_PUBLIC_FILE_LINK_PREFIX; this.s3BucketName = process.env.S3_BUCKET_NAME; @@ -59,10 +63,18 @@ class Config { return this.env; } + public getNodeEnv() { + return this.nodeEnv; + } + public getGoogleCaptchaKey() { return this.googleCaptchaKey; } + public getDatabaseUrl() { + return this.databaseUrl; + } + public getS3PublicFileLinkPrefix() { return this.s3PublicFileLinkPrefix; } diff --git a/src/gameplay/game.ts b/src/gameplay/game.ts index 14bc4a30a..ba4c88d1c 100644 --- a/src/gameplay/game.ts +++ b/src/gameplay/game.ts @@ -32,6 +32,7 @@ import { millisToStr } from '../util/time'; import shuffleArray from '../util/shuffleArray'; import { Anonymizer } from './anonymizer'; import { sendReplyToCommand } from '../sockets/sockets'; +import { config } from '../config'; export const WAITING = 'Waiting'; export const MIN_PLAYERS = 5; @@ -1561,7 +1562,7 @@ class Game extends Room { }); } - if (process.env.NODE_ENV !== 'test') { + if (config.getNodeEnv() !== 'test') { this.playersInGame.forEach((player) => { User.findById(player.userId) .populate('notifications') diff --git a/src/routes/mod.js b/src/routes/mod.js index b7b014dcb..7010123f9 100644 --- a/src/routes/mod.js +++ b/src/routes/mod.js @@ -19,6 +19,7 @@ import ModLogComponent from '../views/components/mod/mod_log'; import ReportLog from '../views/components/mod/report'; import { MongoClient } from 'mongodb'; import { SESSIONS_COLLECTION_NAME } from '../constants'; +import { config } from '../config'; const router = new Router(); @@ -186,7 +187,7 @@ router.post('/ban', isModMiddleware, async (req, res) => { }); // Delete all the sessions associated with this username - const dbResult = await MongoClient.connect(process.env.DATABASEURL); + const dbResult = await MongoClient.connect(config.getDatabaseUrl()); const mySessions = dbResult.db().collection(SESSIONS_COLLECTION_NAME); const deleteResult = await mySessions.deleteMany({ 'session.usernameLower': banPlayerUsername.toLowerCase(), diff --git a/src/sockets/commands/admin/asessions.ts b/src/sockets/commands/admin/asessions.ts index 04d6f50ba..1bd7f082b 100644 --- a/src/sockets/commands/admin/asessions.ts +++ b/src/sockets/commands/admin/asessions.ts @@ -2,6 +2,7 @@ import { sendReplyToCommand } from '../../sockets'; import { SocketUser } from '../../types'; import { Command } from '../types'; import { MongoClient } from 'mongodb'; +import { config } from '../../../config'; export const asessions: Command = { command: 'asessions', @@ -14,7 +15,7 @@ export const asessions: Command = { return; } - const dbResult = await MongoClient.connect(process.env.DATABASEURL); + const dbResult = await MongoClient.connect(config.getDatabaseUrl()); const mySessions = dbResult.db().collection('mySessions'); const entries = mySessions.find({ 'session.usernameLower': username }); diff --git a/src/sockets/sockets.ts b/src/sockets/sockets.ts index aa66b3804..03f97774d 100644 --- a/src/sockets/sockets.ts +++ b/src/sockets/sockets.ts @@ -55,7 +55,7 @@ const matchmakingQueue = new MatchmakingQueue(matchFound); const joinQueueFilter = new JoinQueueFilter(() => new Date()); const readyPrompt = new ReadyPrompt(); -if (process.env.NODE_ENV !== 'test') { +if (config.getNodeEnv() !== 'test') { setInterval(() => { chatSpamFilter.tick(); }, 1000); @@ -149,7 +149,7 @@ function deleteSaveGameFromDb(room) { } } -if (process.env.NODE_ENV !== 'test') { +if (config.getNodeEnv() !== 'test') { setTimeout(async () => { let run = true; let i = 0; From ab66eeab894479a9e89851c05c07af96e3f1ea61 Mon Sep 17 00:00:00 2001 From: Kevin Date: Fri, 14 Jun 2024 23:48:29 +1000 Subject: [PATCH 10/43] Added email related configs --- src/config.ts | 27 +++++++++++++++++++++++++++ src/myFunctions/sendEmail.ts | 7 ++++--- src/myFunctions/sendResetPassword.ts | 3 ++- src/util/vpnDetection.ts | 2 +- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/config.ts b/src/config.ts index d4fd48231..9f7ae541b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -4,6 +4,11 @@ const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); class Config { private readonly env: string; private readonly nodeEnv: string; + private readonly serverDomain: string; + + private readonly proAvalonEmailAddressDomain: string; + private readonly proAvalonEmailAddress: string; + private readonly mailgunApiKey: string; private readonly googleCaptchaKey: string; private readonly databaseUrl: string; @@ -45,6 +50,12 @@ class Config { this.env = process.env.ENV; this.nodeEnv = process.env.NODE_ENV; + this.serverDomain = process.env.SERVER_DOMAIN; + + this.proAvalonEmailAddress = process.env.PROAVALON_EMAIL_ADDRESS; + this.proAvalonEmailAddressDomain = + process.env.PROAVALON_EMAIL_ADDRESS_DOMAIN; + this.mailgunApiKey = process.env.MAILGUN_API_KEY; this.googleCaptchaKey = process.env.MY_SECRET_GOOGLE_CAPTCHA_KEY; this.databaseUrl = process.env.DATABASEURL; @@ -67,6 +78,22 @@ class Config { return this.nodeEnv; } + public getServerDomain() { + return this.serverDomain; + } + + public getProAvalonEmailAddress() { + return this.proAvalonEmailAddress; + } + + public getProAvalonEmailAddressDomain() { + return this.proAvalonEmailAddressDomain; + } + + public getMailgunApiKey() { + return this.mailgunApiKey; + } + public getGoogleCaptchaKey() { return this.googleCaptchaKey; } diff --git a/src/myFunctions/sendEmail.ts b/src/myFunctions/sendEmail.ts index 664c6ba2f..cabd94dd5 100644 --- a/src/myFunctions/sendEmail.ts +++ b/src/myFunctions/sendEmail.ts @@ -1,8 +1,9 @@ import Mailgun from 'mailgun.js'; import formData from 'form-data'; +import { config } from '../config'; -const api_key = process.env.MAILGUN_API_KEY; -const domain = process.env.PROAVALON_EMAIL_ADDRESS_DOMAIN; +const api_key = config.getMailgunApiKey(); +const domain = config.getProAvalonEmailAddressDomain(); const mailgun = new Mailgun(formData); const mg = mailgun.client({ username: 'api', key: api_key }); @@ -13,7 +14,7 @@ export const sendEmail = ( messageHtml: string, ) => { const data = { - from: 'ProAvalon <' + process.env.PROAVALON_EMAIL_ADDRESS + '>', + from: 'ProAvalon <' + config.getProAvalonEmailAddress() + '>', to: recipientEmail, subject: subject, html: messageHtml, diff --git a/src/myFunctions/sendResetPassword.ts b/src/myFunctions/sendResetPassword.ts index 639741083..bf13a8ed9 100644 --- a/src/myFunctions/sendResetPassword.ts +++ b/src/myFunctions/sendResetPassword.ts @@ -2,10 +2,11 @@ import uuid from 'uuid'; import ejs from 'ejs'; import emailTemplateResetPassword from './emailTemplateResetPassword'; import { sendEmail } from './sendEmail'; +import { config } from '../config'; const TOKEN_TIMEOUT = 60 * 60 * 1000; // 1 hour -const serverDomain = process.env.SERVER_DOMAIN; +const serverDomain = config.getServerDomain(); export const sendResetPassword = async (user: any, email: string) => { const token = uuid.v4(); diff --git a/src/util/vpnDetection.ts b/src/util/vpnDetection.ts index 22a00f9c0..f5273c295 100644 --- a/src/util/vpnDetection.ts +++ b/src/util/vpnDetection.ts @@ -100,7 +100,7 @@ const isVpnCheck1 = async (ip: string): Promise => { const isVpnCheck2 = async (ip: string): Promise => { const vpnResponse = await fetch( - `https://check.getipintel.net/check.php?ip=${ip}&contact=${process.env.PROAVALON_EMAIL_ADDRESS}&flags=m`, + `https://check.getipintel.net/check.php?ip=${ip}&contact=${config.getProAvalonEmailAddress()}&flags=m`, ); const data = await vpnResponse.json(); From 3d324f53accc3e50372983e1ee359829394208b5 Mon Sep 17 00:00:00 2001 From: Kevin Date: Sat, 15 Jun 2024 00:15:34 +1000 Subject: [PATCH 11/43] Added the discord config --- src/clients/discord/index.ts | 10 ++++---- src/config.ts | 32 ++++++++++++++++++++++++ src/myFunctions/sendEmailVerification.ts | 3 ++- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/clients/discord/index.ts b/src/clients/discord/index.ts index 5e9f0d736..db056820c 100644 --- a/src/clients/discord/index.ts +++ b/src/clients/discord/index.ts @@ -4,21 +4,21 @@ import { config } from '../../config'; const client = new Discord.Client(); if (config.getEnv() === 'prod') { - client.login(process.env.discord_bot_token); + client.login(config.getDiscordBotToken()); } export function sendToDiscordAdmins(message: string, ping?: boolean): void { if (ping) { message = `${getAdminPing()} ${message}`; } - sendToChannel(message, process.env.discord_admin_channel_id); + sendToChannel(message, config.getDiscordAdminChannelId()); } export function sendToDiscordMods(message: string, ping?: boolean): void { if (ping) { message = `${getModPing()} ${message}`; } - sendToChannel(message, process.env.discord_mod_channel_id); + sendToChannel(message, config.getDiscordModChannelId()); } function sendToChannel(message: string, channelId: string): void { @@ -30,9 +30,9 @@ function sendToChannel(message: string, channelId: string): void { } function getAdminPing(): string { - return `<@&${process.env.discord_admin_role_id}>`; + return `<@&${config.getDiscordAdminRoleId()}>`; } function getModPing(): string { - return `<@&${process.env.discord_mod_role_id}>`; + return `<@&${config.getDiscordModRoleId()}>`; } diff --git a/src/config.ts b/src/config.ts index 9f7ae541b..5b7595828 100644 --- a/src/config.ts +++ b/src/config.ts @@ -22,6 +22,12 @@ class Config { private readonly patreonClientSecret: string; private readonly patreonRedirectUrl: string; + private readonly discordBotToken: string; + private readonly discordAdminChannelId: string; + private readonly discordModChannelId: string; + private readonly discordAdminRoleId: string; + private readonly discordModRoleId: string; + constructor() { if (!VALID_ENVIRONMENTS.has(process.env.ENV)) { // TODO-kev: Prefer the console.error then process exit or throw an error? @@ -68,6 +74,12 @@ class Config { this.patreonClientId = process.env.patreon_client_ID; this.patreonClientSecret = process.env.patreon_client_secret; this.patreonRedirectUrl = process.env.patreon_redirectURL; + + this.discordBotToken = process.env.discord_bot_token; + this.discordAdminChannelId = process.env.discord_admin_channel_id; + this.discordModChannelId = process.env.discord_mod_channel_id; + this.discordAdminRoleId = process.env.discord_admin_role_id; + this.discordModRoleId = process.env.discord_mod_role_id; } public getEnv() { @@ -129,6 +141,26 @@ class Config { public getPatreonRedirectUrl() { return this.patreonRedirectUrl; } + + public getDiscordBotToken() { + return this.discordBotToken; + } + + public getDiscordAdminChannelId() { + return this.discordAdminChannelId; + } + + public getDiscordModChannelId() { + return this.discordModChannelId; + } + + public getDiscordAdminRoleId() { + return this.discordAdminRoleId; + } + + public getDiscordModRoleId() { + return this.discordModRoleId; + } } export const config = new Config(); diff --git a/src/myFunctions/sendEmailVerification.ts b/src/myFunctions/sendEmailVerification.ts index 4ffbf8b77..984faf8a8 100644 --- a/src/myFunctions/sendEmailVerification.ts +++ b/src/myFunctions/sendEmailVerification.ts @@ -3,8 +3,9 @@ import emailTemplateEmailVerification from './emailTemplateEmailVerification'; import uuid from 'uuid'; import disposableEmails from '../util/disposableEmails.js'; import { sendEmail } from './sendEmail'; +import { config } from '../config'; -const serverDomain = process.env.SERVER_DOMAIN; +const serverDomain = config.getServerDomain(); const uuidv4 = uuid.v4; From 4c6825aca380a76815d9fb70a05d4649859e71b9 Mon Sep 17 00:00:00 2001 From: Kevin Date: Sat, 15 Jun 2024 00:36:03 +1000 Subject: [PATCH 12/43] Added vpn to config --- src/config.ts | 12 ++++++++++++ src/util/vpnDetection.ts | 7 ++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/config.ts b/src/config.ts index 5b7595828..d4a9f4c41 100644 --- a/src/config.ts +++ b/src/config.ts @@ -10,6 +10,8 @@ class Config { private readonly proAvalonEmailAddress: string; private readonly mailgunApiKey: string; + private readonly vpnDetectionToken: string; + private readonly whitelistedVpnUsernames: string; private readonly googleCaptchaKey: string; private readonly databaseUrl: string; @@ -63,6 +65,8 @@ class Config { process.env.PROAVALON_EMAIL_ADDRESS_DOMAIN; this.mailgunApiKey = process.env.MAILGUN_API_KEY; + this.vpnDetectionToken = process.env.VPN_DETECTION_TOKEN; + this.whitelistedVpnUsernames = process.env.WHITELISTED_VPN_USERNAMES; this.googleCaptchaKey = process.env.MY_SECRET_GOOGLE_CAPTCHA_KEY; this.databaseUrl = process.env.DATABASEURL; @@ -106,6 +110,14 @@ class Config { return this.mailgunApiKey; } + public getVpnDetectionToken() { + return this.vpnDetectionToken; + } + + public getWhitelistedVpnUsernames() { + return this.whitelistedVpnUsernames; + } + public getGoogleCaptchaKey() { return this.googleCaptchaKey; } diff --git a/src/util/vpnDetection.ts b/src/util/vpnDetection.ts index f5273c295..788f0e1c0 100644 --- a/src/util/vpnDetection.ts +++ b/src/util/vpnDetection.ts @@ -3,9 +3,10 @@ import { config } from '../config'; const VPN_TIMEOUT = 1000 * 60 * 60 * 12; // 12 hours +// TODO-kev: check if this still works let whitelistedUsernames: string[] = []; -if (process.env.WHITELISTED_VPN_USERNAMES) { - whitelistedUsernames = process.env.WHITELISTED_VPN_USERNAMES.split(','); +if (config.getWhitelistedVpnUsernames()) { + whitelistedUsernames = config.getWhitelistedVpnUsernames().split(','); } class VpnEntry { @@ -83,7 +84,7 @@ const isVPN = async (ip: string): Promise => { const isVpnCheck1 = async (ip: string): Promise => { const vpnResponse = await fetch( - `https://vpnapi.io/api/${ip}?key=${process.env.VPN_DETECTION_TOKEN}`, + `https://vpnapi.io/api/${ip}?key=${config.getVpnDetectionToken()}`, ); const data = await vpnResponse.json(); From 8e7d63d3a5c12faa742c0ddc317f59a81b8ef90b Mon Sep 17 00:00:00 2001 From: Kevin Date: Sat, 15 Jun 2024 00:39:39 +1000 Subject: [PATCH 13/43] Added remaining env to config --- src/app.ts | 6 +++--- src/config.ts | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/app.ts b/src/app.ts index 258311529..17d10c501 100644 --- a/src/app.ts +++ b/src/app.ts @@ -83,7 +83,7 @@ if (config.getEnv() === 'local') { ); } -const port = process.env.PORT || 3000; +const port = config.getPort() || 3000; const dbLoc = config.getDatabaseUrl(); console.log(`Using database url: ${dbLoc}`); @@ -130,7 +130,7 @@ process }); // authentication -const secretKey = process.env.MY_SECRET_KEY || 'MySecretKey'; +const secretKey = config.getMySecretKey() || 'MySecretKey'; app.use( session({ secret: secretKey, @@ -183,7 +183,7 @@ app.use('/lobby', lobbyRoutes); app.use('/forum', forumRoutes); app.use('/profile', profileRoutes); -const IP = process.env.IP || '127.0.0.1'; +const IP = config.getIp() || '127.0.0.1'; const server = app.listen(port, () => { console.log(`Server has started on ${IP}:${port}!`); }); diff --git a/src/config.ts b/src/config.ts index d4a9f4c41..7722a9421 100644 --- a/src/config.ts +++ b/src/config.ts @@ -5,6 +5,9 @@ class Config { private readonly env: string; private readonly nodeEnv: string; private readonly serverDomain: string; + private readonly port: string; + private readonly ip: string; + private readonly mySecretKey: string; private readonly proAvalonEmailAddressDomain: string; private readonly proAvalonEmailAddress: string; @@ -59,6 +62,9 @@ class Config { this.env = process.env.ENV; this.nodeEnv = process.env.NODE_ENV; this.serverDomain = process.env.SERVER_DOMAIN; + this.port = process.env.PORT; + this.ip = process.env.IP; + this.mySecretKey = process.env.MY_SECRET_KEY; this.proAvalonEmailAddress = process.env.PROAVALON_EMAIL_ADDRESS; this.proAvalonEmailAddressDomain = @@ -98,6 +104,18 @@ class Config { return this.serverDomain; } + public getPort() { + return this.port; + } + + public getIp() { + return this.ip; + } + + public getMySecretKey() { + return this.mySecretKey; + } + public getProAvalonEmailAddress() { return this.proAvalonEmailAddress; } From 0cbe508277ca944a25bf513f0098853c7c9d9eaf Mon Sep 17 00:00:00 2001 From: Kevin Date: Sat, 15 Jun 2024 01:02:07 +1000 Subject: [PATCH 14/43] Added a check for test environments --- src/config.ts | 50 ++++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/config.ts b/src/config.ts index 7722a9421..fd3edad35 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,6 +1,5 @@ const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); -// TODO-kev: Should i import this into app.ts? class Config { private readonly env: string; private readonly nodeEnv: string; @@ -34,29 +33,32 @@ class Config { private readonly discordModRoleId: string; constructor() { - if (!VALID_ENVIRONMENTS.has(process.env.ENV)) { - // TODO-kev: Prefer the console.error then process exit or throw an error? - console.error(`Bad environment variable given: ${process.env.ENV}`); - throw new Error(`Invalid settings: ENV=${process.env.ENV}`); - process.exit(1); - } - - if ( - process.env.ENV === 'staging' && - process.env.S3_BUCKET_NAME !== 'proavalon-staging' - ) { - throw new Error( - `Invalid settings: ENV=staging S3_BUCKET_NAME=${process.env.S3_BUCKET_NAME}`, - ); - } - - if ( - process.env.ENV === 'prod' && - process.env.S3_BUCKET_NAME !== 'proavalon' - ) { - throw new Error( - `Invalid settings: ENV=prod S3_BUCKET_NAME=${process.env.S3_BUCKET_NAME}`, - ); + // Run validation checks outside test environment + if (process.env.NODE_ENV !== 'test') { + if (!VALID_ENVIRONMENTS.has(process.env.ENV)) { + // TODO-kev: Prefer the console.error then process exit or throw an error? + console.error(`Bad environment variable given: ${process.env.ENV}`); + throw new Error(`Invalid settings: ENV=${process.env.ENV}`); + process.exit(1); + } + + if ( + process.env.ENV === 'staging' && + process.env.S3_BUCKET_NAME !== 'proavalon-staging' + ) { + throw new Error( + `Invalid settings: ENV=staging S3_BUCKET_NAME=${process.env.S3_BUCKET_NAME}`, + ); + } + + if ( + process.env.ENV === 'prod' && + process.env.S3_BUCKET_NAME !== 'proavalon' + ) { + throw new Error( + `Invalid settings: ENV=prod S3_BUCKET_NAME=${process.env.S3_BUCKET_NAME}`, + ); + } } this.env = process.env.ENV; From 4bb12441dbb4383315ab39ccf4efbb43c56a4bcb Mon Sep 17 00:00:00 2001 From: Kevin Date: Sat, 15 Jun 2024 01:08:42 +1000 Subject: [PATCH 15/43] Refactored config.ts --- src/config.ts | 115 +++++++++++++++++++------------------------------- 1 file changed, 43 insertions(+), 72 deletions(-) diff --git a/src/config.ts b/src/config.ts index fd3edad35..127ae2a2b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,97 +1,68 @@ const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); class Config { - private readonly env: string; - private readonly nodeEnv: string; - private readonly serverDomain: string; - private readonly port: string; - private readonly ip: string; - private readonly mySecretKey: string; - - private readonly proAvalonEmailAddressDomain: string; - private readonly proAvalonEmailAddress: string; - private readonly mailgunApiKey: string; - - private readonly vpnDetectionToken: string; - private readonly whitelistedVpnUsernames: string; - private readonly googleCaptchaKey: string; - private readonly databaseUrl: string; - - private readonly s3PublicFileLinkPrefix: string; - private readonly s3BucketName: string; - private readonly s3Region: string; - private readonly s3Endpoint: string; - - private readonly patreonClientId: string; - private readonly patreonClientSecret: string; - private readonly patreonRedirectUrl: string; - - private readonly discordBotToken: string; - private readonly discordAdminChannelId: string; - private readonly discordModChannelId: string; - private readonly discordAdminRoleId: string; - private readonly discordModRoleId: string; + private readonly env: string = process.env.ENV; + private readonly nodeEnv: string = process.env.NODE_ENV; + private readonly serverDomain: string = process.env.SERVER_DOMAIN; + private readonly port: string = process.env.PORT; + private readonly ip: string = process.env.IP; + private readonly mySecretKey: string = process.env.MY_SECRET_KEY; + + private readonly proAvalonEmailAddressDomain: string = + process.env.PROAVALON_EMAIL_ADDRESS_DOMAIN; + private readonly proAvalonEmailAddress: string = + process.env.PROAVALON_EMAIL_ADDRESS; + private readonly mailgunApiKey: string = process.env.MAILGUN_API_KEY; + + private readonly vpnDetectionToken: string = process.env.VPN_DETECTION_TOKEN; + private readonly whitelistedVpnUsernames: string = + process.env.WHITELISTED_VPN_USERNAMES; + private readonly googleCaptchaKey: string = + process.env.MY_SECRET_GOOGLE_CAPTCHA_KEY; + private readonly databaseUrl: string = process.env.DATABASEURL; + + private readonly s3PublicFileLinkPrefix: string = + process.env.S3_PUBLIC_FILE_LINK_PREFIX; + private readonly s3BucketName: string = process.env.S3_BUCKET_NAME; + private readonly s3Region: string = process.env.S3_REGION; + private readonly s3Endpoint: string = process.env.S3_ENDPOINT; + + private readonly patreonClientId: string = process.env.patreon_client_ID; + private readonly patreonClientSecret: string = + process.env.patreon_client_secret; + private readonly patreonRedirectUrl: string = process.env.patreon_redirectURL; + + private readonly discordBotToken: string = process.env.discord_bot_token; + private readonly discordAdminChannelId: string = + process.env.discord_admin_channel_id; + private readonly discordModChannelId: string = + process.env.discord_mod_channel_id; + private readonly discordAdminRoleId: string = + process.env.discord_admin_role_id; + private readonly discordModRoleId: string = process.env.discord_mod_role_id; constructor() { // Run validation checks outside test environment - if (process.env.NODE_ENV !== 'test') { - if (!VALID_ENVIRONMENTS.has(process.env.ENV)) { + if (this.nodeEnv !== 'test') { + if (!VALID_ENVIRONMENTS.has(this.env)) { // TODO-kev: Prefer the console.error then process exit or throw an error? console.error(`Bad environment variable given: ${process.env.ENV}`); throw new Error(`Invalid settings: ENV=${process.env.ENV}`); process.exit(1); } - if ( - process.env.ENV === 'staging' && - process.env.S3_BUCKET_NAME !== 'proavalon-staging' - ) { + if (this.env === 'staging' && this.s3BucketName !== 'proavalon-staging') { throw new Error( `Invalid settings: ENV=staging S3_BUCKET_NAME=${process.env.S3_BUCKET_NAME}`, ); } - if ( - process.env.ENV === 'prod' && - process.env.S3_BUCKET_NAME !== 'proavalon' - ) { + if (this.env === 'prod' && this.s3BucketName !== 'proavalon') { throw new Error( `Invalid settings: ENV=prod S3_BUCKET_NAME=${process.env.S3_BUCKET_NAME}`, ); } } - - this.env = process.env.ENV; - this.nodeEnv = process.env.NODE_ENV; - this.serverDomain = process.env.SERVER_DOMAIN; - this.port = process.env.PORT; - this.ip = process.env.IP; - this.mySecretKey = process.env.MY_SECRET_KEY; - - this.proAvalonEmailAddress = process.env.PROAVALON_EMAIL_ADDRESS; - this.proAvalonEmailAddressDomain = - process.env.PROAVALON_EMAIL_ADDRESS_DOMAIN; - this.mailgunApiKey = process.env.MAILGUN_API_KEY; - - this.vpnDetectionToken = process.env.VPN_DETECTION_TOKEN; - this.whitelistedVpnUsernames = process.env.WHITELISTED_VPN_USERNAMES; - this.googleCaptchaKey = process.env.MY_SECRET_GOOGLE_CAPTCHA_KEY; - this.databaseUrl = process.env.DATABASEURL; - - this.s3PublicFileLinkPrefix = process.env.S3_PUBLIC_FILE_LINK_PREFIX; - this.s3BucketName = process.env.S3_BUCKET_NAME; - this.s3Region = process.env.S3_REGION; - this.s3Endpoint = process.env.S3_ENDPOINT; - - this.patreonClientId = process.env.patreon_client_ID; - this.patreonClientSecret = process.env.patreon_client_secret; - this.patreonRedirectUrl = process.env.patreon_redirectURL; - - this.discordBotToken = process.env.discord_bot_token; - this.discordAdminChannelId = process.env.discord_admin_channel_id; - this.discordModChannelId = process.env.discord_mod_channel_id; - this.discordAdminRoleId = process.env.discord_admin_role_id; - this.discordModRoleId = process.env.discord_mod_role_id; } public getEnv() { From 5eebee94b76ca2035f0585fec8cf6b244e8843dc Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 14:34:02 +1000 Subject: [PATCH 16/43] Added config directory. Split out patreonConfig partially --- src/app.ts | 4 ++-- src/clients/discord/index.ts | 2 +- src/clients/patreon/patreonController.ts | 2 +- src/clients/s3/S3Controller.ts | 2 +- src/{ => config}/config.ts | 10 ++++++++++ src/config/patreonConfig.ts | 11 +++++++++++ src/gameplay/game.ts | 2 +- src/myFunctions/sendEmail.ts | 2 +- src/myFunctions/sendEmailVerification.ts | 2 +- src/myFunctions/sendResetPassword.ts | 2 +- src/routes/forum/forumThreadCommentReplyRoutes.js | 2 +- src/routes/forum/forumThreadCommentRoutes.js | 2 +- src/routes/forum/forumThreadRoutes.js | 2 +- src/routes/index.js | 2 +- src/routes/middleware.ts | 2 +- src/routes/mod.js | 2 +- src/sockets/commands/admin/acreatetestaccounts.ts | 2 +- src/sockets/commands/admin/asessions.ts | 2 +- src/sockets/sockets.ts | 2 +- src/util/captcha.ts | 2 +- src/util/vpnDetection.ts | 2 +- 21 files changed, 41 insertions(+), 20 deletions(-) rename src/{ => config}/config.ts (95%) create mode 100644 src/config/patreonConfig.ts diff --git a/src/app.ts b/src/app.ts index 17d10c501..54a8f1f43 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,6 +1,6 @@ // @ts-nocheck import './env.js'; -import './config'; +import './config/config'; import 'log-timestamp'; import { sendToDiscordAdmins } from './clients/discord'; import assert from 'assert'; @@ -20,7 +20,7 @@ import socket, { Server as SocketServer } from 'socket.io'; import createProxyMiddleware from 'http-proxy-middleware'; import morgan from 'morgan'; -import { config } from './config'; +import { config } from './config/config'; import { server as socketServer } from './sockets/sockets'; import User from './models/user'; import { emailVerified, isLoggedIn } from './routes/middleware'; diff --git a/src/clients/discord/index.ts b/src/clients/discord/index.ts index db056820c..6cf323389 100644 --- a/src/clients/discord/index.ts +++ b/src/clients/discord/index.ts @@ -1,5 +1,5 @@ import Discord, { TextChannel } from 'discord.js'; -import { config } from '../../config'; +import { config } from '../../config/config'; const client = new Discord.Client(); diff --git a/src/clients/patreon/patreonController.ts b/src/clients/patreon/patreonController.ts index fb419d26c..4d642b14d 100644 --- a/src/clients/patreon/patreonController.ts +++ b/src/clients/patreon/patreonController.ts @@ -4,7 +4,7 @@ import { PaidPatronFullDetails, } from './patreonAgent'; import uuid from 'uuid'; -import { config } from '../../config'; +import { config } from '../../config/config'; const PATREON_URLS = { AUTHORIZATION_LINK: 'https://www.patreon.com/oauth2/authorize', diff --git a/src/clients/s3/S3Controller.ts b/src/clients/s3/S3Controller.ts index 087e44c28..effdf9308 100644 --- a/src/clients/s3/S3Controller.ts +++ b/src/clients/s3/S3Controller.ts @@ -8,7 +8,7 @@ import { S3Client, } from '@aws-sdk/client-s3'; import { IS3Controller } from './S3Agent'; -import { config } from '../../config'; +import { config } from '../../config/config'; export default class S3Controller implements IS3Controller { private client: S3Client; diff --git a/src/config.ts b/src/config/config.ts similarity index 95% rename from src/config.ts rename to src/config/config.ts index 127ae2a2b..c6a0fc458 100644 --- a/src/config.ts +++ b/src/config/config.ts @@ -1,3 +1,5 @@ +import { PatreonConfig, PatreonConfigType } from './patreonConfig'; + const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); class Config { @@ -166,4 +168,12 @@ class Config { } } +type ConfigNew = { + patreon: PatreonConfigType; +}; + +export const configNew: Readonly = Object.freeze({ + patreon: PatreonConfig, +}); + export const config = new Config(); diff --git a/src/config/patreonConfig.ts b/src/config/patreonConfig.ts new file mode 100644 index 000000000..d42ce163f --- /dev/null +++ b/src/config/patreonConfig.ts @@ -0,0 +1,11 @@ +export type PatreonConfigType = { + patreonClientId: string; + patreonClientSecret: string; + patreonRedirectUrl: string; +}; + +export const PatreonConfig: Readonly = Object.freeze({ + patreonClientId: process.env.patreon_client_ID, + patreonClientSecret: process.env.patreon_client_secret, + patreonRedirectUrl: process.env.patreon_redirectURL, +}); diff --git a/src/gameplay/game.ts b/src/gameplay/game.ts index ba4c88d1c..8d602799a 100644 --- a/src/gameplay/game.ts +++ b/src/gameplay/game.ts @@ -32,7 +32,7 @@ import { millisToStr } from '../util/time'; import shuffleArray from '../util/shuffleArray'; import { Anonymizer } from './anonymizer'; import { sendReplyToCommand } from '../sockets/sockets'; -import { config } from '../config'; +import { config } from '../config/config'; export const WAITING = 'Waiting'; export const MIN_PLAYERS = 5; diff --git a/src/myFunctions/sendEmail.ts b/src/myFunctions/sendEmail.ts index cabd94dd5..071977db4 100644 --- a/src/myFunctions/sendEmail.ts +++ b/src/myFunctions/sendEmail.ts @@ -1,6 +1,6 @@ import Mailgun from 'mailgun.js'; import formData from 'form-data'; -import { config } from '../config'; +import { config } from '../config/config'; const api_key = config.getMailgunApiKey(); const domain = config.getProAvalonEmailAddressDomain(); diff --git a/src/myFunctions/sendEmailVerification.ts b/src/myFunctions/sendEmailVerification.ts index 984faf8a8..1e809da69 100644 --- a/src/myFunctions/sendEmailVerification.ts +++ b/src/myFunctions/sendEmailVerification.ts @@ -3,7 +3,7 @@ import emailTemplateEmailVerification from './emailTemplateEmailVerification'; import uuid from 'uuid'; import disposableEmails from '../util/disposableEmails.js'; import { sendEmail } from './sendEmail'; -import { config } from '../config'; +import { config } from '../config/config'; const serverDomain = config.getServerDomain(); diff --git a/src/myFunctions/sendResetPassword.ts b/src/myFunctions/sendResetPassword.ts index bf13a8ed9..9c0506322 100644 --- a/src/myFunctions/sendResetPassword.ts +++ b/src/myFunctions/sendResetPassword.ts @@ -2,7 +2,7 @@ import uuid from 'uuid'; import ejs from 'ejs'; import emailTemplateResetPassword from './emailTemplateResetPassword'; import { sendEmail } from './sendEmail'; -import { config } from '../config'; +import { config } from '../config/config'; const TOKEN_TIMEOUT = 60 * 60 * 1000; // 1 hour diff --git a/src/routes/forum/forumThreadCommentReplyRoutes.js b/src/routes/forum/forumThreadCommentReplyRoutes.js index 593f8722d..feb06b62c 100644 --- a/src/routes/forum/forumThreadCommentReplyRoutes.js +++ b/src/routes/forum/forumThreadCommentReplyRoutes.js @@ -3,7 +3,7 @@ import sanitizeHtml from 'sanitize-html'; import mongoose from 'mongoose'; import rateLimit from 'express-rate-limit'; -import { config } from '../../config'; +import { config } from '../../config/config'; import forumThread from '../../models/forumThread'; import forumThreadComment from '../../models/forumThreadComment'; import forumThreadCommentReply from '../../models/forumThreadCommentReply'; diff --git a/src/routes/forum/forumThreadCommentRoutes.js b/src/routes/forum/forumThreadCommentRoutes.js index b5f41b300..03c8fd554 100644 --- a/src/routes/forum/forumThreadCommentRoutes.js +++ b/src/routes/forum/forumThreadCommentRoutes.js @@ -12,7 +12,7 @@ import { allowedHtmlAttributes, allowedHtmlTags } from './sanitizeRestrictions'; import { createNotification } from '../../myFunctions/createNotification'; import REWARDS from '../../rewards/constants'; import { userHasReward } from '../../rewards/getRewards'; -import { config } from '../../config'; +import { config } from '../../config/config'; const router = new Router(); diff --git a/src/routes/forum/forumThreadRoutes.js b/src/routes/forum/forumThreadRoutes.js index 8c7e99b16..e9753a88b 100644 --- a/src/routes/forum/forumThreadRoutes.js +++ b/src/routes/forum/forumThreadRoutes.js @@ -2,7 +2,7 @@ import { Router } from 'express'; import sanitizeHtml from 'sanitize-html'; import rateLimit from 'express-rate-limit'; -import { config } from '../../config'; +import { config } from '../../config/config'; import { checkForumThreadOwnership, asyncMiddleware } from '../middleware'; import getTimeDiffInString from '../../util/getTimeDiffInString'; import lastIds from '../../models/lastIds'; diff --git a/src/routes/index.js b/src/routes/index.js index b4ef50a91..eb553fb6b 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -12,7 +12,7 @@ import statsCumulative from '../models/statsCumulative'; import { emailExists, validEmail } from '../routes/emailVerification'; import { sendEmailVerification } from '../myFunctions/sendEmailVerification'; -import { config } from '../config'; +import { config } from '../config/config'; import { disallowVPNs } from '../util/vpnDetection'; import { settingsSingleton } from '../settings'; import { Alliance } from '../gameplay/types'; diff --git a/src/routes/middleware.ts b/src/routes/middleware.ts index c3c117684..8e60ba15e 100644 --- a/src/routes/middleware.ts +++ b/src/routes/middleware.ts @@ -8,7 +8,7 @@ import { isMod } from '../modsadmins/mods'; import { isAdmin } from '../modsadmins/admins'; import { RequestHandler } from 'express'; -import { config } from '../config'; +import { config } from '../config/config'; // return a function that wraps an async middleware export const asyncMiddleware = diff --git a/src/routes/mod.js b/src/routes/mod.js index 7010123f9..60be57d0e 100644 --- a/src/routes/mod.js +++ b/src/routes/mod.js @@ -19,7 +19,7 @@ import ModLogComponent from '../views/components/mod/mod_log'; import ReportLog from '../views/components/mod/report'; import { MongoClient } from 'mongodb'; import { SESSIONS_COLLECTION_NAME } from '../constants'; -import { config } from '../config'; +import { config } from '../config/config'; const router = new Router(); diff --git a/src/sockets/commands/admin/acreatetestaccounts.ts b/src/sockets/commands/admin/acreatetestaccounts.ts index e8c82e536..c14f0e244 100644 --- a/src/sockets/commands/admin/acreatetestaccounts.ts +++ b/src/sockets/commands/admin/acreatetestaccounts.ts @@ -2,7 +2,7 @@ import { sendReplyToCommand } from '../../sockets'; import { SocketUser } from '../../types'; import User from '../../../models/user'; import { Command } from '../types'; -import { config } from '../../../config'; +import { config } from '../../../config/config'; export const acreatetestaccounts: Command = { command: 'acreatetestaccounts', diff --git a/src/sockets/commands/admin/asessions.ts b/src/sockets/commands/admin/asessions.ts index 1bd7f082b..253e355e2 100644 --- a/src/sockets/commands/admin/asessions.ts +++ b/src/sockets/commands/admin/asessions.ts @@ -2,7 +2,7 @@ import { sendReplyToCommand } from '../../sockets'; import { SocketUser } from '../../types'; import { Command } from '../types'; import { MongoClient } from 'mongodb'; -import { config } from '../../../config'; +import { config } from '../../../config/config'; export const asessions: Command = { command: 'asessions', diff --git a/src/sockets/sockets.ts b/src/sockets/sockets.ts index 03f97774d..7d9d522eb 100644 --- a/src/sockets/sockets.ts +++ b/src/sockets/sockets.ts @@ -46,7 +46,7 @@ import { Card } from '../gameplay/cards/types'; import { TOCommandsImported } from './commands/tournamentOrganisers'; import { PatreonAgent } from '../clients/patreon/patreonAgent'; import { PatreonController } from '../clients/patreon/patreonController'; -import { config } from '../config'; +import { config } from '../config/config'; const chatSpamFilter = new ChatSpamFilter(); const createRoomFilter = new CreateRoomFilter(); diff --git a/src/util/captcha.ts b/src/util/captcha.ts index 4d8888157..a9ec1cbd4 100644 --- a/src/util/captcha.ts +++ b/src/util/captcha.ts @@ -1,6 +1,6 @@ import { RequestHandler } from 'express'; import axios from 'axios'; -import { config } from '../config'; +import { config } from '../config/config'; export const captchaMiddleware: RequestHandler = async (req, res, next) => { if (config.getEnv() !== 'prod') { diff --git a/src/util/vpnDetection.ts b/src/util/vpnDetection.ts index 788f0e1c0..9d69ed69f 100644 --- a/src/util/vpnDetection.ts +++ b/src/util/vpnDetection.ts @@ -1,5 +1,5 @@ import { RequestHandler } from 'express'; -import { config } from '../config'; +import { config } from '../config/config'; const VPN_TIMEOUT = 1000 * 60 * 60 * 12; // 12 hours From 260fa45e6a23336096a7dcfb2fd8ab50f2358dc6 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 14:39:56 +1000 Subject: [PATCH 17/43] Renamed config to configOld for refactor purposes --- src/app.ts | 12 ++++++------ src/clients/discord/index.ts | 16 ++++++++-------- src/clients/patreon/patreonController.ts | 8 ++++---- src/clients/s3/S3Controller.ts | 10 +++++----- src/config/config.ts | 4 ++-- src/gameplay/game.ts | 6 +++--- src/gameplay/room.ts | 2 +- src/myFunctions/sendEmail.ts | 8 ++++---- src/myFunctions/sendEmailVerification.ts | 4 ++-- src/myFunctions/sendResetPassword.ts | 4 ++-- .../forum/forumThreadCommentReplyRoutes.js | 4 ++-- src/routes/forum/forumThreadCommentRoutes.js | 4 ++-- src/routes/forum/forumThreadRoutes.js | 4 ++-- src/routes/index.js | 12 ++++++------ src/routes/middleware.ts | 4 ++-- src/routes/mod.js | 4 ++-- .../commands/admin/acreatetestaccounts.ts | 4 ++-- src/sockets/commands/admin/asessions.ts | 4 ++-- src/sockets/sockets.ts | 8 ++++---- src/util/captcha.ts | 6 +++--- src/util/disposableEmails.js | 2 +- src/util/vpnDetection.ts | 12 ++++++------ 22 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/app.ts b/src/app.ts index 54a8f1f43..8f7c5527e 100644 --- a/src/app.ts +++ b/src/app.ts @@ -20,7 +20,7 @@ import socket, { Server as SocketServer } from 'socket.io'; import createProxyMiddleware from 'http-proxy-middleware'; import morgan from 'morgan'; -import { config } from './config/config'; +import { configOld } from './config/config'; import { server as socketServer } from './sockets/sockets'; import User from './models/user'; import { emailVerified, isLoggedIn } from './routes/middleware'; @@ -75,7 +75,7 @@ app.use( ), ); -if (config.getEnv() === 'local') { +if (configOld.getEnv() === 'local') { console.log('Routing dist_webpack to localhost:3010.'); app.use( '/dist_webpack', @@ -83,8 +83,8 @@ if (config.getEnv() === 'local') { ); } -const port = config.getPort() || 3000; -const dbLoc = config.getDatabaseUrl(); +const port = configOld.getPort() || 3000; +const dbLoc = configOld.getDatabaseUrl(); console.log(`Using database url: ${dbLoc}`); mongoose.connect(dbLoc, { @@ -130,7 +130,7 @@ process }); // authentication -const secretKey = config.getMySecretKey() || 'MySecretKey'; +const secretKey = configOld.getMySecretKey() || 'MySecretKey'; app.use( session({ secret: secretKey, @@ -183,7 +183,7 @@ app.use('/lobby', lobbyRoutes); app.use('/forum', forumRoutes); app.use('/profile', profileRoutes); -const IP = config.getIp() || '127.0.0.1'; +const IP = configOld.getIp() || '127.0.0.1'; const server = app.listen(port, () => { console.log(`Server has started on ${IP}:${port}!`); }); diff --git a/src/clients/discord/index.ts b/src/clients/discord/index.ts index 6cf323389..f7afcf548 100644 --- a/src/clients/discord/index.ts +++ b/src/clients/discord/index.ts @@ -1,38 +1,38 @@ import Discord, { TextChannel } from 'discord.js'; -import { config } from '../../config/config'; +import { configOld } from '../../config/config'; const client = new Discord.Client(); -if (config.getEnv() === 'prod') { - client.login(config.getDiscordBotToken()); +if (configOld.getEnv() === 'prod') { + client.login(configOld.getDiscordBotToken()); } export function sendToDiscordAdmins(message: string, ping?: boolean): void { if (ping) { message = `${getAdminPing()} ${message}`; } - sendToChannel(message, config.getDiscordAdminChannelId()); + sendToChannel(message, configOld.getDiscordAdminChannelId()); } export function sendToDiscordMods(message: string, ping?: boolean): void { if (ping) { message = `${getModPing()} ${message}`; } - sendToChannel(message, config.getDiscordModChannelId()); + sendToChannel(message, configOld.getDiscordModChannelId()); } function sendToChannel(message: string, channelId: string): void { const channel = client.channels.cache.get(channelId) as TextChannel; - if (config.getEnv() === 'prod') { + if (configOld.getEnv() === 'prod') { channel.send(message); } } function getAdminPing(): string { - return `<@&${config.getDiscordAdminRoleId()}>`; + return `<@&${configOld.getDiscordAdminRoleId()}>`; } function getModPing(): string { - return `<@&${config.getDiscordModRoleId()}>`; + return `<@&${configOld.getDiscordModRoleId()}>`; } diff --git a/src/clients/patreon/patreonController.ts b/src/clients/patreon/patreonController.ts index 4d642b14d..8d57d8d6d 100644 --- a/src/clients/patreon/patreonController.ts +++ b/src/clients/patreon/patreonController.ts @@ -4,7 +4,7 @@ import { PaidPatronFullDetails, } from './patreonAgent'; import uuid from 'uuid'; -import { config } from '../../config/config'; +import { configOld } from '../../config/config'; const PATREON_URLS = { AUTHORIZATION_LINK: 'https://www.patreon.com/oauth2/authorize', @@ -13,9 +13,9 @@ const PATREON_URLS = { }; export class PatreonController implements IPatreonController { - private clientId = config.getPatreonClientId(); - private clientSecret = config.getPatreonClientSecret(); - private redirectUri = config.getPatreonRedirectUrl(); + private clientId = configOld.getPatreonClientId(); + private clientSecret = configOld.getPatreonClientSecret(); + private redirectUri = configOld.getPatreonRedirectUrl(); public async getPatreonUserTokens(code: string): Promise { const getPatreonUserTokensUrl = new URL(PATREON_URLS.GET_TOKENS); diff --git a/src/clients/s3/S3Controller.ts b/src/clients/s3/S3Controller.ts index effdf9308..5934178ea 100644 --- a/src/clients/s3/S3Controller.ts +++ b/src/clients/s3/S3Controller.ts @@ -8,7 +8,7 @@ import { S3Client, } from '@aws-sdk/client-s3'; import { IS3Controller } from './S3Agent'; -import { config } from '../../config/config'; +import { configOld } from '../../config/config'; export default class S3Controller implements IS3Controller { private client: S3Client; @@ -16,12 +16,12 @@ export default class S3Controller implements IS3Controller { private bucket: string; constructor() { - this.publicFileLinkPrefix = config.getS3PublicFileLinkPrefix(); - this.bucket = config.getS3BucketName(); + this.publicFileLinkPrefix = configOld.getS3PublicFileLinkPrefix(); + this.bucket = configOld.getS3BucketName(); this.client = new S3Client({ - region: config.getS3Region(), - endpoint: config.getS3Endpoint(), + region: configOld.getS3Region(), + endpoint: configOld.getS3Endpoint(), credentials: fromEnv(), }); } diff --git a/src/config/config.ts b/src/config/config.ts index c6a0fc458..3ec109bb6 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -172,8 +172,8 @@ type ConfigNew = { patreon: PatreonConfigType; }; -export const configNew: Readonly = Object.freeze({ +export const config: Readonly = Object.freeze({ patreon: PatreonConfig, }); -export const config = new Config(); +export const configOld = new Config(); diff --git a/src/gameplay/game.ts b/src/gameplay/game.ts index 8d602799a..56adafe53 100644 --- a/src/gameplay/game.ts +++ b/src/gameplay/game.ts @@ -32,7 +32,7 @@ import { millisToStr } from '../util/time'; import shuffleArray from '../util/shuffleArray'; import { Anonymizer } from './anonymizer'; import { sendReplyToCommand } from '../sockets/sockets'; -import { config } from '../config/config'; +import { configOld } from '../config/config'; export const WAITING = 'Waiting'; export const MIN_PLAYERS = 5; @@ -129,7 +129,7 @@ class Game extends Room { constructor(gameConfig: GameConfig) { super(gameConfig.roomConfig); - // Expand config + // Expand configOld this.muteSpectators = gameConfig.muteSpectators; this.disableVoteHistory = gameConfig.disableVoteHistory; this.roomCreationType = gameConfig.roomCreationType; @@ -1562,7 +1562,7 @@ class Game extends Room { }); } - if (config.getNodeEnv() !== 'test') { + if (configOld.getNodeEnv() !== 'test') { this.playersInGame.forEach((player) => { User.findById(player.userId) .populate('notifications') diff --git a/src/gameplay/room.ts b/src/gameplay/room.ts index 542aea6a0..e20babb57 100644 --- a/src/gameplay/room.ts +++ b/src/gameplay/room.ts @@ -79,7 +79,7 @@ class Room { readyPrompt: ReadyPrompt; constructor(roomConfig: RoomConfig) { - // Expand config + // Expand configOld this.host = roomConfig.host; this.roomId = roomConfig.roomId; this.io = roomConfig.io; diff --git a/src/myFunctions/sendEmail.ts b/src/myFunctions/sendEmail.ts index 071977db4..e538e2bba 100644 --- a/src/myFunctions/sendEmail.ts +++ b/src/myFunctions/sendEmail.ts @@ -1,9 +1,9 @@ import Mailgun from 'mailgun.js'; import formData from 'form-data'; -import { config } from '../config/config'; +import { configOld } from '../config/config'; -const api_key = config.getMailgunApiKey(); -const domain = config.getProAvalonEmailAddressDomain(); +const api_key = configOld.getMailgunApiKey(); +const domain = configOld.getProAvalonEmailAddressDomain(); const mailgun = new Mailgun(formData); const mg = mailgun.client({ username: 'api', key: api_key }); @@ -14,7 +14,7 @@ export const sendEmail = ( messageHtml: string, ) => { const data = { - from: 'ProAvalon <' + config.getProAvalonEmailAddress() + '>', + from: 'ProAvalon <' + configOld.getProAvalonEmailAddress() + '>', to: recipientEmail, subject: subject, html: messageHtml, diff --git a/src/myFunctions/sendEmailVerification.ts b/src/myFunctions/sendEmailVerification.ts index 1e809da69..4af720410 100644 --- a/src/myFunctions/sendEmailVerification.ts +++ b/src/myFunctions/sendEmailVerification.ts @@ -3,9 +3,9 @@ import emailTemplateEmailVerification from './emailTemplateEmailVerification'; import uuid from 'uuid'; import disposableEmails from '../util/disposableEmails.js'; import { sendEmail } from './sendEmail'; -import { config } from '../config/config'; +import { configOld } from '../config/config'; -const serverDomain = config.getServerDomain(); +const serverDomain = configOld.getServerDomain(); const uuidv4 = uuid.v4; diff --git a/src/myFunctions/sendResetPassword.ts b/src/myFunctions/sendResetPassword.ts index 9c0506322..97340baf6 100644 --- a/src/myFunctions/sendResetPassword.ts +++ b/src/myFunctions/sendResetPassword.ts @@ -2,11 +2,11 @@ import uuid from 'uuid'; import ejs from 'ejs'; import emailTemplateResetPassword from './emailTemplateResetPassword'; import { sendEmail } from './sendEmail'; -import { config } from '../config/config'; +import { configOld } from '../config/config'; const TOKEN_TIMEOUT = 60 * 60 * 1000; // 1 hour -const serverDomain = config.getServerDomain(); +const serverDomain = configOld.getServerDomain(); export const sendResetPassword = async (user: any, email: string) => { const token = uuid.v4(); diff --git a/src/routes/forum/forumThreadCommentReplyRoutes.js b/src/routes/forum/forumThreadCommentReplyRoutes.js index feb06b62c..79970e878 100644 --- a/src/routes/forum/forumThreadCommentReplyRoutes.js +++ b/src/routes/forum/forumThreadCommentReplyRoutes.js @@ -3,7 +3,7 @@ import sanitizeHtml from 'sanitize-html'; import mongoose from 'mongoose'; import rateLimit from 'express-rate-limit'; -import { config } from '../../config/config'; +import { configOld } from '../../config/config'; import forumThread from '../../models/forumThread'; import forumThreadComment from '../../models/forumThreadComment'; import forumThreadCommentReply from '../../models/forumThreadCommentReply'; @@ -40,7 +40,7 @@ const sanitizeHtmlAllowedAttributesForumThread = { }; const newReplyLimiter = - config.getEnv() === 'local' + configOld.getEnv() === 'local' ? rateLimit({ max: 0, // Disable if we are local }) diff --git a/src/routes/forum/forumThreadCommentRoutes.js b/src/routes/forum/forumThreadCommentRoutes.js index 03c8fd554..f1c3c4a63 100644 --- a/src/routes/forum/forumThreadCommentRoutes.js +++ b/src/routes/forum/forumThreadCommentRoutes.js @@ -12,12 +12,12 @@ import { allowedHtmlAttributes, allowedHtmlTags } from './sanitizeRestrictions'; import { createNotification } from '../../myFunctions/createNotification'; import REWARDS from '../../rewards/constants'; import { userHasReward } from '../../rewards/getRewards'; -import { config } from '../../config/config'; +import { configOld } from '../../config/config'; const router = new Router(); const newCommentLimiter = - config.getEnv() === 'local' + configOld.getEnv() === 'local' ? rateLimit({ max: 0, // Disable if we are local }) diff --git a/src/routes/forum/forumThreadRoutes.js b/src/routes/forum/forumThreadRoutes.js index e9753a88b..9aad774f9 100644 --- a/src/routes/forum/forumThreadRoutes.js +++ b/src/routes/forum/forumThreadRoutes.js @@ -2,7 +2,7 @@ import { Router } from 'express'; import sanitizeHtml from 'sanitize-html'; import rateLimit from 'express-rate-limit'; -import { config } from '../../config/config'; +import { configOld } from '../../config/config'; import { checkForumThreadOwnership, asyncMiddleware } from '../middleware'; import getTimeDiffInString from '../../util/getTimeDiffInString'; import lastIds from '../../models/lastIds'; @@ -130,7 +130,7 @@ lastIds.findOne({}).exec(async (err, returnedLastId) => { }); const newForumLimiter = - config.getEnv() === 'local' + configOld.getEnv() === 'local' ? rateLimit({ max: 0, // Disable if we are local }) diff --git a/src/routes/index.js b/src/routes/index.js index eb553fb6b..49e21d761 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -12,7 +12,7 @@ import statsCumulative from '../models/statsCumulative'; import { emailExists, validEmail } from '../routes/emailVerification'; import { sendEmailVerification } from '../myFunctions/sendEmailVerification'; -import { config } from '../config/config'; +import { configOld } from '../config/config'; import { disallowVPNs } from '../util/vpnDetection'; import { settingsSingleton } from '../settings'; import { Alliance } from '../gameplay/types'; @@ -32,11 +32,11 @@ router.get('/', (req, res) => { // register route router.get('/register', (req, res) => { - res.render('register', { platform: config.getEnv() }); + res.render('register', { platform: configOld.getEnv() }); }); const registerLimiter = - config.getEnv() === 'local' + configOld.getEnv() === 'local' ? rateLimit({ max: 0, // Disable if we are local }) @@ -99,7 +99,7 @@ router.post( passport.authenticate('local')(req, res, () => { res.redirect('/lobby'); }); - if (config.getEnv() === 'prod') { + if (configOld.getEnv() === 'prod') { sendEmailVerification(user, req.body.emailAddress); } else { user.emailVerified = true; @@ -113,7 +113,7 @@ router.post( ); const loginLimiter = - config.getEnv() === 'local' + configOld.getEnv() === 'local' ? rateLimit({ max: 0, // Disable if we are local }) @@ -237,7 +237,7 @@ router.get('/statistics', (req, res) => { }); router.get('/resetPassword', (req, res) => { - res.render('resetPassword', { platform: config.getEnv() }); + res.render('resetPassword', { platform: configOld.getEnv() }); }); router.post( diff --git a/src/routes/middleware.ts b/src/routes/middleware.ts index 8e60ba15e..58c14f8bb 100644 --- a/src/routes/middleware.ts +++ b/src/routes/middleware.ts @@ -8,7 +8,7 @@ import { isMod } from '../modsadmins/mods'; import { isAdmin } from '../modsadmins/admins'; import { RequestHandler } from 'express'; -import { config } from '../config/config'; +import { configOld } from '../config/config'; // return a function that wraps an async middleware export const asyncMiddleware = @@ -222,7 +222,7 @@ export const isAdminMiddleware = (req, res, next) => { }; export const emailVerified = (req, res, next) => { - if (req.user.emailVerified === true || config.getEnv() != 'prod') { + if (req.user.emailVerified === true || configOld.getEnv() != 'prod') { next(); } else { res.redirect('/emailVerification'); diff --git a/src/routes/mod.js b/src/routes/mod.js index 60be57d0e..260092076 100644 --- a/src/routes/mod.js +++ b/src/routes/mod.js @@ -19,7 +19,7 @@ import ModLogComponent from '../views/components/mod/mod_log'; import ReportLog from '../views/components/mod/report'; import { MongoClient } from 'mongodb'; import { SESSIONS_COLLECTION_NAME } from '../constants'; -import { config } from '../config/config'; +import { configOld } from '../config/config'; const router = new Router(); @@ -187,7 +187,7 @@ router.post('/ban', isModMiddleware, async (req, res) => { }); // Delete all the sessions associated with this username - const dbResult = await MongoClient.connect(config.getDatabaseUrl()); + const dbResult = await MongoClient.connect(configOld.getDatabaseUrl()); const mySessions = dbResult.db().collection(SESSIONS_COLLECTION_NAME); const deleteResult = await mySessions.deleteMany({ 'session.usernameLower': banPlayerUsername.toLowerCase(), diff --git a/src/sockets/commands/admin/acreatetestaccounts.ts b/src/sockets/commands/admin/acreatetestaccounts.ts index c14f0e244..d332b5d37 100644 --- a/src/sockets/commands/admin/acreatetestaccounts.ts +++ b/src/sockets/commands/admin/acreatetestaccounts.ts @@ -2,13 +2,13 @@ import { sendReplyToCommand } from '../../sockets'; import { SocketUser } from '../../types'; import User from '../../../models/user'; import { Command } from '../types'; -import { config } from '../../../config/config'; +import { configOld } from '../../../config/config'; export const acreatetestaccounts: Command = { command: 'acreatetestaccounts', help: '/acreatetestaccounts: Creates test accounts: 1 to 10. Passwords are the username.', run: async (args: string[], socket: SocketUser) => { - if (config.getEnv() === 'prod') { + if (configOld.getEnv() === 'prod') { sendReplyToCommand(socket, 'Cannot create test accounts in prod.'); return; } diff --git a/src/sockets/commands/admin/asessions.ts b/src/sockets/commands/admin/asessions.ts index 253e355e2..0682373dc 100644 --- a/src/sockets/commands/admin/asessions.ts +++ b/src/sockets/commands/admin/asessions.ts @@ -2,7 +2,7 @@ import { sendReplyToCommand } from '../../sockets'; import { SocketUser } from '../../types'; import { Command } from '../types'; import { MongoClient } from 'mongodb'; -import { config } from '../../../config/config'; +import { configOld } from '../../../config/config'; export const asessions: Command = { command: 'asessions', @@ -15,7 +15,7 @@ export const asessions: Command = { return; } - const dbResult = await MongoClient.connect(config.getDatabaseUrl()); + const dbResult = await MongoClient.connect(configOld.getDatabaseUrl()); const mySessions = dbResult.db().collection('mySessions'); const entries = mySessions.find({ 'session.usernameLower': username }); diff --git a/src/sockets/sockets.ts b/src/sockets/sockets.ts index 7d9d522eb..2f001c143 100644 --- a/src/sockets/sockets.ts +++ b/src/sockets/sockets.ts @@ -46,7 +46,7 @@ import { Card } from '../gameplay/cards/types'; import { TOCommandsImported } from './commands/tournamentOrganisers'; import { PatreonAgent } from '../clients/patreon/patreonAgent'; import { PatreonController } from '../clients/patreon/patreonController'; -import { config } from '../config/config'; +import { configOld } from '../config/config'; const chatSpamFilter = new ChatSpamFilter(); const createRoomFilter = new CreateRoomFilter(); @@ -55,7 +55,7 @@ const matchmakingQueue = new MatchmakingQueue(matchFound); const joinQueueFilter = new JoinQueueFilter(() => new Date()); const readyPrompt = new ReadyPrompt(); -if (config.getNodeEnv() !== 'test') { +if (configOld.getNodeEnv() !== 'test') { setInterval(() => { chatSpamFilter.tick(); }, 1000); @@ -149,7 +149,7 @@ function deleteSaveGameFromDb(room) { } } -if (config.getNodeEnv() !== 'test') { +if (configOld.getNodeEnv() !== 'test') { setTimeout(async () => { let run = true; let i = 0; @@ -1955,7 +1955,7 @@ function joinQueue(): boolean { return false; } - if (config.getEnv() !== 'local') { + if (configOld.getEnv() !== 'local') { if (this.request.user.totalGamesPlayed < 3) { this.emit('allChatToClient', { message: 'You require 3 games to join the ranked queue.', diff --git a/src/util/captcha.ts b/src/util/captcha.ts index a9ec1cbd4..65cb0dc0d 100644 --- a/src/util/captcha.ts +++ b/src/util/captcha.ts @@ -1,9 +1,9 @@ import { RequestHandler } from 'express'; import axios from 'axios'; -import { config } from '../config/config'; +import { configOld } from '../config/config'; export const captchaMiddleware: RequestHandler = async (req, res, next) => { - if (config.getEnv() !== 'prod') { + if (configOld.getEnv() !== 'prod') { return next(); } @@ -19,7 +19,7 @@ export const captchaMiddleware: RequestHandler = async (req, res, next) => { return; } - const secretKey = config.getGoogleCaptchaKey(); + const secretKey = configOld.getGoogleCaptchaKey(); const verifyUrl = `https://google.com/recaptcha/api/siteverify?secret=${secretKey}&response=${req.body.captcha}&remoteip=${req.connection.remoteAddress}`; const response = await axios.post(verifyUrl); diff --git a/src/util/disposableEmails.js b/src/util/disposableEmails.js index 466ec8a0d..5b519df6d 100644 --- a/src/util/disposableEmails.js +++ b/src/util/disposableEmails.js @@ -7461,7 +7461,7 @@ export default [ 'gamesportal.me', 'gamestips.ru', 'gamgling.com', - 'gamno.config.work', + 'gamno.configOld.work', 'gamora274ey.cf', 'gamora274ey.ga', 'gamora274ey.gq', diff --git a/src/util/vpnDetection.ts b/src/util/vpnDetection.ts index 9d69ed69f..9c4ae3159 100644 --- a/src/util/vpnDetection.ts +++ b/src/util/vpnDetection.ts @@ -1,12 +1,12 @@ import { RequestHandler } from 'express'; -import { config } from '../config/config'; +import { configOld } from '../config/config'; const VPN_TIMEOUT = 1000 * 60 * 60 * 12; // 12 hours // TODO-kev: check if this still works let whitelistedUsernames: string[] = []; -if (config.getWhitelistedVpnUsernames()) { - whitelistedUsernames = config.getWhitelistedVpnUsernames().split(','); +if (configOld.getWhitelistedVpnUsernames()) { + whitelistedUsernames = configOld.getWhitelistedVpnUsernames().split(','); } class VpnEntry { @@ -84,7 +84,7 @@ const isVPN = async (ip: string): Promise => { const isVpnCheck1 = async (ip: string): Promise => { const vpnResponse = await fetch( - `https://vpnapi.io/api/${ip}?key=${config.getVpnDetectionToken()}`, + `https://vpnapi.io/api/${ip}?key=${configOld.getVpnDetectionToken()}`, ); const data = await vpnResponse.json(); @@ -101,7 +101,7 @@ const isVpnCheck1 = async (ip: string): Promise => { const isVpnCheck2 = async (ip: string): Promise => { const vpnResponse = await fetch( - `https://check.getipintel.net/check.php?ip=${ip}&contact=${config.getProAvalonEmailAddress()}&flags=m`, + `https://check.getipintel.net/check.php?ip=${ip}&contact=${configOld.getProAvalonEmailAddress()}&flags=m`, ); const data = await vpnResponse.json(); @@ -118,7 +118,7 @@ const isVpnCheck2 = async (ip: string): Promise => { }; export const disallowVPNs: RequestHandler = (req, res, next) => { - if (config.getEnv() === 'local') { + if (configOld.getEnv() === 'local') { next(); return; } From c8ad6ab360719839e60b0ab1542bcf2c0d462a01 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 14:43:42 +1000 Subject: [PATCH 18/43] Extracted patreon config variables --- src/clients/patreon/patreonController.ts | 10 +++++----- src/config/patreonConfig.ts | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/clients/patreon/patreonController.ts b/src/clients/patreon/patreonController.ts index 8d57d8d6d..821c26438 100644 --- a/src/clients/patreon/patreonController.ts +++ b/src/clients/patreon/patreonController.ts @@ -3,8 +3,8 @@ import { PatreonUserTokens, PaidPatronFullDetails, } from './patreonAgent'; -import uuid from 'uuid'; -import { configOld } from '../../config/config'; +import uuid from 'uuid';dd . +import { config } from '../../config/config'; const PATREON_URLS = { AUTHORIZATION_LINK: 'https://www.patreon.com/oauth2/authorize', @@ -13,9 +13,9 @@ const PATREON_URLS = { }; export class PatreonController implements IPatreonController { - private clientId = configOld.getPatreonClientId(); - private clientSecret = configOld.getPatreonClientSecret(); - private redirectUri = configOld.getPatreonRedirectUrl(); + private clientId = config.patreon.clientId; + private clientSecret = config.patreon.clientSecret; + private redirectUri = config.patreon.redirectUrl; public async getPatreonUserTokens(code: string): Promise { const getPatreonUserTokensUrl = new URL(PATREON_URLS.GET_TOKENS); diff --git a/src/config/patreonConfig.ts b/src/config/patreonConfig.ts index d42ce163f..51fc06db5 100644 --- a/src/config/patreonConfig.ts +++ b/src/config/patreonConfig.ts @@ -1,11 +1,11 @@ export type PatreonConfigType = { - patreonClientId: string; - patreonClientSecret: string; - patreonRedirectUrl: string; + clientId: string; + clientSecret: string; + redirectUrl: string; }; export const PatreonConfig: Readonly = Object.freeze({ - patreonClientId: process.env.patreon_client_ID, - patreonClientSecret: process.env.patreon_client_secret, - patreonRedirectUrl: process.env.patreon_redirectURL, + clientId: process.env.patreon_client_ID, + clientSecret: process.env.patreon_client_secret, + redirectUrl: process.env.patreon_redirectURL, }); From 226bcdd9e4ba3c99ae788095aded2657119d5fc4 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 14:44:32 +1000 Subject: [PATCH 19/43] Minor fix --- src/clients/patreon/patreonController.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clients/patreon/patreonController.ts b/src/clients/patreon/patreonController.ts index 821c26438..2e7add4f5 100644 --- a/src/clients/patreon/patreonController.ts +++ b/src/clients/patreon/patreonController.ts @@ -3,7 +3,7 @@ import { PatreonUserTokens, PaidPatronFullDetails, } from './patreonAgent'; -import uuid from 'uuid';dd . +import uuid from 'uuid'; import { config } from '../../config/config'; const PATREON_URLS = { From 60264e521ca3fa0a343dd5b22a8c132df194701e Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 14:45:37 +1000 Subject: [PATCH 20/43] Removed patreon variables from old config --- src/clients/patreon/patreonController.ts | 5 +++-- src/config/config.ts | 17 ----------------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/src/clients/patreon/patreonController.ts b/src/clients/patreon/patreonController.ts index 2e7add4f5..461b1e148 100644 --- a/src/clients/patreon/patreonController.ts +++ b/src/clients/patreon/patreonController.ts @@ -1,10 +1,11 @@ +import uuid from 'uuid'; + +import { config } from '../../config/config'; import { IPatreonController, PatreonUserTokens, PaidPatronFullDetails, } from './patreonAgent'; -import uuid from 'uuid'; -import { config } from '../../config/config'; const PATREON_URLS = { AUTHORIZATION_LINK: 'https://www.patreon.com/oauth2/authorize', diff --git a/src/config/config.ts b/src/config/config.ts index 3ec109bb6..6df0a7ca7 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -29,11 +29,6 @@ class Config { private readonly s3Region: string = process.env.S3_REGION; private readonly s3Endpoint: string = process.env.S3_ENDPOINT; - private readonly patreonClientId: string = process.env.patreon_client_ID; - private readonly patreonClientSecret: string = - process.env.patreon_client_secret; - private readonly patreonRedirectUrl: string = process.env.patreon_redirectURL; - private readonly discordBotToken: string = process.env.discord_bot_token; private readonly discordAdminChannelId: string = process.env.discord_admin_channel_id; @@ -135,18 +130,6 @@ class Config { return this.s3Endpoint; } - public getPatreonClientId() { - return this.patreonClientId; - } - - public getPatreonClientSecret() { - return this.patreonClientSecret; - } - - public getPatreonRedirectUrl() { - return this.patreonRedirectUrl; - } - public getDiscordBotToken() { return this.discordBotToken; } From f620ce8f43df0ad5d2a7556bfd07678cce3a546e Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 14:52:55 +1000 Subject: [PATCH 21/43] Extracted Discord config --- src/clients/discord/index.ts | 13 +++++++------ src/config/config.ts | 32 +++----------------------------- src/config/discord.ts | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 35 deletions(-) create mode 100644 src/config/discord.ts diff --git a/src/clients/discord/index.ts b/src/clients/discord/index.ts index f7afcf548..f72c4449a 100644 --- a/src/clients/discord/index.ts +++ b/src/clients/discord/index.ts @@ -1,24 +1,25 @@ import Discord, { TextChannel } from 'discord.js'; -import { configOld } from '../../config/config'; + +import { config, configOld } from '../../config/config'; const client = new Discord.Client(); if (configOld.getEnv() === 'prod') { - client.login(configOld.getDiscordBotToken()); + client.login(config.discord.botToken); } export function sendToDiscordAdmins(message: string, ping?: boolean): void { if (ping) { message = `${getAdminPing()} ${message}`; } - sendToChannel(message, configOld.getDiscordAdminChannelId()); + sendToChannel(message, config.discord.adminChannelId); } export function sendToDiscordMods(message: string, ping?: boolean): void { if (ping) { message = `${getModPing()} ${message}`; } - sendToChannel(message, configOld.getDiscordModChannelId()); + sendToChannel(message, config.discord.modChannelId); } function sendToChannel(message: string, channelId: string): void { @@ -30,9 +31,9 @@ function sendToChannel(message: string, channelId: string): void { } function getAdminPing(): string { - return `<@&${configOld.getDiscordAdminRoleId()}>`; + return `<@&${config.discord.adminRoleId}>`; } function getModPing(): string { - return `<@&${configOld.getDiscordModRoleId()}>`; + return `<@&${config.discord.modRoleId}>`; } diff --git a/src/config/config.ts b/src/config/config.ts index 6df0a7ca7..d8bccb829 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -1,4 +1,5 @@ import { PatreonConfig, PatreonConfigType } from './patreonConfig'; +import { DiscordConfig, DiscordConfigType } from './discord'; const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); @@ -29,15 +30,6 @@ class Config { private readonly s3Region: string = process.env.S3_REGION; private readonly s3Endpoint: string = process.env.S3_ENDPOINT; - private readonly discordBotToken: string = process.env.discord_bot_token; - private readonly discordAdminChannelId: string = - process.env.discord_admin_channel_id; - private readonly discordModChannelId: string = - process.env.discord_mod_channel_id; - private readonly discordAdminRoleId: string = - process.env.discord_admin_role_id; - private readonly discordModRoleId: string = process.env.discord_mod_role_id; - constructor() { // Run validation checks outside test environment if (this.nodeEnv !== 'test') { @@ -129,34 +121,16 @@ class Config { public getS3Endpoint() { return this.s3Endpoint; } - - public getDiscordBotToken() { - return this.discordBotToken; - } - - public getDiscordAdminChannelId() { - return this.discordAdminChannelId; - } - - public getDiscordModChannelId() { - return this.discordModChannelId; - } - - public getDiscordAdminRoleId() { - return this.discordAdminRoleId; - } - - public getDiscordModRoleId() { - return this.discordModRoleId; - } } type ConfigNew = { patreon: PatreonConfigType; + discord: DiscordConfigType; }; export const config: Readonly = Object.freeze({ patreon: PatreonConfig, + discord: DiscordConfig, }); export const configOld = new Config(); diff --git a/src/config/discord.ts b/src/config/discord.ts new file mode 100644 index 000000000..3a03079f3 --- /dev/null +++ b/src/config/discord.ts @@ -0,0 +1,15 @@ +export type DiscordConfigType = { + botToken: string; + adminChannelId: string; + modChannelId: string; + adminRoleId: string; + modRoleId: string; +}; + +export const DiscordConfig: Readonly = Object.freeze({ + botToken: process.env.discord_bot_token, + adminChannelId: process.env.discord_admin_channel_id, + modChannelId: process.env.discord_mod_channel_id, + adminRoleId: process.env.discord_admin_role_id, + modRoleId: process.env.discord_mod_role_id, +}); From 8836209f7a1ecef14dff99b5776d3af1f98786f1 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 15:13:48 +1000 Subject: [PATCH 22/43] Extracted s3 config variables --- src/clients/s3/S3Controller.ts | 11 ++++----- src/config/config.ts | 41 +++++----------------------------- src/config/s3Config.ts | 34 ++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 41 deletions(-) create mode 100644 src/config/s3Config.ts diff --git a/src/clients/s3/S3Controller.ts b/src/clients/s3/S3Controller.ts index 5934178ea..e5ea60994 100644 --- a/src/clients/s3/S3Controller.ts +++ b/src/clients/s3/S3Controller.ts @@ -7,8 +7,9 @@ import { PutObjectCommand, S3Client, } from '@aws-sdk/client-s3'; + +import { config } from '../../config/config'; import { IS3Controller } from './S3Agent'; -import { configOld } from '../../config/config'; export default class S3Controller implements IS3Controller { private client: S3Client; @@ -16,12 +17,12 @@ export default class S3Controller implements IS3Controller { private bucket: string; constructor() { - this.publicFileLinkPrefix = configOld.getS3PublicFileLinkPrefix(); - this.bucket = configOld.getS3BucketName(); + this.publicFileLinkPrefix = config.s3.publicFileLinkPrefix; + this.bucket = config.s3.bucketName; this.client = new S3Client({ - region: configOld.getS3Region(), - endpoint: configOld.getS3Endpoint(), + region: config.s3.region, + endpoint: config.s3.endpoint, credentials: fromEnv(), }); } diff --git a/src/config/config.ts b/src/config/config.ts index d8bccb829..5909a2c01 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -1,5 +1,6 @@ import { PatreonConfig, PatreonConfigType } from './patreonConfig'; import { DiscordConfig, DiscordConfigType } from './discord'; +import { S3Config, S3ConfigType } from './s3Config'; const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); @@ -24,12 +25,6 @@ class Config { process.env.MY_SECRET_GOOGLE_CAPTCHA_KEY; private readonly databaseUrl: string = process.env.DATABASEURL; - private readonly s3PublicFileLinkPrefix: string = - process.env.S3_PUBLIC_FILE_LINK_PREFIX; - private readonly s3BucketName: string = process.env.S3_BUCKET_NAME; - private readonly s3Region: string = process.env.S3_REGION; - private readonly s3Endpoint: string = process.env.S3_ENDPOINT; - constructor() { // Run validation checks outside test environment if (this.nodeEnv !== 'test') { @@ -39,18 +34,6 @@ class Config { throw new Error(`Invalid settings: ENV=${process.env.ENV}`); process.exit(1); } - - if (this.env === 'staging' && this.s3BucketName !== 'proavalon-staging') { - throw new Error( - `Invalid settings: ENV=staging S3_BUCKET_NAME=${process.env.S3_BUCKET_NAME}`, - ); - } - - if (this.env === 'prod' && this.s3BucketName !== 'proavalon') { - throw new Error( - `Invalid settings: ENV=prod S3_BUCKET_NAME=${process.env.S3_BUCKET_NAME}`, - ); - } } } @@ -105,32 +88,18 @@ class Config { public getDatabaseUrl() { return this.databaseUrl; } - - public getS3PublicFileLinkPrefix() { - return this.s3PublicFileLinkPrefix; - } - - public getS3BucketName() { - return this.s3BucketName; - } - - public getS3Region() { - return this.s3Region; - } - - public getS3Endpoint() { - return this.s3Endpoint; - } } type ConfigNew = { - patreon: PatreonConfigType; discord: DiscordConfigType; + patreon: PatreonConfigType; + s3: S3ConfigType; }; export const config: Readonly = Object.freeze({ - patreon: PatreonConfig, discord: DiscordConfig, + patreon: PatreonConfig, + s3: S3Config, }); export const configOld = new Config(); diff --git a/src/config/s3Config.ts b/src/config/s3Config.ts new file mode 100644 index 000000000..3fba97235 --- /dev/null +++ b/src/config/s3Config.ts @@ -0,0 +1,34 @@ +export type S3ConfigType = { + publicFileLinkPrefix: string; + bucketName: string; + region: string; + endpoint: string; +}; + +export const S3Config: Readonly = Object.freeze({ + publicFileLinkPrefix: process.env.S3_PUBLIC_FILE_LINK_PREFIX, + bucketName: validateBucketName(), + region: process.env.S3_REGION, + endpoint: process.env.S3_ENDPOINT, +}); + +function validateBucketName() { + const { NODE_ENV, ENV, S3_BUCKET_NAME } = process.env; + + if (NODE_ENV !== 'test') { + const expectedBucketNames: { [key: string]: string } = { + prod: `proavalon`, + staging: `proavalon-staging`, + }; + + const expectedBucketName = expectedBucketNames[ENV]; + + if (expectedBucketName && S3_BUCKET_NAME !== expectedBucketName) { + throw new Error( + `Invalid env variables: ENV=${ENV} S3_BUCKET_NAME=${S3_BUCKET_NAME}`, + ); + } + } + + return S3_BUCKET_NAME; +} From 4063b3a722502280b731dbe6cb3eaa50095e1c7c Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 15:19:50 +1000 Subject: [PATCH 23/43] Extracted email variables --- src/config/config.ts | 21 +++------------------ src/config/emailConfig.ts | 11 +++++++++++ src/myFunctions/sendEmail.ts | 9 +++++---- src/util/vpnDetection.ts | 4 ++-- 4 files changed, 21 insertions(+), 24 deletions(-) create mode 100644 src/config/emailConfig.ts diff --git a/src/config/config.ts b/src/config/config.ts index 5909a2c01..86923d4aa 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -1,6 +1,7 @@ import { PatreonConfig, PatreonConfigType } from './patreonConfig'; import { DiscordConfig, DiscordConfigType } from './discord'; import { S3Config, S3ConfigType } from './s3Config'; +import { EmailConfig, EmailConfigType } from './emailConfig'; const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); @@ -12,12 +13,6 @@ class Config { private readonly ip: string = process.env.IP; private readonly mySecretKey: string = process.env.MY_SECRET_KEY; - private readonly proAvalonEmailAddressDomain: string = - process.env.PROAVALON_EMAIL_ADDRESS_DOMAIN; - private readonly proAvalonEmailAddress: string = - process.env.PROAVALON_EMAIL_ADDRESS; - private readonly mailgunApiKey: string = process.env.MAILGUN_API_KEY; - private readonly vpnDetectionToken: string = process.env.VPN_DETECTION_TOKEN; private readonly whitelistedVpnUsernames: string = process.env.WHITELISTED_VPN_USERNAMES; @@ -61,18 +56,6 @@ class Config { return this.mySecretKey; } - public getProAvalonEmailAddress() { - return this.proAvalonEmailAddress; - } - - public getProAvalonEmailAddressDomain() { - return this.proAvalonEmailAddressDomain; - } - - public getMailgunApiKey() { - return this.mailgunApiKey; - } - public getVpnDetectionToken() { return this.vpnDetectionToken; } @@ -92,12 +75,14 @@ class Config { type ConfigNew = { discord: DiscordConfigType; + email: EmailConfigType; patreon: PatreonConfigType; s3: S3ConfigType; }; export const config: Readonly = Object.freeze({ discord: DiscordConfig, + email: EmailConfig, patreon: PatreonConfig, s3: S3Config, }); diff --git a/src/config/emailConfig.ts b/src/config/emailConfig.ts new file mode 100644 index 000000000..1845d99ca --- /dev/null +++ b/src/config/emailConfig.ts @@ -0,0 +1,11 @@ +export type EmailConfigType = { + proAvalonEmailAddressDomain: string; + proAvalonEmailAddress: string; + mailgunApiKey: string; +}; + +export const EmailConfig: Readonly = Object.freeze({ + proAvalonEmailAddressDomain: process.env.PROAVALON_EMAIL_ADDRESS_DOMAIN, + proAvalonEmailAddress: process.env.PROAVALON_EMAIL_ADDRESS, + mailgunApiKey: process.env.MAILGUN_API_KEY, +}); diff --git a/src/myFunctions/sendEmail.ts b/src/myFunctions/sendEmail.ts index e538e2bba..0917eec8f 100644 --- a/src/myFunctions/sendEmail.ts +++ b/src/myFunctions/sendEmail.ts @@ -1,9 +1,10 @@ import Mailgun from 'mailgun.js'; import formData from 'form-data'; -import { configOld } from '../config/config'; -const api_key = configOld.getMailgunApiKey(); -const domain = configOld.getProAvalonEmailAddressDomain(); +import { config } from '../config/config'; + +const api_key = config.email.mailgunApiKey; +const domain = config.email.proAvalonEmailAddressDomain; const mailgun = new Mailgun(formData); const mg = mailgun.client({ username: 'api', key: api_key }); @@ -14,7 +15,7 @@ export const sendEmail = ( messageHtml: string, ) => { const data = { - from: 'ProAvalon <' + configOld.getProAvalonEmailAddress() + '>', + from: 'ProAvalon <' + config.email.proAvalonEmailAddress + '>', to: recipientEmail, subject: subject, html: messageHtml, diff --git a/src/util/vpnDetection.ts b/src/util/vpnDetection.ts index 9c4ae3159..ab0009f10 100644 --- a/src/util/vpnDetection.ts +++ b/src/util/vpnDetection.ts @@ -1,5 +1,5 @@ import { RequestHandler } from 'express'; -import { configOld } from '../config/config'; +import { config, configOld } from '../config/config'; const VPN_TIMEOUT = 1000 * 60 * 60 * 12; // 12 hours @@ -101,7 +101,7 @@ const isVpnCheck1 = async (ip: string): Promise => { const isVpnCheck2 = async (ip: string): Promise => { const vpnResponse = await fetch( - `https://check.getipintel.net/check.php?ip=${ip}&contact=${configOld.getProAvalonEmailAddress()}&flags=m`, + `https://check.getipintel.net/check.php?ip=${ip}&contact=${config.email.proAvalonEmailAddress}&flags=m`, ); const data = await vpnResponse.json(); From 605a6cd1a57a5f3ceabfcd4aee3a450b9a66d9b2 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 15:28:20 +1000 Subject: [PATCH 24/43] Extracted nodeEnv --- src/config/config.ts | 11 +++++------ src/gameplay/game.ts | 4 ++-- src/sockets/sockets.ts | 6 +++--- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/config/config.ts b/src/config/config.ts index 86923d4aa..288bb6d0d 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -7,7 +7,6 @@ const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); class Config { private readonly env: string = process.env.ENV; - private readonly nodeEnv: string = process.env.NODE_ENV; private readonly serverDomain: string = process.env.SERVER_DOMAIN; private readonly port: string = process.env.PORT; private readonly ip: string = process.env.IP; @@ -22,7 +21,7 @@ class Config { constructor() { // Run validation checks outside test environment - if (this.nodeEnv !== 'test') { + if (process.env.NODE_ENV !== 'test') { if (!VALID_ENVIRONMENTS.has(this.env)) { // TODO-kev: Prefer the console.error then process exit or throw an error? console.error(`Bad environment variable given: ${process.env.ENV}`); @@ -36,10 +35,6 @@ class Config { return this.env; } - public getNodeEnv() { - return this.nodeEnv; - } - public getServerDomain() { return this.serverDomain; } @@ -74,6 +69,8 @@ class Config { } type ConfigNew = { + nodeEnv: string; + discord: DiscordConfigType; email: EmailConfigType; patreon: PatreonConfigType; @@ -81,6 +78,8 @@ type ConfigNew = { }; export const config: Readonly = Object.freeze({ + nodeEnv: process.env.NODE_ENV, + discord: DiscordConfig, email: EmailConfig, patreon: PatreonConfig, diff --git a/src/gameplay/game.ts b/src/gameplay/game.ts index 56adafe53..ec70c2edb 100644 --- a/src/gameplay/game.ts +++ b/src/gameplay/game.ts @@ -1,6 +1,7 @@ // @ts-nocheck import _ from 'lodash'; +import { config } from '../config/config'; import Room, { RoomConfig } from './room'; import usernamesIndexes from '../myFunctions/usernamesIndexes'; import User from '../models/user'; @@ -32,7 +33,6 @@ import { millisToStr } from '../util/time'; import shuffleArray from '../util/shuffleArray'; import { Anonymizer } from './anonymizer'; import { sendReplyToCommand } from '../sockets/sockets'; -import { configOld } from '../config/config'; export const WAITING = 'Waiting'; export const MIN_PLAYERS = 5; @@ -1562,7 +1562,7 @@ class Game extends Room { }); } - if (configOld.getNodeEnv() !== 'test') { + if (config.nodeEnv !== 'test') { this.playersInGame.forEach((player) => { User.findById(player.userId) .populate('notifications') diff --git a/src/sockets/sockets.ts b/src/sockets/sockets.ts index 2f001c143..51ebcdc2a 100644 --- a/src/sockets/sockets.ts +++ b/src/sockets/sockets.ts @@ -46,7 +46,7 @@ import { Card } from '../gameplay/cards/types'; import { TOCommandsImported } from './commands/tournamentOrganisers'; import { PatreonAgent } from '../clients/patreon/patreonAgent'; import { PatreonController } from '../clients/patreon/patreonController'; -import { configOld } from '../config/config'; +import { config, configOld } from '../config/config'; const chatSpamFilter = new ChatSpamFilter(); const createRoomFilter = new CreateRoomFilter(); @@ -55,7 +55,7 @@ const matchmakingQueue = new MatchmakingQueue(matchFound); const joinQueueFilter = new JoinQueueFilter(() => new Date()); const readyPrompt = new ReadyPrompt(); -if (configOld.getNodeEnv() !== 'test') { +if (config.nodeEnv !== 'test') { setInterval(() => { chatSpamFilter.tick(); }, 1000); @@ -149,7 +149,7 @@ function deleteSaveGameFromDb(room) { } } -if (configOld.getNodeEnv() !== 'test') { +if (config.nodeEnv !== 'test') { setTimeout(async () => { let run = true; let i = 0; From 00070247f198f34e0649da37fd74535bcfaf5d4b Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 15:34:25 +1000 Subject: [PATCH 25/43] Extracted general config variables --- src/app.ts | 8 +++---- src/config/config.ts | 28 +++++++----------------- src/myFunctions/sendEmailVerification.ts | 7 +++--- src/myFunctions/sendResetPassword.ts | 6 ++--- 4 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/app.ts b/src/app.ts index 8f7c5527e..2730d5005 100644 --- a/src/app.ts +++ b/src/app.ts @@ -20,7 +20,7 @@ import socket, { Server as SocketServer } from 'socket.io'; import createProxyMiddleware from 'http-proxy-middleware'; import morgan from 'morgan'; -import { configOld } from './config/config'; +import { config, configOld } from './config/config'; import { server as socketServer } from './sockets/sockets'; import User from './models/user'; import { emailVerified, isLoggedIn } from './routes/middleware'; @@ -83,7 +83,7 @@ if (configOld.getEnv() === 'local') { ); } -const port = configOld.getPort() || 3000; +const port = config.port || 3000; const dbLoc = configOld.getDatabaseUrl(); console.log(`Using database url: ${dbLoc}`); @@ -130,7 +130,7 @@ process }); // authentication -const secretKey = configOld.getMySecretKey() || 'MySecretKey'; +const secretKey = config.mySecretKey || 'MySecretKey'; app.use( session({ secret: secretKey, @@ -183,7 +183,7 @@ app.use('/lobby', lobbyRoutes); app.use('/forum', forumRoutes); app.use('/profile', profileRoutes); -const IP = configOld.getIp() || '127.0.0.1'; +const IP = config.ip || '127.0.0.1'; const server = app.listen(port, () => { console.log(`Server has started on ${IP}:${port}!`); }); diff --git a/src/config/config.ts b/src/config/config.ts index 288bb6d0d..23ba14d80 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -7,10 +7,6 @@ const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); class Config { private readonly env: string = process.env.ENV; - private readonly serverDomain: string = process.env.SERVER_DOMAIN; - private readonly port: string = process.env.PORT; - private readonly ip: string = process.env.IP; - private readonly mySecretKey: string = process.env.MY_SECRET_KEY; private readonly vpnDetectionToken: string = process.env.VPN_DETECTION_TOKEN; private readonly whitelistedVpnUsernames: string = @@ -35,22 +31,6 @@ class Config { return this.env; } - public getServerDomain() { - return this.serverDomain; - } - - public getPort() { - return this.port; - } - - public getIp() { - return this.ip; - } - - public getMySecretKey() { - return this.mySecretKey; - } - public getVpnDetectionToken() { return this.vpnDetectionToken; } @@ -70,6 +50,10 @@ class Config { type ConfigNew = { nodeEnv: string; + serverDomain: string; + port: string; + ip: string; + mySecretKey: string; discord: DiscordConfigType; email: EmailConfigType; @@ -79,6 +63,10 @@ type ConfigNew = { export const config: Readonly = Object.freeze({ nodeEnv: process.env.NODE_ENV, + serverDomain: process.env.SERVER_DOMAIN, + port: process.env.PORT, + ip: process.env.IP, + mySecretKey: process.env.MY_SECRET_KEY, discord: DiscordConfig, email: EmailConfig, diff --git a/src/myFunctions/sendEmailVerification.ts b/src/myFunctions/sendEmailVerification.ts index 4af720410..2c57ce25b 100644 --- a/src/myFunctions/sendEmailVerification.ts +++ b/src/myFunctions/sendEmailVerification.ts @@ -1,11 +1,12 @@ import ejs from 'ejs'; -import emailTemplateEmailVerification from './emailTemplateEmailVerification'; import uuid from 'uuid'; + +import { config } from '../config/config'; +import emailTemplateEmailVerification from './emailTemplateEmailVerification'; import disposableEmails from '../util/disposableEmails.js'; import { sendEmail } from './sendEmail'; -import { configOld } from '../config/config'; -const serverDomain = configOld.getServerDomain(); +const serverDomain = config.serverDomain; const uuidv4 = uuid.v4; diff --git a/src/myFunctions/sendResetPassword.ts b/src/myFunctions/sendResetPassword.ts index 97340baf6..be14882e5 100644 --- a/src/myFunctions/sendResetPassword.ts +++ b/src/myFunctions/sendResetPassword.ts @@ -1,12 +1,12 @@ import uuid from 'uuid'; import ejs from 'ejs'; + +import { config } from '../config/config'; import emailTemplateResetPassword from './emailTemplateResetPassword'; import { sendEmail } from './sendEmail'; -import { configOld } from '../config/config'; const TOKEN_TIMEOUT = 60 * 60 * 1000; // 1 hour - -const serverDomain = configOld.getServerDomain(); +const serverDomain = config.serverDomain; export const sendResetPassword = async (user: any, email: string) => { const token = uuid.v4(); From f111894a8c566e10b1b249967e852a304403a8d0 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 15:37:44 +1000 Subject: [PATCH 26/43] Variable renames --- src/app.ts | 6 +++--- src/config/config.ts | 20 ++++++++++---------- src/gameplay/game.ts | 2 +- src/myFunctions/sendEmailVerification.ts | 2 +- src/myFunctions/sendResetPassword.ts | 2 +- src/sockets/sockets.ts | 4 ++-- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/app.ts b/src/app.ts index 2730d5005..cb6f52b8a 100644 --- a/src/app.ts +++ b/src/app.ts @@ -83,7 +83,7 @@ if (configOld.getEnv() === 'local') { ); } -const port = config.port || 3000; +const port = config.PORT || 3000; const dbLoc = configOld.getDatabaseUrl(); console.log(`Using database url: ${dbLoc}`); @@ -130,7 +130,7 @@ process }); // authentication -const secretKey = config.mySecretKey || 'MySecretKey'; +const secretKey = config.MY_SECRET_KEY || 'MySecretKey'; app.use( session({ secret: secretKey, @@ -183,7 +183,7 @@ app.use('/lobby', lobbyRoutes); app.use('/forum', forumRoutes); app.use('/profile', profileRoutes); -const IP = config.ip || '127.0.0.1'; +const IP = config.IP || '127.0.0.1'; const server = app.listen(port, () => { console.log(`Server has started on ${IP}:${port}!`); }); diff --git a/src/config/config.ts b/src/config/config.ts index 23ba14d80..1aada4f45 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -49,11 +49,11 @@ class Config { } type ConfigNew = { - nodeEnv: string; - serverDomain: string; - port: string; - ip: string; - mySecretKey: string; + NODE_ENV: string; + SERVER_DOMAIN: string; + PORT: string; + IP: string; + MY_SECRET_KEY: string; discord: DiscordConfigType; email: EmailConfigType; @@ -62,11 +62,11 @@ type ConfigNew = { }; export const config: Readonly = Object.freeze({ - nodeEnv: process.env.NODE_ENV, - serverDomain: process.env.SERVER_DOMAIN, - port: process.env.PORT, - ip: process.env.IP, - mySecretKey: process.env.MY_SECRET_KEY, + NODE_ENV: process.env.NODE_ENV, + SERVER_DOMAIN: process.env.SERVER_DOMAIN, + PORT: process.env.PORT, + IP: process.env.IP, + MY_SECRET_KEY: process.env.MY_SECRET_KEY, discord: DiscordConfig, email: EmailConfig, diff --git a/src/gameplay/game.ts b/src/gameplay/game.ts index ec70c2edb..2ae2f9323 100644 --- a/src/gameplay/game.ts +++ b/src/gameplay/game.ts @@ -1562,7 +1562,7 @@ class Game extends Room { }); } - if (config.nodeEnv !== 'test') { + if (config.NODE_ENV !== 'test') { this.playersInGame.forEach((player) => { User.findById(player.userId) .populate('notifications') diff --git a/src/myFunctions/sendEmailVerification.ts b/src/myFunctions/sendEmailVerification.ts index 2c57ce25b..257f80f83 100644 --- a/src/myFunctions/sendEmailVerification.ts +++ b/src/myFunctions/sendEmailVerification.ts @@ -6,7 +6,7 @@ import emailTemplateEmailVerification from './emailTemplateEmailVerification'; import disposableEmails from '../util/disposableEmails.js'; import { sendEmail } from './sendEmail'; -const serverDomain = config.serverDomain; +const serverDomain = config.SERVER_DOMAIN; const uuidv4 = uuid.v4; diff --git a/src/myFunctions/sendResetPassword.ts b/src/myFunctions/sendResetPassword.ts index be14882e5..991e20768 100644 --- a/src/myFunctions/sendResetPassword.ts +++ b/src/myFunctions/sendResetPassword.ts @@ -6,7 +6,7 @@ import emailTemplateResetPassword from './emailTemplateResetPassword'; import { sendEmail } from './sendEmail'; const TOKEN_TIMEOUT = 60 * 60 * 1000; // 1 hour -const serverDomain = config.serverDomain; +const serverDomain = config.SERVER_DOMAIN; export const sendResetPassword = async (user: any, email: string) => { const token = uuid.v4(); diff --git a/src/sockets/sockets.ts b/src/sockets/sockets.ts index 51ebcdc2a..65c603b57 100644 --- a/src/sockets/sockets.ts +++ b/src/sockets/sockets.ts @@ -55,7 +55,7 @@ const matchmakingQueue = new MatchmakingQueue(matchFound); const joinQueueFilter = new JoinQueueFilter(() => new Date()); const readyPrompt = new ReadyPrompt(); -if (config.nodeEnv !== 'test') { +if (config.NODE_ENV !== 'test') { setInterval(() => { chatSpamFilter.tick(); }, 1000); @@ -149,7 +149,7 @@ function deleteSaveGameFromDb(room) { } } -if (config.nodeEnv !== 'test') { +if (config.NODE_ENV !== 'test') { setTimeout(async () => { let run = true; let i = 0; From b9767bf579fba298cb1bd41880ed179297580e22 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 15:44:21 +1000 Subject: [PATCH 27/43] Additional variable renames --- src/clients/discord/index.ts | 10 +++++----- src/clients/patreon/patreonController.ts | 6 +++--- src/clients/s3/S3Controller.ts | 8 ++++---- src/config/discord.ts | 20 ++++++++++---------- src/config/emailConfig.ts | 12 ++++++------ src/config/patreonConfig.ts | 12 ++++++------ src/config/s3Config.ts | 16 ++++++++-------- src/myFunctions/sendEmail.ts | 6 +++--- src/util/vpnDetection.ts | 2 +- 9 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/clients/discord/index.ts b/src/clients/discord/index.ts index f72c4449a..0c9de05e5 100644 --- a/src/clients/discord/index.ts +++ b/src/clients/discord/index.ts @@ -5,21 +5,21 @@ import { config, configOld } from '../../config/config'; const client = new Discord.Client(); if (configOld.getEnv() === 'prod') { - client.login(config.discord.botToken); + client.login(config.discord.BOT_TOKEN); } export function sendToDiscordAdmins(message: string, ping?: boolean): void { if (ping) { message = `${getAdminPing()} ${message}`; } - sendToChannel(message, config.discord.adminChannelId); + sendToChannel(message, config.discord.ADMIN_CHANNEL_ID); } export function sendToDiscordMods(message: string, ping?: boolean): void { if (ping) { message = `${getModPing()} ${message}`; } - sendToChannel(message, config.discord.modChannelId); + sendToChannel(message, config.discord.MOD_CHANNEL_ID); } function sendToChannel(message: string, channelId: string): void { @@ -31,9 +31,9 @@ function sendToChannel(message: string, channelId: string): void { } function getAdminPing(): string { - return `<@&${config.discord.adminRoleId}>`; + return `<@&${config.discord.ADMIN_ROLE_ID}>`; } function getModPing(): string { - return `<@&${config.discord.modRoleId}>`; + return `<@&${config.discord.MOD_ROLE_ID}>`; } diff --git a/src/clients/patreon/patreonController.ts b/src/clients/patreon/patreonController.ts index 461b1e148..fb123fcfc 100644 --- a/src/clients/patreon/patreonController.ts +++ b/src/clients/patreon/patreonController.ts @@ -14,9 +14,9 @@ const PATREON_URLS = { }; export class PatreonController implements IPatreonController { - private clientId = config.patreon.clientId; - private clientSecret = config.patreon.clientSecret; - private redirectUri = config.patreon.redirectUrl; + private clientId = config.patreon.CLIENT_ID; + private clientSecret = config.patreon.CLIENT_SECRET; + private redirectUri = config.patreon.REDIRECT_URL; public async getPatreonUserTokens(code: string): Promise { const getPatreonUserTokensUrl = new URL(PATREON_URLS.GET_TOKENS); diff --git a/src/clients/s3/S3Controller.ts b/src/clients/s3/S3Controller.ts index e5ea60994..d3c2bb441 100644 --- a/src/clients/s3/S3Controller.ts +++ b/src/clients/s3/S3Controller.ts @@ -17,12 +17,12 @@ export default class S3Controller implements IS3Controller { private bucket: string; constructor() { - this.publicFileLinkPrefix = config.s3.publicFileLinkPrefix; - this.bucket = config.s3.bucketName; + this.publicFileLinkPrefix = config.s3.PUBLIC_FILE_LINK_PREFIX; + this.bucket = config.s3.BUCKET_NAME; this.client = new S3Client({ - region: config.s3.region, - endpoint: config.s3.endpoint, + region: config.s3.REGION, + endpoint: config.s3.ENDPOINT, credentials: fromEnv(), }); } diff --git a/src/config/discord.ts b/src/config/discord.ts index 3a03079f3..ef7c8c452 100644 --- a/src/config/discord.ts +++ b/src/config/discord.ts @@ -1,15 +1,15 @@ export type DiscordConfigType = { - botToken: string; - adminChannelId: string; - modChannelId: string; - adminRoleId: string; - modRoleId: string; + BOT_TOKEN: string; + ADMIN_CHANNEL_ID: string; + MOD_CHANNEL_ID: string; + ADMIN_ROLE_ID: string; + MOD_ROLE_ID: string; }; export const DiscordConfig: Readonly = Object.freeze({ - botToken: process.env.discord_bot_token, - adminChannelId: process.env.discord_admin_channel_id, - modChannelId: process.env.discord_mod_channel_id, - adminRoleId: process.env.discord_admin_role_id, - modRoleId: process.env.discord_mod_role_id, + BOT_TOKEN: process.env.discord_bot_token, + ADMIN_CHANNEL_ID: process.env.discord_admin_channel_id, + MOD_CHANNEL_ID: process.env.discord_mod_channel_id, + ADMIN_ROLE_ID: process.env.discord_admin_role_id, + MOD_ROLE_ID: process.env.discord_mod_role_id, }); diff --git a/src/config/emailConfig.ts b/src/config/emailConfig.ts index 1845d99ca..9f067a419 100644 --- a/src/config/emailConfig.ts +++ b/src/config/emailConfig.ts @@ -1,11 +1,11 @@ export type EmailConfigType = { - proAvalonEmailAddressDomain: string; - proAvalonEmailAddress: string; - mailgunApiKey: string; + PROAVALON_EMAIL_ADDRESS_DOMAIN: string; + PROAVALON_EMAIL_ADDRESS: string; + MAILGUN_API_KEY: string; }; export const EmailConfig: Readonly = Object.freeze({ - proAvalonEmailAddressDomain: process.env.PROAVALON_EMAIL_ADDRESS_DOMAIN, - proAvalonEmailAddress: process.env.PROAVALON_EMAIL_ADDRESS, - mailgunApiKey: process.env.MAILGUN_API_KEY, + PROAVALON_EMAIL_ADDRESS_DOMAIN: process.env.PROAVALON_EMAIL_ADDRESS_DOMAIN, + PROAVALON_EMAIL_ADDRESS: process.env.PROAVALON_EMAIL_ADDRESS, + MAILGUN_API_KEY: process.env.MAILGUN_API_KEY, }); diff --git a/src/config/patreonConfig.ts b/src/config/patreonConfig.ts index 51fc06db5..6e23e6448 100644 --- a/src/config/patreonConfig.ts +++ b/src/config/patreonConfig.ts @@ -1,11 +1,11 @@ export type PatreonConfigType = { - clientId: string; - clientSecret: string; - redirectUrl: string; + CLIENT_ID: string; + CLIENT_SECRET: string; + REDIRECT_URL: string; }; export const PatreonConfig: Readonly = Object.freeze({ - clientId: process.env.patreon_client_ID, - clientSecret: process.env.patreon_client_secret, - redirectUrl: process.env.patreon_redirectURL, + CLIENT_ID: process.env.patreon_client_ID, + CLIENT_SECRET: process.env.patreon_client_secret, + REDIRECT_URL: process.env.patreon_redirectURL, }); diff --git a/src/config/s3Config.ts b/src/config/s3Config.ts index 3fba97235..f5994340b 100644 --- a/src/config/s3Config.ts +++ b/src/config/s3Config.ts @@ -1,15 +1,15 @@ export type S3ConfigType = { - publicFileLinkPrefix: string; - bucketName: string; - region: string; - endpoint: string; + PUBLIC_FILE_LINK_PREFIX: string; + BUCKET_NAME: string; + REGION: string; + ENDPOINT: string; }; export const S3Config: Readonly = Object.freeze({ - publicFileLinkPrefix: process.env.S3_PUBLIC_FILE_LINK_PREFIX, - bucketName: validateBucketName(), - region: process.env.S3_REGION, - endpoint: process.env.S3_ENDPOINT, + PUBLIC_FILE_LINK_PREFIX: process.env.S3_PUBLIC_FILE_LINK_PREFIX, + BUCKET_NAME: validateBucketName(), + REGION: process.env.S3_REGION, + ENDPOINT: process.env.S3_ENDPOINT, }); function validateBucketName() { diff --git a/src/myFunctions/sendEmail.ts b/src/myFunctions/sendEmail.ts index 0917eec8f..3b976efa5 100644 --- a/src/myFunctions/sendEmail.ts +++ b/src/myFunctions/sendEmail.ts @@ -3,8 +3,8 @@ import formData from 'form-data'; import { config } from '../config/config'; -const api_key = config.email.mailgunApiKey; -const domain = config.email.proAvalonEmailAddressDomain; +const api_key = config.email.MAILGUN_API_KEY; +const domain = config.email.PROAVALON_EMAIL_ADDRESS_DOMAIN; const mailgun = new Mailgun(formData); const mg = mailgun.client({ username: 'api', key: api_key }); @@ -15,7 +15,7 @@ export const sendEmail = ( messageHtml: string, ) => { const data = { - from: 'ProAvalon <' + config.email.proAvalonEmailAddress + '>', + from: 'ProAvalon <' + config.email.PROAVALON_EMAIL_ADDRESS + '>', to: recipientEmail, subject: subject, html: messageHtml, diff --git a/src/util/vpnDetection.ts b/src/util/vpnDetection.ts index ab0009f10..762073f7d 100644 --- a/src/util/vpnDetection.ts +++ b/src/util/vpnDetection.ts @@ -101,7 +101,7 @@ const isVpnCheck1 = async (ip: string): Promise => { const isVpnCheck2 = async (ip: string): Promise => { const vpnResponse = await fetch( - `https://check.getipintel.net/check.php?ip=${ip}&contact=${config.email.proAvalonEmailAddress}&flags=m`, + `https://check.getipintel.net/check.php?ip=${ip}&contact=${config.email.PROAVALON_EMAIL_ADDRESS}&flags=m`, ); const data = await vpnResponse.json(); From af65349eae45466c4b6c917da37e7be3d5dc7f7c Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 15:45:59 +1000 Subject: [PATCH 28/43] Renamed config to index.ts --- src/app.ts | 4 ++-- src/clients/discord/index.ts | 2 +- src/clients/patreon/patreonController.ts | 2 +- src/clients/s3/S3Controller.ts | 2 +- src/config/{config.ts => index.ts} | 0 src/gameplay/game.ts | 2 +- src/myFunctions/sendEmail.ts | 2 +- src/myFunctions/sendEmailVerification.ts | 2 +- src/myFunctions/sendResetPassword.ts | 2 +- src/routes/forum/forumThreadCommentReplyRoutes.js | 2 +- src/routes/forum/forumThreadCommentRoutes.js | 2 +- src/routes/forum/forumThreadRoutes.js | 2 +- src/routes/index.js | 2 +- src/routes/middleware.ts | 2 +- src/routes/mod.js | 2 +- src/sockets/commands/admin/acreatetestaccounts.ts | 2 +- src/sockets/commands/admin/asessions.ts | 2 +- src/sockets/sockets.ts | 2 +- src/util/captcha.ts | 2 +- src/util/vpnDetection.ts | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) rename src/config/{config.ts => index.ts} (100%) diff --git a/src/app.ts b/src/app.ts index cb6f52b8a..954efd547 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,6 +1,6 @@ // @ts-nocheck import './env.js'; -import './config/config'; +import './config'; import 'log-timestamp'; import { sendToDiscordAdmins } from './clients/discord'; import assert from 'assert'; @@ -20,7 +20,7 @@ import socket, { Server as SocketServer } from 'socket.io'; import createProxyMiddleware from 'http-proxy-middleware'; import morgan from 'morgan'; -import { config, configOld } from './config/config'; +import { config, configOld } from './config'; import { server as socketServer } from './sockets/sockets'; import User from './models/user'; import { emailVerified, isLoggedIn } from './routes/middleware'; diff --git a/src/clients/discord/index.ts b/src/clients/discord/index.ts index 0c9de05e5..def4d1da5 100644 --- a/src/clients/discord/index.ts +++ b/src/clients/discord/index.ts @@ -1,6 +1,6 @@ import Discord, { TextChannel } from 'discord.js'; -import { config, configOld } from '../../config/config'; +import { config, configOld } from '../../config'; const client = new Discord.Client(); diff --git a/src/clients/patreon/patreonController.ts b/src/clients/patreon/patreonController.ts index fb123fcfc..27524e484 100644 --- a/src/clients/patreon/patreonController.ts +++ b/src/clients/patreon/patreonController.ts @@ -1,6 +1,6 @@ import uuid from 'uuid'; -import { config } from '../../config/config'; +import { config } from '../../config'; import { IPatreonController, PatreonUserTokens, diff --git a/src/clients/s3/S3Controller.ts b/src/clients/s3/S3Controller.ts index d3c2bb441..217837f57 100644 --- a/src/clients/s3/S3Controller.ts +++ b/src/clients/s3/S3Controller.ts @@ -8,7 +8,7 @@ import { S3Client, } from '@aws-sdk/client-s3'; -import { config } from '../../config/config'; +import { config } from '../../config'; import { IS3Controller } from './S3Agent'; export default class S3Controller implements IS3Controller { diff --git a/src/config/config.ts b/src/config/index.ts similarity index 100% rename from src/config/config.ts rename to src/config/index.ts diff --git a/src/gameplay/game.ts b/src/gameplay/game.ts index 2ae2f9323..e69d8f353 100644 --- a/src/gameplay/game.ts +++ b/src/gameplay/game.ts @@ -1,7 +1,7 @@ // @ts-nocheck import _ from 'lodash'; -import { config } from '../config/config'; +import { config } from '../config'; import Room, { RoomConfig } from './room'; import usernamesIndexes from '../myFunctions/usernamesIndexes'; import User from '../models/user'; diff --git a/src/myFunctions/sendEmail.ts b/src/myFunctions/sendEmail.ts index 3b976efa5..9c6a2aeea 100644 --- a/src/myFunctions/sendEmail.ts +++ b/src/myFunctions/sendEmail.ts @@ -1,7 +1,7 @@ import Mailgun from 'mailgun.js'; import formData from 'form-data'; -import { config } from '../config/config'; +import { config } from '../config'; const api_key = config.email.MAILGUN_API_KEY; const domain = config.email.PROAVALON_EMAIL_ADDRESS_DOMAIN; diff --git a/src/myFunctions/sendEmailVerification.ts b/src/myFunctions/sendEmailVerification.ts index 257f80f83..5a7b36b1d 100644 --- a/src/myFunctions/sendEmailVerification.ts +++ b/src/myFunctions/sendEmailVerification.ts @@ -1,7 +1,7 @@ import ejs from 'ejs'; import uuid from 'uuid'; -import { config } from '../config/config'; +import { config } from '../config'; import emailTemplateEmailVerification from './emailTemplateEmailVerification'; import disposableEmails from '../util/disposableEmails.js'; import { sendEmail } from './sendEmail'; diff --git a/src/myFunctions/sendResetPassword.ts b/src/myFunctions/sendResetPassword.ts index 991e20768..f2f9063c3 100644 --- a/src/myFunctions/sendResetPassword.ts +++ b/src/myFunctions/sendResetPassword.ts @@ -1,7 +1,7 @@ import uuid from 'uuid'; import ejs from 'ejs'; -import { config } from '../config/config'; +import { config } from '../config'; import emailTemplateResetPassword from './emailTemplateResetPassword'; import { sendEmail } from './sendEmail'; diff --git a/src/routes/forum/forumThreadCommentReplyRoutes.js b/src/routes/forum/forumThreadCommentReplyRoutes.js index 79970e878..82b048835 100644 --- a/src/routes/forum/forumThreadCommentReplyRoutes.js +++ b/src/routes/forum/forumThreadCommentReplyRoutes.js @@ -3,7 +3,7 @@ import sanitizeHtml from 'sanitize-html'; import mongoose from 'mongoose'; import rateLimit from 'express-rate-limit'; -import { configOld } from '../../config/config'; +import { configOld } from '../../config'; import forumThread from '../../models/forumThread'; import forumThreadComment from '../../models/forumThreadComment'; import forumThreadCommentReply from '../../models/forumThreadCommentReply'; diff --git a/src/routes/forum/forumThreadCommentRoutes.js b/src/routes/forum/forumThreadCommentRoutes.js index f1c3c4a63..3be86bf2b 100644 --- a/src/routes/forum/forumThreadCommentRoutes.js +++ b/src/routes/forum/forumThreadCommentRoutes.js @@ -12,7 +12,7 @@ import { allowedHtmlAttributes, allowedHtmlTags } from './sanitizeRestrictions'; import { createNotification } from '../../myFunctions/createNotification'; import REWARDS from '../../rewards/constants'; import { userHasReward } from '../../rewards/getRewards'; -import { configOld } from '../../config/config'; +import { configOld } from '../../config'; const router = new Router(); diff --git a/src/routes/forum/forumThreadRoutes.js b/src/routes/forum/forumThreadRoutes.js index 9aad774f9..82ab167b4 100644 --- a/src/routes/forum/forumThreadRoutes.js +++ b/src/routes/forum/forumThreadRoutes.js @@ -2,7 +2,7 @@ import { Router } from 'express'; import sanitizeHtml from 'sanitize-html'; import rateLimit from 'express-rate-limit'; -import { configOld } from '../../config/config'; +import { configOld } from '../../config'; import { checkForumThreadOwnership, asyncMiddleware } from '../middleware'; import getTimeDiffInString from '../../util/getTimeDiffInString'; import lastIds from '../../models/lastIds'; diff --git a/src/routes/index.js b/src/routes/index.js index 49e21d761..9fb1d7b5c 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -12,7 +12,7 @@ import statsCumulative from '../models/statsCumulative'; import { emailExists, validEmail } from '../routes/emailVerification'; import { sendEmailVerification } from '../myFunctions/sendEmailVerification'; -import { configOld } from '../config/config'; +import { configOld } from '../config'; import { disallowVPNs } from '../util/vpnDetection'; import { settingsSingleton } from '../settings'; import { Alliance } from '../gameplay/types'; diff --git a/src/routes/middleware.ts b/src/routes/middleware.ts index 58c14f8bb..86f6c4191 100644 --- a/src/routes/middleware.ts +++ b/src/routes/middleware.ts @@ -8,7 +8,7 @@ import { isMod } from '../modsadmins/mods'; import { isAdmin } from '../modsadmins/admins'; import { RequestHandler } from 'express'; -import { configOld } from '../config/config'; +import { configOld } from '../config'; // return a function that wraps an async middleware export const asyncMiddleware = diff --git a/src/routes/mod.js b/src/routes/mod.js index 260092076..d55f57eb1 100644 --- a/src/routes/mod.js +++ b/src/routes/mod.js @@ -19,7 +19,7 @@ import ModLogComponent from '../views/components/mod/mod_log'; import ReportLog from '../views/components/mod/report'; import { MongoClient } from 'mongodb'; import { SESSIONS_COLLECTION_NAME } from '../constants'; -import { configOld } from '../config/config'; +import { configOld } from '../config'; const router = new Router(); diff --git a/src/sockets/commands/admin/acreatetestaccounts.ts b/src/sockets/commands/admin/acreatetestaccounts.ts index d332b5d37..90956eb0e 100644 --- a/src/sockets/commands/admin/acreatetestaccounts.ts +++ b/src/sockets/commands/admin/acreatetestaccounts.ts @@ -2,7 +2,7 @@ import { sendReplyToCommand } from '../../sockets'; import { SocketUser } from '../../types'; import User from '../../../models/user'; import { Command } from '../types'; -import { configOld } from '../../../config/config'; +import { configOld } from '../../../config'; export const acreatetestaccounts: Command = { command: 'acreatetestaccounts', diff --git a/src/sockets/commands/admin/asessions.ts b/src/sockets/commands/admin/asessions.ts index 0682373dc..51756d9e9 100644 --- a/src/sockets/commands/admin/asessions.ts +++ b/src/sockets/commands/admin/asessions.ts @@ -2,7 +2,7 @@ import { sendReplyToCommand } from '../../sockets'; import { SocketUser } from '../../types'; import { Command } from '../types'; import { MongoClient } from 'mongodb'; -import { configOld } from '../../../config/config'; +import { configOld } from '../../../config'; export const asessions: Command = { command: 'asessions', diff --git a/src/sockets/sockets.ts b/src/sockets/sockets.ts index 65c603b57..2de1e1259 100644 --- a/src/sockets/sockets.ts +++ b/src/sockets/sockets.ts @@ -46,7 +46,7 @@ import { Card } from '../gameplay/cards/types'; import { TOCommandsImported } from './commands/tournamentOrganisers'; import { PatreonAgent } from '../clients/patreon/patreonAgent'; import { PatreonController } from '../clients/patreon/patreonController'; -import { config, configOld } from '../config/config'; +import { config, configOld } from '../config'; const chatSpamFilter = new ChatSpamFilter(); const createRoomFilter = new CreateRoomFilter(); diff --git a/src/util/captcha.ts b/src/util/captcha.ts index 65cb0dc0d..04b239f73 100644 --- a/src/util/captcha.ts +++ b/src/util/captcha.ts @@ -1,6 +1,6 @@ import { RequestHandler } from 'express'; import axios from 'axios'; -import { configOld } from '../config/config'; +import { configOld } from '../config'; export const captchaMiddleware: RequestHandler = async (req, res, next) => { if (configOld.getEnv() !== 'prod') { diff --git a/src/util/vpnDetection.ts b/src/util/vpnDetection.ts index 762073f7d..921320e75 100644 --- a/src/util/vpnDetection.ts +++ b/src/util/vpnDetection.ts @@ -1,5 +1,5 @@ import { RequestHandler } from 'express'; -import { config, configOld } from '../config/config'; +import { config, configOld } from '../config'; const VPN_TIMEOUT = 1000 * 60 * 60 * 12; // 12 hours From 7f3ddabfcad75db4aecea891f52e1f12fa21be70 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 15:46:31 +1000 Subject: [PATCH 29/43] renamed to discordConfig --- src/config/{discord.ts => discordConfig.ts} | 0 src/config/index.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/config/{discord.ts => discordConfig.ts} (100%) diff --git a/src/config/discord.ts b/src/config/discordConfig.ts similarity index 100% rename from src/config/discord.ts rename to src/config/discordConfig.ts diff --git a/src/config/index.ts b/src/config/index.ts index 1aada4f45..c72a10cb3 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -1,5 +1,5 @@ import { PatreonConfig, PatreonConfigType } from './patreonConfig'; -import { DiscordConfig, DiscordConfigType } from './discord'; +import { DiscordConfig, DiscordConfigType } from './discordConfig'; import { S3Config, S3ConfigType } from './s3Config'; import { EmailConfig, EmailConfigType } from './emailConfig'; From 65f35f1f58966247b58132442dc5a18aaf3b4e12 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 15:50:48 +1000 Subject: [PATCH 30/43] Extracted vpn variables --- src/config/index.ts | 14 +++----------- src/config/vpnConfig.ts | 9 +++++++++ src/util/vpnDetection.ts | 6 +++--- 3 files changed, 15 insertions(+), 14 deletions(-) create mode 100644 src/config/vpnConfig.ts diff --git a/src/config/index.ts b/src/config/index.ts index c72a10cb3..bfaa3ebb1 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -2,15 +2,13 @@ import { PatreonConfig, PatreonConfigType } from './patreonConfig'; import { DiscordConfig, DiscordConfigType } from './discordConfig'; import { S3Config, S3ConfigType } from './s3Config'; import { EmailConfig, EmailConfigType } from './emailConfig'; +import { VpnConfig, VpnConfigType } from './vpnConfig'; const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); class Config { private readonly env: string = process.env.ENV; - private readonly vpnDetectionToken: string = process.env.VPN_DETECTION_TOKEN; - private readonly whitelistedVpnUsernames: string = - process.env.WHITELISTED_VPN_USERNAMES; private readonly googleCaptchaKey: string = process.env.MY_SECRET_GOOGLE_CAPTCHA_KEY; private readonly databaseUrl: string = process.env.DATABASEURL; @@ -31,14 +29,6 @@ class Config { return this.env; } - public getVpnDetectionToken() { - return this.vpnDetectionToken; - } - - public getWhitelistedVpnUsernames() { - return this.whitelistedVpnUsernames; - } - public getGoogleCaptchaKey() { return this.googleCaptchaKey; } @@ -59,6 +49,7 @@ type ConfigNew = { email: EmailConfigType; patreon: PatreonConfigType; s3: S3ConfigType; + vpn: VpnConfigType; }; export const config: Readonly = Object.freeze({ @@ -72,6 +63,7 @@ export const config: Readonly = Object.freeze({ email: EmailConfig, patreon: PatreonConfig, s3: S3Config, + vpn: VpnConfig, }); export const configOld = new Config(); diff --git a/src/config/vpnConfig.ts b/src/config/vpnConfig.ts new file mode 100644 index 000000000..ad154dc03 --- /dev/null +++ b/src/config/vpnConfig.ts @@ -0,0 +1,9 @@ +export type VpnConfigType = { + VPN_DETECTION_TOKEN: string; + WHITELISTED_VPN_USERNAMES: string; +}; + +export const VpnConfig: Readonly = Object.freeze({ + VPN_DETECTION_TOKEN: process.env.VPN_DETECTION_TOKEN, + WHITELISTED_VPN_USERNAMES: process.env.WHITELISTED_VPN_USERNAMES, +}); diff --git a/src/util/vpnDetection.ts b/src/util/vpnDetection.ts index 921320e75..1052b0b97 100644 --- a/src/util/vpnDetection.ts +++ b/src/util/vpnDetection.ts @@ -5,8 +5,8 @@ const VPN_TIMEOUT = 1000 * 60 * 60 * 12; // 12 hours // TODO-kev: check if this still works let whitelistedUsernames: string[] = []; -if (configOld.getWhitelistedVpnUsernames()) { - whitelistedUsernames = configOld.getWhitelistedVpnUsernames().split(','); +if (config.vpn.WHITELISTED_VPN_USERNAMES) { + whitelistedUsernames = config.vpn.WHITELISTED_VPN_USERNAMES.split(','); } class VpnEntry { @@ -84,7 +84,7 @@ const isVPN = async (ip: string): Promise => { const isVpnCheck1 = async (ip: string): Promise => { const vpnResponse = await fetch( - `https://vpnapi.io/api/${ip}?key=${configOld.getVpnDetectionToken()}`, + `https://vpnapi.io/api/${ip}?key=${config.vpn.VPN_DETECTION_TOKEN}`, ); const data = await vpnResponse.json(); From d3ac29ea69b7c6dd0cbad9e5f33422196371fa30 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 15:56:21 +1000 Subject: [PATCH 31/43] Added google captcha and databaseurl --- src/app.ts | 2 +- src/config/index.ts | 12 ++++++------ src/routes/mod.js | 6 +++--- src/sockets/commands/admin/asessions.ts | 7 ++++--- src/util/captcha.ts | 4 ++-- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/app.ts b/src/app.ts index 954efd547..90749b16e 100644 --- a/src/app.ts +++ b/src/app.ts @@ -84,7 +84,7 @@ if (configOld.getEnv() === 'local') { } const port = config.PORT || 3000; -const dbLoc = configOld.getDatabaseUrl(); +const dbLoc = config.DATABASE_URL; console.log(`Using database url: ${dbLoc}`); mongoose.connect(dbLoc, { diff --git a/src/config/index.ts b/src/config/index.ts index bfaa3ebb1..00f3c2f5e 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -9,8 +9,6 @@ const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); class Config { private readonly env: string = process.env.ENV; - private readonly googleCaptchaKey: string = - process.env.MY_SECRET_GOOGLE_CAPTCHA_KEY; private readonly databaseUrl: string = process.env.DATABASEURL; constructor() { @@ -29,10 +27,6 @@ class Config { return this.env; } - public getGoogleCaptchaKey() { - return this.googleCaptchaKey; - } - public getDatabaseUrl() { return this.databaseUrl; } @@ -45,6 +39,9 @@ type ConfigNew = { IP: string; MY_SECRET_KEY: string; + GOOGLE_CAPTCHA_KEY: string; + DATABASE_URL: string; + discord: DiscordConfigType; email: EmailConfigType; patreon: PatreonConfigType; @@ -59,6 +56,9 @@ export const config: Readonly = Object.freeze({ IP: process.env.IP, MY_SECRET_KEY: process.env.MY_SECRET_KEY, + GOOGLE_CAPTCHA_KEY: process.env.MY_SECRET_GOOGLE_CAPTCHA_KEY, + DATABASE_URL: process.env.DATABASEURL, // TODO-kev: Consider renaming env variable + discord: DiscordConfig, email: EmailConfig, patreon: PatreonConfig, diff --git a/src/routes/mod.js b/src/routes/mod.js index d55f57eb1..e026ea256 100644 --- a/src/routes/mod.js +++ b/src/routes/mod.js @@ -1,7 +1,9 @@ import React from 'react'; import { Router } from 'express'; import { renderToString } from 'react-dom/server'; +import { MongoClient } from 'mongodb'; +import { config } from '../config'; import { isModMiddleware } from './middleware'; import User from '../models/user'; import Ban from '../models/ban'; @@ -17,9 +19,7 @@ import { import ModLogComponent from '../views/components/mod/mod_log'; import ReportLog from '../views/components/mod/report'; -import { MongoClient } from 'mongodb'; import { SESSIONS_COLLECTION_NAME } from '../constants'; -import { configOld } from '../config'; const router = new Router(); @@ -187,7 +187,7 @@ router.post('/ban', isModMiddleware, async (req, res) => { }); // Delete all the sessions associated with this username - const dbResult = await MongoClient.connect(configOld.getDatabaseUrl()); + const dbResult = await MongoClient.connect(config.DATABASE_URL); const mySessions = dbResult.db().collection(SESSIONS_COLLECTION_NAME); const deleteResult = await mySessions.deleteMany({ 'session.usernameLower': banPlayerUsername.toLowerCase(), diff --git a/src/sockets/commands/admin/asessions.ts b/src/sockets/commands/admin/asessions.ts index 51756d9e9..c27f48dd7 100644 --- a/src/sockets/commands/admin/asessions.ts +++ b/src/sockets/commands/admin/asessions.ts @@ -1,8 +1,9 @@ +import { MongoClient } from 'mongodb'; + +import { config } from '../../../config'; import { sendReplyToCommand } from '../../sockets'; import { SocketUser } from '../../types'; import { Command } from '../types'; -import { MongoClient } from 'mongodb'; -import { configOld } from '../../../config'; export const asessions: Command = { command: 'asessions', @@ -15,7 +16,7 @@ export const asessions: Command = { return; } - const dbResult = await MongoClient.connect(configOld.getDatabaseUrl()); + const dbResult = await MongoClient.connect(config.DATABASE_URL); const mySessions = dbResult.db().collection('mySessions'); const entries = mySessions.find({ 'session.usernameLower': username }); diff --git a/src/util/captcha.ts b/src/util/captcha.ts index 04b239f73..46e0174c2 100644 --- a/src/util/captcha.ts +++ b/src/util/captcha.ts @@ -1,6 +1,6 @@ import { RequestHandler } from 'express'; import axios from 'axios'; -import { configOld } from '../config'; +import { config, configOld } from '../config'; export const captchaMiddleware: RequestHandler = async (req, res, next) => { if (configOld.getEnv() !== 'prod') { @@ -19,7 +19,7 @@ export const captchaMiddleware: RequestHandler = async (req, res, next) => { return; } - const secretKey = configOld.getGoogleCaptchaKey(); + const secretKey = config.GOOGLE_CAPTCHA_KEY; const verifyUrl = `https://google.com/recaptcha/api/siteverify?secret=${secretKey}&response=${req.body.captcha}&remoteip=${req.connection.remoteAddress}`; const response = await axios.post(verifyUrl); From 8e4d60fce4ebae5587f574f3e34b40549febb6f0 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 15:57:24 +1000 Subject: [PATCH 32/43] Minor update --- src/config/index.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/config/index.ts b/src/config/index.ts index 00f3c2f5e..c7d7cd340 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -9,8 +9,6 @@ const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); class Config { private readonly env: string = process.env.ENV; - private readonly databaseUrl: string = process.env.DATABASEURL; - constructor() { // Run validation checks outside test environment if (process.env.NODE_ENV !== 'test') { @@ -26,10 +24,6 @@ class Config { public getEnv() { return this.env; } - - public getDatabaseUrl() { - return this.databaseUrl; - } } type ConfigNew = { From f5ffd6dc0b7f9e86de47ba66ff5a05b95c70af49 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 16:04:10 +1000 Subject: [PATCH 33/43] Extracted env --- src/app.ts | 4 ++-- src/clients/discord/index.ts | 6 +++--- src/config/index.ts | 8 ++------ src/routes/forum/forumThreadCommentReplyRoutes.js | 4 ++-- src/routes/forum/forumThreadCommentRoutes.js | 5 +++-- src/routes/forum/forumThreadRoutes.js | 4 ++-- src/routes/index.js | 12 ++++++------ src/routes/middleware.ts | 8 ++++---- src/sockets/commands/admin/acreatetestaccounts.ts | 4 ++-- src/sockets/sockets.ts | 4 ++-- src/util/captcha.ts | 4 ++-- src/util/vpnDetection.ts | 4 ++-- 12 files changed, 32 insertions(+), 35 deletions(-) diff --git a/src/app.ts b/src/app.ts index 90749b16e..ea40ef3c6 100644 --- a/src/app.ts +++ b/src/app.ts @@ -20,7 +20,7 @@ import socket, { Server as SocketServer } from 'socket.io'; import createProxyMiddleware from 'http-proxy-middleware'; import morgan from 'morgan'; -import { config, configOld } from './config'; +import { config } from './config'; import { server as socketServer } from './sockets/sockets'; import User from './models/user'; import { emailVerified, isLoggedIn } from './routes/middleware'; @@ -75,7 +75,7 @@ app.use( ), ); -if (configOld.getEnv() === 'local') { +if (config.ENV === 'local') { console.log('Routing dist_webpack to localhost:3010.'); app.use( '/dist_webpack', diff --git a/src/clients/discord/index.ts b/src/clients/discord/index.ts index def4d1da5..c7da171e6 100644 --- a/src/clients/discord/index.ts +++ b/src/clients/discord/index.ts @@ -1,10 +1,10 @@ import Discord, { TextChannel } from 'discord.js'; -import { config, configOld } from '../../config'; +import { config } from '../../config'; const client = new Discord.Client(); -if (configOld.getEnv() === 'prod') { +if (config.ENV === 'prod') { client.login(config.discord.BOT_TOKEN); } @@ -25,7 +25,7 @@ export function sendToDiscordMods(message: string, ping?: boolean): void { function sendToChannel(message: string, channelId: string): void { const channel = client.channels.cache.get(channelId) as TextChannel; - if (configOld.getEnv() === 'prod') { + if (config.ENV === 'prod') { channel.send(message); } } diff --git a/src/config/index.ts b/src/config/index.ts index c7d7cd340..8ea8a2332 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -20,13 +20,10 @@ class Config { } } } - - public getEnv() { - return this.env; - } } type ConfigNew = { + ENV: string; NODE_ENV: string; SERVER_DOMAIN: string; PORT: string; @@ -44,6 +41,7 @@ type ConfigNew = { }; export const config: Readonly = Object.freeze({ + ENV: process.env.ENV, NODE_ENV: process.env.NODE_ENV, SERVER_DOMAIN: process.env.SERVER_DOMAIN, PORT: process.env.PORT, @@ -59,5 +57,3 @@ export const config: Readonly = Object.freeze({ s3: S3Config, vpn: VpnConfig, }); - -export const configOld = new Config(); diff --git a/src/routes/forum/forumThreadCommentReplyRoutes.js b/src/routes/forum/forumThreadCommentReplyRoutes.js index 82b048835..e60f14560 100644 --- a/src/routes/forum/forumThreadCommentReplyRoutes.js +++ b/src/routes/forum/forumThreadCommentReplyRoutes.js @@ -3,7 +3,7 @@ import sanitizeHtml from 'sanitize-html'; import mongoose from 'mongoose'; import rateLimit from 'express-rate-limit'; -import { configOld } from '../../config'; +import { config } from '../../config'; import forumThread from '../../models/forumThread'; import forumThreadComment from '../../models/forumThreadComment'; import forumThreadCommentReply from '../../models/forumThreadCommentReply'; @@ -40,7 +40,7 @@ const sanitizeHtmlAllowedAttributesForumThread = { }; const newReplyLimiter = - configOld.getEnv() === 'local' + config.ENV === 'local' ? rateLimit({ max: 0, // Disable if we are local }) diff --git a/src/routes/forum/forumThreadCommentRoutes.js b/src/routes/forum/forumThreadCommentRoutes.js index 3be86bf2b..e7d95318e 100644 --- a/src/routes/forum/forumThreadCommentRoutes.js +++ b/src/routes/forum/forumThreadCommentRoutes.js @@ -2,6 +2,8 @@ import { Router } from 'express'; import sanitizeHtml from 'sanitize-html'; import mongoose from 'mongoose'; import rateLimit from 'express-rate-limit'; + +import { config } from '../../config'; import forumThread from '../../models/forumThread'; import forumThreadComment from '../../models/forumThreadComment'; import { @@ -12,12 +14,11 @@ import { allowedHtmlAttributes, allowedHtmlTags } from './sanitizeRestrictions'; import { createNotification } from '../../myFunctions/createNotification'; import REWARDS from '../../rewards/constants'; import { userHasReward } from '../../rewards/getRewards'; -import { configOld } from '../../config'; const router = new Router(); const newCommentLimiter = - configOld.getEnv() === 'local' + config.ENV === 'local' ? rateLimit({ max: 0, // Disable if we are local }) diff --git a/src/routes/forum/forumThreadRoutes.js b/src/routes/forum/forumThreadRoutes.js index 82ab167b4..557fef153 100644 --- a/src/routes/forum/forumThreadRoutes.js +++ b/src/routes/forum/forumThreadRoutes.js @@ -2,7 +2,7 @@ import { Router } from 'express'; import sanitizeHtml from 'sanitize-html'; import rateLimit from 'express-rate-limit'; -import { configOld } from '../../config'; +import { config } from '../../config'; import { checkForumThreadOwnership, asyncMiddleware } from '../middleware'; import getTimeDiffInString from '../../util/getTimeDiffInString'; import lastIds from '../../models/lastIds'; @@ -130,7 +130,7 @@ lastIds.findOne({}).exec(async (err, returnedLastId) => { }); const newForumLimiter = - configOld.getEnv() === 'local' + config.ENV === 'local' ? rateLimit({ max: 0, // Disable if we are local }) diff --git a/src/routes/index.js b/src/routes/index.js index 9fb1d7b5c..8aa5a7bc0 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -12,7 +12,7 @@ import statsCumulative from '../models/statsCumulative'; import { emailExists, validEmail } from '../routes/emailVerification'; import { sendEmailVerification } from '../myFunctions/sendEmailVerification'; -import { configOld } from '../config'; +import { config } from '../config'; import { disallowVPNs } from '../util/vpnDetection'; import { settingsSingleton } from '../settings'; import { Alliance } from '../gameplay/types'; @@ -32,11 +32,11 @@ router.get('/', (req, res) => { // register route router.get('/register', (req, res) => { - res.render('register', { platform: configOld.getEnv() }); + res.render('register', { platform: config.ENV }); }); const registerLimiter = - configOld.getEnv() === 'local' + config.ENV === 'local' ? rateLimit({ max: 0, // Disable if we are local }) @@ -99,7 +99,7 @@ router.post( passport.authenticate('local')(req, res, () => { res.redirect('/lobby'); }); - if (configOld.getEnv() === 'prod') { + if (config.ENV === 'prod') { sendEmailVerification(user, req.body.emailAddress); } else { user.emailVerified = true; @@ -113,7 +113,7 @@ router.post( ); const loginLimiter = - configOld.getEnv() === 'local' + config.ENV === 'local' ? rateLimit({ max: 0, // Disable if we are local }) @@ -237,7 +237,7 @@ router.get('/statistics', (req, res) => { }); router.get('/resetPassword', (req, res) => { - res.render('resetPassword', { platform: configOld.getEnv() }); + res.render('resetPassword', { platform: config.ENV }); }); router.post( diff --git a/src/routes/middleware.ts b/src/routes/middleware.ts index 86f6c4191..2c44e1796 100644 --- a/src/routes/middleware.ts +++ b/src/routes/middleware.ts @@ -1,4 +1,7 @@ // @ts-nocheck +import { RequestHandler } from 'express'; + +import { config } from '../config'; import forumThread from '../models/forumThread'; import forumThreadComment from '../models/forumThreadComment'; import forumThreadCommentReply from '../models/forumThreadCommentReply'; @@ -7,9 +10,6 @@ import Ban from '../models/ban'; import { isMod } from '../modsadmins/mods'; import { isAdmin } from '../modsadmins/admins'; -import { RequestHandler } from 'express'; -import { configOld } from '../config'; - // return a function that wraps an async middleware export const asyncMiddleware = (fn: RequestHandler): RequestHandler => @@ -222,7 +222,7 @@ export const isAdminMiddleware = (req, res, next) => { }; export const emailVerified = (req, res, next) => { - if (req.user.emailVerified === true || configOld.getEnv() != 'prod') { + if (req.user.emailVerified === true || config.ENV != 'prod') { next(); } else { res.redirect('/emailVerification'); diff --git a/src/sockets/commands/admin/acreatetestaccounts.ts b/src/sockets/commands/admin/acreatetestaccounts.ts index 90956eb0e..105bd269f 100644 --- a/src/sockets/commands/admin/acreatetestaccounts.ts +++ b/src/sockets/commands/admin/acreatetestaccounts.ts @@ -1,14 +1,14 @@ +import { config } from '../../../config'; import { sendReplyToCommand } from '../../sockets'; import { SocketUser } from '../../types'; import User from '../../../models/user'; import { Command } from '../types'; -import { configOld } from '../../../config'; export const acreatetestaccounts: Command = { command: 'acreatetestaccounts', help: '/acreatetestaccounts: Creates test accounts: 1 to 10. Passwords are the username.', run: async (args: string[], socket: SocketUser) => { - if (configOld.getEnv() === 'prod') { + if (config.ENV === 'prod') { sendReplyToCommand(socket, 'Cannot create test accounts in prod.'); return; } diff --git a/src/sockets/sockets.ts b/src/sockets/sockets.ts index 2de1e1259..53ea06587 100644 --- a/src/sockets/sockets.ts +++ b/src/sockets/sockets.ts @@ -2,6 +2,7 @@ import { Server as SocketServer, Socket } from 'socket.io'; import { SocketUser } from './types'; +import { config } from '../config'; import GameWrapper from '../gameplay/gameWrapper'; import savedGameObj from '../models/savedGame'; @@ -46,7 +47,6 @@ import { Card } from '../gameplay/cards/types'; import { TOCommandsImported } from './commands/tournamentOrganisers'; import { PatreonAgent } from '../clients/patreon/patreonAgent'; import { PatreonController } from '../clients/patreon/patreonController'; -import { config, configOld } from '../config'; const chatSpamFilter = new ChatSpamFilter(); const createRoomFilter = new CreateRoomFilter(); @@ -1955,7 +1955,7 @@ function joinQueue(): boolean { return false; } - if (configOld.getEnv() !== 'local') { + if (config.ENV !== 'local') { if (this.request.user.totalGamesPlayed < 3) { this.emit('allChatToClient', { message: 'You require 3 games to join the ranked queue.', diff --git a/src/util/captcha.ts b/src/util/captcha.ts index 46e0174c2..6501bb076 100644 --- a/src/util/captcha.ts +++ b/src/util/captcha.ts @@ -1,9 +1,9 @@ import { RequestHandler } from 'express'; import axios from 'axios'; -import { config, configOld } from '../config'; +import { config } from '../config'; export const captchaMiddleware: RequestHandler = async (req, res, next) => { - if (configOld.getEnv() !== 'prod') { + if (config.ENV !== 'prod') { return next(); } diff --git a/src/util/vpnDetection.ts b/src/util/vpnDetection.ts index 1052b0b97..f57ad12a6 100644 --- a/src/util/vpnDetection.ts +++ b/src/util/vpnDetection.ts @@ -1,5 +1,5 @@ import { RequestHandler } from 'express'; -import { config, configOld } from '../config'; +import { config } from '../config'; const VPN_TIMEOUT = 1000 * 60 * 60 * 12; // 12 hours @@ -118,7 +118,7 @@ const isVpnCheck2 = async (ip: string): Promise => { }; export const disallowVPNs: RequestHandler = (req, res, next) => { - if (configOld.getEnv() === 'local') { + if (config.ENV === 'local') { next(); return; } From 9873ce4dcad7cb43afe4a1dc3b6a251c9f78d2af Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 16:12:32 +1000 Subject: [PATCH 34/43] Added ENV validation --- src/config/index.ts | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/src/config/index.ts b/src/config/index.ts index 8ea8a2332..9aa41b3aa 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -4,24 +4,6 @@ import { S3Config, S3ConfigType } from './s3Config'; import { EmailConfig, EmailConfigType } from './emailConfig'; import { VpnConfig, VpnConfigType } from './vpnConfig'; -const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); - -class Config { - private readonly env: string = process.env.ENV; - - constructor() { - // Run validation checks outside test environment - if (process.env.NODE_ENV !== 'test') { - if (!VALID_ENVIRONMENTS.has(this.env)) { - // TODO-kev: Prefer the console.error then process exit or throw an error? - console.error(`Bad environment variable given: ${process.env.ENV}`); - throw new Error(`Invalid settings: ENV=${process.env.ENV}`); - process.exit(1); - } - } - } -} - type ConfigNew = { ENV: string; NODE_ENV: string; @@ -41,7 +23,7 @@ type ConfigNew = { }; export const config: Readonly = Object.freeze({ - ENV: process.env.ENV, + ENV: validateEnv(), NODE_ENV: process.env.NODE_ENV, SERVER_DOMAIN: process.env.SERVER_DOMAIN, PORT: process.env.PORT, @@ -57,3 +39,18 @@ export const config: Readonly = Object.freeze({ s3: S3Config, vpn: VpnConfig, }); + +function validateEnv() { + const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); + + if (process.env.NODE_ENV !== 'test') { + if (!VALID_ENVIRONMENTS.has(process.env.ENV)) { + // TODO-kev: Prefer the console.error then process exit or throw an error? + console.error(`Bad environment variable given: ${process.env.ENV}`); + throw new Error(`Invalid settings: ENV=${process.env.ENV}`); + process.exit(1); + } + } + + return process.env.ENV; +} From 0cb5053ad66a86ae1f92a83686bec8f4111d9ea4 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 16:30:28 +1000 Subject: [PATCH 35/43] Added required env variables for some general ones --- src/config/index.ts | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/config/index.ts b/src/config/index.ts index 9aa41b3aa..acc05f851 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -6,13 +6,13 @@ import { VpnConfig, VpnConfigType } from './vpnConfig'; type ConfigNew = { ENV: string; - NODE_ENV: string; - SERVER_DOMAIN: string; - PORT: string; - IP: string; + NODE_ENV?: string; + SERVER_DOMAIN?: string; + PORT?: string; + IP?: string; MY_SECRET_KEY: string; - GOOGLE_CAPTCHA_KEY: string; + GOOGLE_CAPTCHA_KEY?: string; DATABASE_URL: string; discord: DiscordConfigType; @@ -28,10 +28,10 @@ export const config: Readonly = Object.freeze({ SERVER_DOMAIN: process.env.SERVER_DOMAIN, PORT: process.env.PORT, IP: process.env.IP, - MY_SECRET_KEY: process.env.MY_SECRET_KEY, + MY_SECRET_KEY: getRequiredEnvVariable('MY_SECRET_KEY'), GOOGLE_CAPTCHA_KEY: process.env.MY_SECRET_GOOGLE_CAPTCHA_KEY, - DATABASE_URL: process.env.DATABASEURL, // TODO-kev: Consider renaming env variable + DATABASE_URL: getRequiredEnvVariable('DATABASEURL'), // TODO-kev: Consider renaming env variable discord: DiscordConfig, email: EmailConfig, @@ -42,15 +42,26 @@ export const config: Readonly = Object.freeze({ function validateEnv() { const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); + const ENV = getRequiredEnvVariable('ENV'); if (process.env.NODE_ENV !== 'test') { - if (!VALID_ENVIRONMENTS.has(process.env.ENV)) { + if (!VALID_ENVIRONMENTS.has(ENV)) { // TODO-kev: Prefer the console.error then process exit or throw an error? - console.error(`Bad environment variable given: ${process.env.ENV}`); - throw new Error(`Invalid settings: ENV=${process.env.ENV}`); + console.error(`Bad environment variable given: ${ENV}`); + throw new Error(`Invalid settings: ENV=${ENV}`); process.exit(1); } } - return process.env.ENV; + return ENV; +} + +export function getRequiredEnvVariable(variableName: string) { + const envVariable = process.env[variableName]; + + if (envVariable === undefined || envVariable === '') { + throw new Error(`Missing required environment variable: ${variableName}`); + } + + return envVariable; } From 41aa39352c8720caba9bdff560a67d0b91b3de28 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 16:47:38 +1000 Subject: [PATCH 36/43] Added function for required variable --- src/config/discordConfig.ts | 10 +++++----- src/config/emailConfig.ts | 6 +++--- src/config/index.ts | 11 +---------- src/config/patreonConfig.ts | 6 +++--- src/config/s3Config.ts | 13 ++++++++----- src/config/utils.ts | 9 +++++++++ src/config/vpnConfig.ts | 4 ++-- 7 files changed, 31 insertions(+), 28 deletions(-) create mode 100644 src/config/utils.ts diff --git a/src/config/discordConfig.ts b/src/config/discordConfig.ts index ef7c8c452..f1bd7b197 100644 --- a/src/config/discordConfig.ts +++ b/src/config/discordConfig.ts @@ -1,9 +1,9 @@ export type DiscordConfigType = { - BOT_TOKEN: string; - ADMIN_CHANNEL_ID: string; - MOD_CHANNEL_ID: string; - ADMIN_ROLE_ID: string; - MOD_ROLE_ID: string; + BOT_TOKEN?: string; + ADMIN_CHANNEL_ID?: string; + MOD_CHANNEL_ID?: string; + ADMIN_ROLE_ID?: string; + MOD_ROLE_ID?: string; }; export const DiscordConfig: Readonly = Object.freeze({ diff --git a/src/config/emailConfig.ts b/src/config/emailConfig.ts index 9f067a419..c701be716 100644 --- a/src/config/emailConfig.ts +++ b/src/config/emailConfig.ts @@ -1,7 +1,7 @@ export type EmailConfigType = { - PROAVALON_EMAIL_ADDRESS_DOMAIN: string; - PROAVALON_EMAIL_ADDRESS: string; - MAILGUN_API_KEY: string; + PROAVALON_EMAIL_ADDRESS_DOMAIN?: string; + PROAVALON_EMAIL_ADDRESS?: string; + MAILGUN_API_KEY?: string; }; export const EmailConfig: Readonly = Object.freeze({ diff --git a/src/config/index.ts b/src/config/index.ts index acc05f851..aa063f261 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -3,6 +3,7 @@ import { DiscordConfig, DiscordConfigType } from './discordConfig'; import { S3Config, S3ConfigType } from './s3Config'; import { EmailConfig, EmailConfigType } from './emailConfig'; import { VpnConfig, VpnConfigType } from './vpnConfig'; +import { getRequiredEnvVariable } from './utils'; type ConfigNew = { ENV: string; @@ -55,13 +56,3 @@ function validateEnv() { return ENV; } - -export function getRequiredEnvVariable(variableName: string) { - const envVariable = process.env[variableName]; - - if (envVariable === undefined || envVariable === '') { - throw new Error(`Missing required environment variable: ${variableName}`); - } - - return envVariable; -} diff --git a/src/config/patreonConfig.ts b/src/config/patreonConfig.ts index 6e23e6448..265f528a4 100644 --- a/src/config/patreonConfig.ts +++ b/src/config/patreonConfig.ts @@ -1,7 +1,7 @@ export type PatreonConfigType = { - CLIENT_ID: string; - CLIENT_SECRET: string; - REDIRECT_URL: string; + CLIENT_ID?: string; + CLIENT_SECRET?: string; + REDIRECT_URL?: string; }; export const PatreonConfig: Readonly = Object.freeze({ diff --git a/src/config/s3Config.ts b/src/config/s3Config.ts index f5994340b..5f7e0fb1c 100644 --- a/src/config/s3Config.ts +++ b/src/config/s3Config.ts @@ -1,3 +1,5 @@ +import { getRequiredEnvVariable } from './utils'; + export type S3ConfigType = { PUBLIC_FILE_LINK_PREFIX: string; BUCKET_NAME: string; @@ -6,14 +8,15 @@ export type S3ConfigType = { }; export const S3Config: Readonly = Object.freeze({ - PUBLIC_FILE_LINK_PREFIX: process.env.S3_PUBLIC_FILE_LINK_PREFIX, + PUBLIC_FILE_LINK_PREFIX: getRequiredEnvVariable('S3_PUBLIC_FILE_LINK_PREFIX'), BUCKET_NAME: validateBucketName(), - REGION: process.env.S3_REGION, - ENDPOINT: process.env.S3_ENDPOINT, + REGION: getRequiredEnvVariable('S3_REGION'), + ENDPOINT: getRequiredEnvVariable('S3_ENDPOINT'), }); function validateBucketName() { - const { NODE_ENV, ENV, S3_BUCKET_NAME } = process.env; + const { NODE_ENV, ENV } = process.env; + const S3_BUCKET_NAME = getRequiredEnvVariable('S3_BUCKET_NAME'); if (NODE_ENV !== 'test') { const expectedBucketNames: { [key: string]: string } = { @@ -25,7 +28,7 @@ function validateBucketName() { if (expectedBucketName && S3_BUCKET_NAME !== expectedBucketName) { throw new Error( - `Invalid env variables: ENV=${ENV} S3_BUCKET_NAME=${S3_BUCKET_NAME}`, + `Invalid env variables: ENV=${ENV} S3_BUCKET_NAME=${S3_BUCKET_NAME} expectedBucketName=${expectedBucketName}`, ); } } diff --git a/src/config/utils.ts b/src/config/utils.ts new file mode 100644 index 000000000..df11368b5 --- /dev/null +++ b/src/config/utils.ts @@ -0,0 +1,9 @@ +export function getRequiredEnvVariable(variableName: string) { + const envVariable = process.env[variableName]; + + if (envVariable === undefined || envVariable === '') { + throw new Error(`Missing required environment variable: ${variableName}`); + } + + return envVariable; +} diff --git a/src/config/vpnConfig.ts b/src/config/vpnConfig.ts index ad154dc03..890058011 100644 --- a/src/config/vpnConfig.ts +++ b/src/config/vpnConfig.ts @@ -1,6 +1,6 @@ export type VpnConfigType = { - VPN_DETECTION_TOKEN: string; - WHITELISTED_VPN_USERNAMES: string; + VPN_DETECTION_TOKEN?: string; + WHITELISTED_VPN_USERNAMES?: string; }; export const VpnConfig: Readonly = Object.freeze({ From 1df6b7b58278fc1c4a36540e4a5f95df36348e74 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 16:57:24 +1000 Subject: [PATCH 37/43] Added required prod variables --- src/config/discordConfig.ts | 12 +++++++----- src/config/emailConfig.ts | 12 +++++++++--- src/config/patreonConfig.ts | 8 +++++--- src/config/utils.ts | 6 ++++++ src/config/vpnConfig.ts | 8 ++++++-- 5 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/config/discordConfig.ts b/src/config/discordConfig.ts index f1bd7b197..9b4455119 100644 --- a/src/config/discordConfig.ts +++ b/src/config/discordConfig.ts @@ -1,3 +1,5 @@ +import { getRequiredEnvVariable, getRequiredProdEnvVariable } from './utils'; + export type DiscordConfigType = { BOT_TOKEN?: string; ADMIN_CHANNEL_ID?: string; @@ -7,9 +9,9 @@ export type DiscordConfigType = { }; export const DiscordConfig: Readonly = Object.freeze({ - BOT_TOKEN: process.env.discord_bot_token, - ADMIN_CHANNEL_ID: process.env.discord_admin_channel_id, - MOD_CHANNEL_ID: process.env.discord_mod_channel_id, - ADMIN_ROLE_ID: process.env.discord_admin_role_id, - MOD_ROLE_ID: process.env.discord_mod_role_id, + BOT_TOKEN: getRequiredProdEnvVariable('discord_bot_token'), + ADMIN_CHANNEL_ID: getRequiredProdEnvVariable('discord_admin_channel_id'), + MOD_CHANNEL_ID: getRequiredProdEnvVariable('discord_mod_channel_id'), + ADMIN_ROLE_ID: getRequiredProdEnvVariable('discord_admin_role_id'), + MOD_ROLE_ID: getRequiredProdEnvVariable('discord_mod_role_id'), }); diff --git a/src/config/emailConfig.ts b/src/config/emailConfig.ts index c701be716..b6f471306 100644 --- a/src/config/emailConfig.ts +++ b/src/config/emailConfig.ts @@ -1,3 +1,5 @@ +import { getRequiredProdEnvVariable } from './utils'; + export type EmailConfigType = { PROAVALON_EMAIL_ADDRESS_DOMAIN?: string; PROAVALON_EMAIL_ADDRESS?: string; @@ -5,7 +7,11 @@ export type EmailConfigType = { }; export const EmailConfig: Readonly = Object.freeze({ - PROAVALON_EMAIL_ADDRESS_DOMAIN: process.env.PROAVALON_EMAIL_ADDRESS_DOMAIN, - PROAVALON_EMAIL_ADDRESS: process.env.PROAVALON_EMAIL_ADDRESS, - MAILGUN_API_KEY: process.env.MAILGUN_API_KEY, + PROAVALON_EMAIL_ADDRESS_DOMAIN: getRequiredProdEnvVariable( + 'PROAVALON_EMAIL_ADDRESS_DOMAIN', + ), + PROAVALON_EMAIL_ADDRESS: getRequiredProdEnvVariable( + 'PROAVALON_EMAIL_ADDRESS', + ), + MAILGUN_API_KEY: getRequiredProdEnvVariable('MAILGUN_API_KEY'), }); diff --git a/src/config/patreonConfig.ts b/src/config/patreonConfig.ts index 265f528a4..d4b5a6570 100644 --- a/src/config/patreonConfig.ts +++ b/src/config/patreonConfig.ts @@ -1,3 +1,5 @@ +import { getRequiredProdEnvVariable } from './utils'; + export type PatreonConfigType = { CLIENT_ID?: string; CLIENT_SECRET?: string; @@ -5,7 +7,7 @@ export type PatreonConfigType = { }; export const PatreonConfig: Readonly = Object.freeze({ - CLIENT_ID: process.env.patreon_client_ID, - CLIENT_SECRET: process.env.patreon_client_secret, - REDIRECT_URL: process.env.patreon_redirectURL, + CLIENT_ID: getRequiredProdEnvVariable('patreon_client_ID'), + CLIENT_SECRET: getRequiredProdEnvVariable('patreon_client_secret'), + REDIRECT_URL: getRequiredProdEnvVariable('patreon_redirectURL'), }); diff --git a/src/config/utils.ts b/src/config/utils.ts index df11368b5..8e3adbeb3 100644 --- a/src/config/utils.ts +++ b/src/config/utils.ts @@ -1,3 +1,9 @@ +export function getRequiredProdEnvVariable(variableName: string) { + return process.env.ENV === `prod` + ? getRequiredEnvVariable(variableName) + : process.env[variableName]; +} + export function getRequiredEnvVariable(variableName: string) { const envVariable = process.env[variableName]; diff --git a/src/config/vpnConfig.ts b/src/config/vpnConfig.ts index 890058011..30774bbf3 100644 --- a/src/config/vpnConfig.ts +++ b/src/config/vpnConfig.ts @@ -1,9 +1,13 @@ +import { getRequiredProdEnvVariable } from './utils'; + export type VpnConfigType = { VPN_DETECTION_TOKEN?: string; WHITELISTED_VPN_USERNAMES?: string; }; export const VpnConfig: Readonly = Object.freeze({ - VPN_DETECTION_TOKEN: process.env.VPN_DETECTION_TOKEN, - WHITELISTED_VPN_USERNAMES: process.env.WHITELISTED_VPN_USERNAMES, + VPN_DETECTION_TOKEN: getRequiredProdEnvVariable('VPN_DETECTION_TOKEN'), + WHITELISTED_VPN_USERNAMES: getRequiredProdEnvVariable( + 'WHITELISTED_VPN_USERNAMES', + ), }); From a09da9212d7fccf78eef90b79a57b79595bf7717 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 17:01:52 +1000 Subject: [PATCH 38/43] Fixed up the port/ip/secret key in app.ts --- src/app.ts | 6 +++--- src/config/index.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app.ts b/src/app.ts index ea40ef3c6..b5a5671a6 100644 --- a/src/app.ts +++ b/src/app.ts @@ -83,7 +83,7 @@ if (config.ENV === 'local') { ); } -const port = config.PORT || 3000; +const port = config.PORT; const dbLoc = config.DATABASE_URL; console.log(`Using database url: ${dbLoc}`); @@ -130,7 +130,7 @@ process }); // authentication -const secretKey = config.MY_SECRET_KEY || 'MySecretKey'; +const secretKey = config.MY_SECRET_KEY; app.use( session({ secret: secretKey, @@ -183,7 +183,7 @@ app.use('/lobby', lobbyRoutes); app.use('/forum', forumRoutes); app.use('/profile', profileRoutes); -const IP = config.IP || '127.0.0.1'; +const IP = config.IP; const server = app.listen(port, () => { console.log(`Server has started on ${IP}:${port}!`); }); diff --git a/src/config/index.ts b/src/config/index.ts index aa063f261..8eba6ef3e 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -27,9 +27,9 @@ export const config: Readonly = Object.freeze({ ENV: validateEnv(), NODE_ENV: process.env.NODE_ENV, SERVER_DOMAIN: process.env.SERVER_DOMAIN, - PORT: process.env.PORT, - IP: process.env.IP, - MY_SECRET_KEY: getRequiredEnvVariable('MY_SECRET_KEY'), + PORT: process.env.PORT || '3000', + IP: process.env.IP || '127.0.0.1', + MY_SECRET_KEY: process.env.MY_SECRET_KEY || 'MySecretKey', GOOGLE_CAPTCHA_KEY: process.env.MY_SECRET_GOOGLE_CAPTCHA_KEY, DATABASE_URL: getRequiredEnvVariable('DATABASEURL'), // TODO-kev: Consider renaming env variable From eea948c408656faa960b2de4a1a588de129f63b4 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 17 Jun 2024 17:07:10 +1000 Subject: [PATCH 39/43] Minor fix --- src/config/utils.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/config/utils.ts b/src/config/utils.ts index 8e3adbeb3..c0ad1775a 100644 --- a/src/config/utils.ts +++ b/src/config/utils.ts @@ -7,7 +7,10 @@ export function getRequiredProdEnvVariable(variableName: string) { export function getRequiredEnvVariable(variableName: string) { const envVariable = process.env[variableName]; - if (envVariable === undefined || envVariable === '') { + if ( + process.env.NODE_ENV !== 'test' && + (envVariable === undefined || envVariable === '') + ) { throw new Error(`Missing required environment variable: ${variableName}`); } From 92b697dd0938f49c66e67a95adf01b251957c6e0 Mon Sep 17 00:00:00 2001 From: Kevin Date: Thu, 27 Jun 2024 18:30:29 +1000 Subject: [PATCH 40/43] Minor update --- src/config/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/config/index.ts b/src/config/index.ts index 8eba6ef3e..21a16e584 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -47,9 +47,7 @@ function validateEnv() { if (process.env.NODE_ENV !== 'test') { if (!VALID_ENVIRONMENTS.has(ENV)) { - // TODO-kev: Prefer the console.error then process exit or throw an error? console.error(`Bad environment variable given: ${ENV}`); - throw new Error(`Invalid settings: ENV=${ENV}`); process.exit(1); } } From 54267312b0f3510c55723c1e647826928c7f16be Mon Sep 17 00:00:00 2001 From: Kevin Date: Thu, 27 Jun 2024 18:42:30 +1000 Subject: [PATCH 41/43] Updated s3 bucket validation --- src/config/s3Config.ts | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/config/s3Config.ts b/src/config/s3Config.ts index 5f7e0fb1c..225c99207 100644 --- a/src/config/s3Config.ts +++ b/src/config/s3Config.ts @@ -15,22 +15,16 @@ export const S3Config: Readonly = Object.freeze({ }); function validateBucketName() { - const { NODE_ENV, ENV } = process.env; const S3_BUCKET_NAME = getRequiredEnvVariable('S3_BUCKET_NAME'); - if (NODE_ENV !== 'test') { - const expectedBucketNames: { [key: string]: string } = { - prod: `proavalon`, - staging: `proavalon-staging`, - }; - - const expectedBucketName = expectedBucketNames[ENV]; - - if (expectedBucketName && S3_BUCKET_NAME !== expectedBucketName) { - throw new Error( - `Invalid env variables: ENV=${ENV} S3_BUCKET_NAME=${S3_BUCKET_NAME} expectedBucketName=${expectedBucketName}`, - ); - } + if ( + (process.env.ENV === 'prod' && S3_BUCKET_NAME !== `proavalon`) || + (process.env.ENV === 'staging' && S3_BUCKET_NAME !== `proavalon-staging`) + ) { + console.error( + `Invalid env variables: ENV=${process.env.ENV} S3_BUCKET_NAME=${S3_BUCKET_NAME}`, + ); + process.exit(1); } return S3_BUCKET_NAME; From 6147795aba2b4fd447328ec9ab75eb4db78c96b4 Mon Sep 17 00:00:00 2001 From: Kevin Date: Thu, 27 Jun 2024 18:49:57 +1000 Subject: [PATCH 42/43] Minor update --- src/config/utils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config/utils.ts b/src/config/utils.ts index c0ad1775a..05ca12729 100644 --- a/src/config/utils.ts +++ b/src/config/utils.ts @@ -11,7 +11,8 @@ export function getRequiredEnvVariable(variableName: string) { process.env.NODE_ENV !== 'test' && (envVariable === undefined || envVariable === '') ) { - throw new Error(`Missing required environment variable: ${variableName}`); + console.error(`Missing required environment variable: ${variableName}`); + process.exit(1); } return envVariable; From 41aebad3266a25fba9dc7c3abe7d7de122a64c2a Mon Sep 17 00:00:00 2001 From: Kevin Date: Thu, 27 Jun 2024 19:09:39 +1000 Subject: [PATCH 43/43] Added port validation --- src/config/index.ts | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/config/index.ts b/src/config/index.ts index 21a16e584..555d8d781 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -9,7 +9,7 @@ type ConfigNew = { ENV: string; NODE_ENV?: string; SERVER_DOMAIN?: string; - PORT?: string; + PORT?: number; IP?: string; MY_SECRET_KEY: string; @@ -27,7 +27,7 @@ export const config: Readonly = Object.freeze({ ENV: validateEnv(), NODE_ENV: process.env.NODE_ENV, SERVER_DOMAIN: process.env.SERVER_DOMAIN, - PORT: process.env.PORT || '3000', + PORT: validatePort(), IP: process.env.IP || '127.0.0.1', MY_SECRET_KEY: process.env.MY_SECRET_KEY || 'MySecretKey', @@ -41,7 +41,7 @@ export const config: Readonly = Object.freeze({ vpn: VpnConfig, }); -function validateEnv() { +function validateEnv(): string { const VALID_ENVIRONMENTS: Set = new Set(['local', 'staging', 'prod']); const ENV = getRequiredEnvVariable('ENV'); @@ -54,3 +54,19 @@ function validateEnv() { return ENV; } + +function validatePort(): number { + if (!process.env.PORT) { + return 3000; + } + + const port = parseInt(process.env.PORT, 10); + + if (isNaN(port) || port < 1 || port > 65535) { + console.error( + `Invalid port number: ${port}. Port must be between 1 and 65535.`, + ); + } + + return port; +}