mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-06-10 01:24:20 +02:00
🔧 Use .env to pass services accounts access and some fixes
This commit is contained in:
parent
772ae1c8b8
commit
74685fa741
14
.env.example
Normal file
14
.env.example
Normal 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=
|
@ -52,6 +52,7 @@ module.exports = {
|
|||||||
"testing-library/no-node-access": "off",
|
"testing-library/no-node-access": "off",
|
||||||
"testing-library/render-result-naming-convention": "off",
|
"testing-library/render-result-naming-convention": "off",
|
||||||
"jsx-a11y/label-has-associated-control": "off",
|
"jsx-a11y/label-has-associated-control": "off",
|
||||||
|
"jsx-a11y/control-has-associated-label": "off",
|
||||||
},
|
},
|
||||||
globals: {
|
globals: {
|
||||||
__CLIENT__: true,
|
__CLIENT__: true,
|
||||||
|
@ -40,8 +40,8 @@
|
|||||||
"npm": ">=6"
|
"npm": ">=6"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "yarn dev:build && nodemon ./public/server",
|
"dev": "yarn dev:build && nodemon -r dotenv/config ./public/server",
|
||||||
"ser": "yarn dev:build && node ./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",
|
"dev:build": "cross-env NODE_ENV=development webpack --config ./webpack/server.config.ts",
|
||||||
"local-start": "cross-env LOCAL=true yarn build && node ./public/server",
|
"local-start": "cross-env LOCAL=true yarn build && node ./public/server",
|
||||||
"discord-register": "cross-env REGISTER_DISCORD_COMMANDS=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",
|
"compression-webpack-plugin": "^8.0.1",
|
||||||
"css-loader": "^5.2.6",
|
"css-loader": "^5.2.6",
|
||||||
"css-minimizer-webpack-plugin": "^3.0.2",
|
"css-minimizer-webpack-plugin": "^3.0.2",
|
||||||
|
"dotenv": "^16.3.1",
|
||||||
"eslint": "^7.14.0",
|
"eslint": "^7.14.0",
|
||||||
"eslint-config-airbnb": "^18.2.1",
|
"eslint-config-airbnb": "^18.2.1",
|
||||||
"eslint-config-prettier": "^8.3.0",
|
"eslint-config-prettier": "^8.3.0",
|
||||||
|
@ -71,7 +71,7 @@ const BoxItem: React.FC<Props> = ({
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
<div className={poufpaf ? styles.poufpaf : styles.noPoufpaf}> </div>
|
<div className={poufpaf ? styles.poufpaf : styles.noPoufpaf}> </div>
|
||||||
</a>
|
</a>
|
||||||
<ul className={styles.knowledgeList}>
|
<ul className={styles.knowledgeList}>
|
||||||
{knowledgeChoices.map(({ name, value }) => (
|
{knowledgeChoices.map(({ name, value }) => (
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
// eslint-disable-next-line max-classes-per-file
|
// eslint-disable-next-line max-classes-per-file
|
||||||
import path from "path"
|
|
||||||
import _, { assign, pick } from "lodash"
|
import _, { assign, pick } from "lodash"
|
||||||
import { promises as fs, constants } from "fs"
|
|
||||||
import { GoogleSpreadsheet, GoogleSpreadsheetWorksheet } from "google-spreadsheet"
|
import { GoogleSpreadsheet, GoogleSpreadsheetWorksheet } from "google-spreadsheet"
|
||||||
import { SheetNames, saveLocalDb, loadLocalDb } from "./localDb"
|
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
|
// 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 REMOTE_UPDATE_DELAY = 120000
|
||||||
const DELAY_BETWEEN_ATTEMPTS = 30000
|
const DELAY_BETWEEN_ATTEMPTS = 30000
|
||||||
const DELAY_BETWEEN_FIRST_LOAD = 1500
|
const DELAY_BETWEEN_FIRST_LOAD = 1500
|
||||||
|
|
||||||
let creds: string | undefined | null
|
|
||||||
|
|
||||||
export type ElementWithId<ElementNoId> = { id: number } & ElementNoId
|
export type ElementWithId<ElementNoId> = { id: number } & ElementNoId
|
||||||
|
|
||||||
export const sheetNames = new SheetNames()
|
export const sheetNames = new SheetNames()
|
||||||
@ -25,19 +21,14 @@ export const sheetNames = new SheetNames()
|
|||||||
type SheetList = { [sheetName in keyof SheetNames]?: Sheet<object, ElementWithId<object>> }
|
type SheetList = { [sheetName in keyof SheetNames]?: Sheet<object, ElementWithId<object>> }
|
||||||
const sheetList: SheetList = {}
|
const sheetList: SheetList = {}
|
||||||
|
|
||||||
let hasGSheetsAccessReturn: boolean | undefined
|
export function hasGSheetsAccess(): Promise<boolean> {
|
||||||
export async function hasGSheetsAccess(): Promise<boolean> {
|
return new Promise<boolean>((resolve) => {
|
||||||
if (hasGSheetsAccessReturn !== undefined) {
|
if (GCP_SERVICE_ACCOUNT_PRIVATE_KEY && GCP_SERVICE_ACCOUNT_CLIENT_EMAIL) {
|
||||||
return hasGSheetsAccessReturn
|
resolve(true)
|
||||||
}
|
} else {
|
||||||
try {
|
resolve(false)
|
||||||
// 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 async function checkGSheetsAccess(): Promise<void> {
|
export async function checkGSheetsAccess(): Promise<void> {
|
||||||
@ -367,20 +358,12 @@ export class Sheet<
|
|||||||
private async getGSheet(attempts = 3): Promise<GoogleSpreadsheetWorksheet | null> {
|
private async getGSheet(attempts = 3): Promise<GoogleSpreadsheetWorksheet | null> {
|
||||||
return tryNTimes(
|
return tryNTimes(
|
||||||
async () => {
|
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
|
// Authentication
|
||||||
const doc = new GoogleSpreadsheet("1p8TDSNlgKC7sm1a_wX44NrkpWEH3-Zey1O2ZjYfPsn4")
|
const doc = new GoogleSpreadsheet(GSHEET_ID)
|
||||||
await doc.useServiceAccountAuth(JSON.parse(creds))
|
await doc.useServiceAccountAuth({
|
||||||
|
client_email: GCP_SERVICE_ACCOUNT_CLIENT_EMAIL || "",
|
||||||
|
private_key: GCP_SERVICE_ACCOUNT_PRIVATE_KEY || "",
|
||||||
|
})
|
||||||
await doc.loadInfo()
|
await doc.loadInfo()
|
||||||
return doc.sheetsByTitle[this.sheetName]
|
return doc.sheetsByTitle[this.sheetName]
|
||||||
},
|
},
|
||||||
|
@ -45,7 +45,7 @@ export default async (req: Request, res: Response, next: NextFunction): Promise<
|
|||||||
// Load data from server-side first
|
// Load data from server-side first
|
||||||
await loadBranchData()
|
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 extractor = new ChunkExtractor({ statsFile })
|
||||||
|
|
||||||
const staticContext: Record<string, any> = {}
|
const staticContext: Record<string, any> = {}
|
||||||
|
3
src/types/index.d.ts
vendored
3
src/types/index.d.ts
vendored
@ -30,6 +30,9 @@ declare namespace NodeJS {
|
|||||||
SENDGRID_API_KEY?: string
|
SENDGRID_API_KEY?: string
|
||||||
FORCE_ORANGE_PUBLIC_VAPID_KEY?: string
|
FORCE_ORANGE_PUBLIC_VAPID_KEY?: string
|
||||||
FORCE_ORANGE_PRIVATE_VAPID_KEY?: string
|
FORCE_ORANGE_PRIVATE_VAPID_KEY?: string
|
||||||
|
GCP_SERVICE_ACCOUNT_PRIVATE_KEY?: string
|
||||||
|
GCP_SERVICE_ACCOUNT_CLIENT_EMAIL?: string
|
||||||
|
GSHEET_ID?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4524,6 +4524,11 @@ domutils@^3.0.1:
|
|||||||
domelementtype "^2.3.0"
|
domelementtype "^2.3.0"
|
||||||
domhandler "^5.0.3"
|
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:
|
download@^6.2.2:
|
||||||
version "6.2.5"
|
version "6.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/download/-/download-6.2.5.tgz#acd6a542e4cd0bb42ca70cfc98c9e43b07039714"
|
resolved "https://registry.yarnpkg.com/download/-/download-6.2.5.tgz#acd6a542e4cd0bb42ca70cfc98c9e43b07039714"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user