mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-06-09 09:04:20 +02:00
Add local JSON DB
This commit is contained in:
parent
1d004e7052
commit
1011a293d0
1
.gitignore
vendored
1
.gitignore
vendored
@ -14,6 +14,7 @@ public/*
|
|||||||
# Access
|
# Access
|
||||||
access/gsheets.json
|
access/gsheets.json
|
||||||
access/jwt_secret.json
|
access/jwt_secret.json
|
||||||
|
access/db.json
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
5
src/server/checkAccess.ts
Executable file
5
src/server/checkAccess.ts
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
import { checkGSheetsAccess } from "./gsheets/accessors"
|
||||||
|
|
||||||
|
export default async function checkAccess(): Promise<void> {
|
||||||
|
checkGSheetsAccess()
|
||||||
|
}
|
@ -1,16 +1,21 @@
|
|||||||
// eslint-disable-next-line max-classes-per-file
|
// eslint-disable-next-line max-classes-per-file
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import _ from "lodash"
|
import _ from "lodash"
|
||||||
import { promises as fs } from "fs"
|
import { promises as fs, constants } from "fs"
|
||||||
import { GoogleSpreadsheet, GoogleSpreadsheetWorksheet } from "google-spreadsheet"
|
import { GoogleSpreadsheet, GoogleSpreadsheetWorksheet } from "google-spreadsheet"
|
||||||
|
|
||||||
// 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/PreVolunteerAdd
|
// 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/PreVolunteerAdd
|
||||||
|
|
||||||
const CRED_PATH = path.resolve(process.cwd(), "access/gsheets.json")
|
const CRED_PATH = path.resolve(process.cwd(), "access/gsheets.json")
|
||||||
|
const DB_PATH = path.resolve(process.cwd(), "access/db.json")
|
||||||
|
|
||||||
const REMOTE_UPDATE_DELAY = 40000
|
const REMOTE_UPDATE_DELAY = 40000
|
||||||
const DELAY_AFTER_QUERY = 2000
|
const DELAY_AFTER_QUERY = 2000
|
||||||
|
|
||||||
|
let creds: string | undefined | null
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
let localDb: { [sheetName in keyof SheetNames]?: object[] | undefined } = {}
|
||||||
|
|
||||||
export type ElementWithId<ElementNoId> = { id: number } & ElementNoId
|
export type ElementWithId<ElementNoId> = { id: number } & ElementNoId
|
||||||
|
|
||||||
export class SheetNames {
|
export class SheetNames {
|
||||||
@ -28,6 +33,26 @@ 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 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 async function checkGSheetsAccess(): Promise<void> {
|
||||||
|
if (!(await hasGSheetsAccess())) {
|
||||||
|
console.error(`Google Sheets: no creds found, loading local database ${DB_PATH} instead`)
|
||||||
|
}
|
||||||
|
}
|
||||||
export function getSheet<
|
export function getSheet<
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
ElementNoId extends object,
|
ElementNoId extends object,
|
||||||
@ -83,7 +108,7 @@ export class Sheet<
|
|||||||
(englishProp: string) => (specimen as any)[englishProp]
|
(englishProp: string) => (specimen as any)[englishProp]
|
||||||
) as Element
|
) as Element
|
||||||
|
|
||||||
setTimeout(() => this.dbLoad(), 100 * Object.values(sheetList).length)
|
setTimeout(() => this.dbFirstLoad(), 100 * Object.values(sheetList).length)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getList(): Promise<Element[] | undefined> {
|
async getList(): Promise<Element[] | undefined> {
|
||||||
@ -91,9 +116,10 @@ export class Sheet<
|
|||||||
return JSON.parse(JSON.stringify(this._state))
|
return JSON.parse(JSON.stringify(this._state))
|
||||||
}
|
}
|
||||||
|
|
||||||
setList(newState: Element[] | undefined): void {
|
async setList(newState: Element[] | undefined): Promise<void> {
|
||||||
this._state = JSON.parse(JSON.stringify(newState))
|
this._state = JSON.parse(JSON.stringify(newState))
|
||||||
this.modifiedSinceSave = true
|
this.modifiedSinceSave = true
|
||||||
|
this.localDbSave()
|
||||||
}
|
}
|
||||||
|
|
||||||
async nextId(): Promise<number> {
|
async nextId(): Promise<number> {
|
||||||
@ -147,6 +173,15 @@ export class Sheet<
|
|||||||
} else {
|
} else {
|
||||||
this.dbLoad()
|
this.dbLoad()
|
||||||
}
|
}
|
||||||
|
if (__DEV__) {
|
||||||
|
this.localDbSave()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async localDbSave(): Promise<void> {
|
||||||
|
localDb[this.name] = this._state
|
||||||
|
const jsonDB = __DEV__ ? JSON.stringify(localDb, null, 2) : JSON.stringify(localDb)
|
||||||
|
await fs.writeFile(DB_PATH, jsonDB)
|
||||||
}
|
}
|
||||||
|
|
||||||
dbSave(): void {
|
dbSave(): void {
|
||||||
@ -174,12 +209,36 @@ export class Sheet<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async dbFirstLoad(): Promise<void> {
|
||||||
|
if (await hasGSheetsAccess()) {
|
||||||
|
this.dbLoad()
|
||||||
|
} else if (_.isEmpty(localDb)) {
|
||||||
|
let stringifiedDb
|
||||||
|
try {
|
||||||
|
stringifiedDb = await fs.readFile(DB_PATH)
|
||||||
|
} catch {
|
||||||
|
console.error(`Error: Found no DB file at ${DB_PATH}`)
|
||||||
|
}
|
||||||
|
if (stringifiedDb) {
|
||||||
|
localDb = JSON.parse(stringifiedDb.toString())
|
||||||
|
if (localDb[this.name]) {
|
||||||
|
this._state = localDb[this.name] as Element[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.dbLoad()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async dbSaveAsync(): Promise<void> {
|
private async dbSaveAsync(): Promise<void> {
|
||||||
if (!this._state) {
|
if (!this._state) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const sheet = await this.getGSheet()
|
const sheet = await this.getGSheet()
|
||||||
|
|
||||||
|
if (!sheet) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Load sheet into an array of objects
|
// Load sheet into an array of objects
|
||||||
const rows = await sheet.getRows()
|
const rows = await sheet.getRows()
|
||||||
await delayDBAccess()
|
await delayDBAccess()
|
||||||
@ -245,6 +304,10 @@ export class Sheet<
|
|||||||
type StringifiedElement = Record<keyof Element, string>
|
type StringifiedElement = Record<keyof Element, string>
|
||||||
const sheet = await this.getGSheet()
|
const sheet = await this.getGSheet()
|
||||||
|
|
||||||
|
if (!sheet) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Load sheet into an array of objects
|
// Load sheet into an array of objects
|
||||||
const rows = (await sheet.getRows()) as StringifiedElement[]
|
const rows = (await sheet.getRows()) as StringifiedElement[]
|
||||||
await delayDBAccess()
|
await delayDBAccess()
|
||||||
@ -275,11 +338,21 @@ export class Sheet<
|
|||||||
this._state = elements
|
this._state = elements
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getGSheet(): Promise<GoogleSpreadsheetWorksheet> {
|
private async getGSheet(): Promise<GoogleSpreadsheetWorksheet | null> {
|
||||||
const doc = new GoogleSpreadsheet("1pMMKcYx6NXLOqNn6pLHJTPMTOLRYZmSNg2QQcAu7-Pw")
|
if (creds === undefined) {
|
||||||
const creds = await fs.readFile(CRED_PATH)
|
if (await hasGSheetsAccess()) {
|
||||||
|
const credsBuffer = await fs.readFile(CRED_PATH)
|
||||||
|
creds = credsBuffer?.toString() || null
|
||||||
|
} else {
|
||||||
|
creds = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (creds === null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
// Authentication
|
// Authentication
|
||||||
await doc.useServiceAccountAuth(JSON.parse(creds.toString()))
|
const doc = new GoogleSpreadsheet("1pMMKcYx6NXLOqNn6pLHJTPMTOLRYZmSNg2QQcAu7-Pw")
|
||||||
|
await doc.useServiceAccountAuth(JSON.parse(creds))
|
||||||
await doc.loadInfo()
|
await doc.loadInfo()
|
||||||
return doc.sheetsByTitle[this.sheetName]
|
return doc.sheetsByTitle[this.sheetName]
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,9 @@ import {
|
|||||||
} from "./gsheets/volunteers"
|
} from "./gsheets/volunteers"
|
||||||
import config from "../config"
|
import config from "../config"
|
||||||
import notificationsSubscribe from "./notificationsSubscribe"
|
import notificationsSubscribe from "./notificationsSubscribe"
|
||||||
|
import checkAccess from "./checkAccess"
|
||||||
|
|
||||||
|
checkAccess()
|
||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user