🔧 Use .env to pass services accounts access and some fixes

This commit is contained in:
ChatonDeAru 2024-03-23 17:52:33 +01:00
parent 772ae1c8b8
commit 74685fa741
No known key found for this signature in database
GPG Key ID: 3CADF765A409F755
9 changed files with 43 additions and 35 deletions

14
.env.example Normal file
View File

@ -0,0 +1,14 @@
## Google Cloud Platform Service Account
GCP_SERVICE_ACCOUNT_PRIVATE_KEY=
GCP_SERVICE_ACCOUNT_CLIENT_ID=
GCP_SERVICE_ACCOUNT_CLIENT_EMAIL=
GSHEET_ID=
## Discord
DISCORD_TOKEN=
DISCORD_CLIENTID=
DISCORD_GUILDID=
## Notifications
FORCE_ORANGE_PUBLIC_VAPID_KEY=
FORCE_ORANGE_PRIVATE_VAPID_KEY=

View File

@ -52,6 +52,7 @@ module.exports = {
"testing-library/no-node-access": "off",
"testing-library/render-result-naming-convention": "off",
"jsx-a11y/label-has-associated-control": "off",
"jsx-a11y/control-has-associated-label": "off",
},
globals: {
__CLIENT__: true,

1
.nvmrc Normal file
View File

@ -0,0 +1 @@
18.12.1

View File

@ -40,8 +40,8 @@
"npm": ">=6"
},
"scripts": {
"dev": "yarn dev:build && nodemon ./public/server",
"ser": "yarn dev:build && node ./public/server",
"dev": "yarn dev:build && nodemon -r dotenv/config ./public/server",
"ser": "yarn dev:build && node -r dotenv/config ./public/server",
"dev:build": "cross-env NODE_ENV=development webpack --config ./webpack/server.config.ts",
"local-start": "cross-env LOCAL=true yarn build && node ./public/server",
"discord-register": "cross-env REGISTER_DISCORD_COMMANDS=true yarn build && node ./public/server",
@ -175,6 +175,7 @@
"compression-webpack-plugin": "^8.0.1",
"css-loader": "^5.2.6",
"css-minimizer-webpack-plugin": "^3.0.2",
"dotenv": "^16.3.1",
"eslint": "^7.14.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-config-prettier": "^8.3.0",

View File

@ -71,7 +71,7 @@ const BoxItem: React.FC<Props> = ({
target="_blank"
rel="noreferrer"
>
<div className={poufpaf ? styles.poufpaf : styles.noPoufpaf}> </div>
<div className={poufpaf ? styles.poufpaf : styles.noPoufpaf}>&nbsp;</div>
</a>
<ul className={styles.knowledgeList}>
{knowledgeChoices.map(({ name, value }) => (

View File

@ -1,7 +1,5 @@
// eslint-disable-next-line max-classes-per-file
import path from "path"
import _, { assign, pick } from "lodash"
import { promises as fs, constants } from "fs"
import { GoogleSpreadsheet, GoogleSpreadsheetWorksheet } from "google-spreadsheet"
import { SheetNames, saveLocalDb, loadLocalDb } from "./localDb"
@ -9,14 +7,12 @@ export { SheetNames } from "./localDb"
// Test write attack with: wget --header='Content-Type:application/json' --post-data='{"prenom":"Pierre","nom":"SCELLES","email":"test@gmail.com","telephone":"0601010101","dejaBenevole":false,"commentaire":""}' http://localhost:3000/PostulantAdd
const CRED_PATH = path.resolve(process.cwd(), "access/gsheets.json")
const { GCP_SERVICE_ACCOUNT_PRIVATE_KEY, GCP_SERVICE_ACCOUNT_CLIENT_EMAIL, GSHEET_ID } = process.env
const REMOTE_UPDATE_DELAY = 120000
const DELAY_BETWEEN_ATTEMPTS = 30000
const DELAY_BETWEEN_FIRST_LOAD = 1500
let creds: string | undefined | null
export type ElementWithId<ElementNoId> = { id: number } & ElementNoId
export const sheetNames = new SheetNames()
@ -25,19 +21,14 @@ export const sheetNames = new SheetNames()
type SheetList = { [sheetName in keyof SheetNames]?: Sheet<object, ElementWithId<object>> }
const sheetList: SheetList = {}
let hasGSheetsAccessReturn: boolean | undefined
export async function hasGSheetsAccess(): Promise<boolean> {
if (hasGSheetsAccessReturn !== undefined) {
return hasGSheetsAccessReturn
}
try {
// eslint-disable-next-line no-bitwise
await fs.access(CRED_PATH, constants.R_OK | constants.W_OK)
hasGSheetsAccessReturn = true
} catch {
hasGSheetsAccessReturn = false
}
return hasGSheetsAccessReturn
export function hasGSheetsAccess(): Promise<boolean> {
return new Promise<boolean>((resolve) => {
if (GCP_SERVICE_ACCOUNT_PRIVATE_KEY && GCP_SERVICE_ACCOUNT_CLIENT_EMAIL) {
resolve(true)
} else {
resolve(false)
}
})
}
export async function checkGSheetsAccess(): Promise<void> {
@ -367,20 +358,12 @@ export class Sheet<
private async getGSheet(attempts = 3): Promise<GoogleSpreadsheetWorksheet | null> {
return tryNTimes(
async () => {
if (creds === undefined) {
if (await hasGSheetsAccess()) {
const credsBuffer = await fs.readFile(CRED_PATH)
creds = credsBuffer?.toString() || null
} else {
creds = null
}
}
if (creds === null) {
return null
}
// Authentication
const doc = new GoogleSpreadsheet("1p8TDSNlgKC7sm1a_wX44NrkpWEH3-Zey1O2ZjYfPsn4")
await doc.useServiceAccountAuth(JSON.parse(creds))
const doc = new GoogleSpreadsheet(GSHEET_ID)
await doc.useServiceAccountAuth({
client_email: GCP_SERVICE_ACCOUNT_CLIENT_EMAIL || "",
private_key: GCP_SERVICE_ACCOUNT_PRIVATE_KEY || "",
})
await doc.loadInfo()
return doc.sheetsByTitle[this.sheetName]
},

View File

@ -45,7 +45,7 @@ export default async (req: Request, res: Response, next: NextFunction): Promise<
// Load data from server-side first
await loadBranchData()
const statsFile = path.resolve(process.cwd(), "public/loadable-stats")
const statsFile = path.resolve(process.cwd(), "public/loadable-stats.json")
const extractor = new ChunkExtractor({ statsFile })
const staticContext: Record<string, any> = {}

View File

@ -30,6 +30,9 @@ declare namespace NodeJS {
SENDGRID_API_KEY?: string
FORCE_ORANGE_PUBLIC_VAPID_KEY?: string
FORCE_ORANGE_PRIVATE_VAPID_KEY?: string
GCP_SERVICE_ACCOUNT_PRIVATE_KEY?: string
GCP_SERVICE_ACCOUNT_CLIENT_EMAIL?: string
GSHEET_ID?: string
}
}

View File

@ -4524,6 +4524,11 @@ domutils@^3.0.1:
domelementtype "^2.3.0"
domhandler "^5.0.3"
dotenv@^16.3.1:
version "16.3.1"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e"
integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==
download@^6.2.2:
version "6.2.5"
resolved "https://registry.yarnpkg.com/download/-/download-6.2.5.tgz#acd6a542e4cd0bb42ca70cfc98c9e43b07039714"