mirror of
https://github.com/Paris-est-Ludique/intranet.git
synced 2025-06-09 00:54:21 +02:00
Support running without api access for dev
This commit is contained in:
parent
65d9439308
commit
aa76e33c54
@ -15,5 +15,5 @@ export default {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
JWT_SECRET: "RblQqA6uF#msq2312bebf2FLFn4XzWQ6dttXSJwBX#?gL2JWf!",
|
DEV_JWT_SECRET: "fakeqA6uF#msq2312bebf2FLFn4XzWQ6dttXSJwBX#?gL2JWf!",
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ import devServer from "./devServer"
|
|||||||
import ssr from "./ssr"
|
import ssr from "./ssr"
|
||||||
|
|
||||||
import certbotRouter from "../routes/certbot"
|
import certbotRouter from "../routes/certbot"
|
||||||
import { secure } from "./secure"
|
import { hasSecret, secure } from "./secure"
|
||||||
import { javGameListGet } from "./gsheets/javGames"
|
import { javGameListGet } from "./gsheets/javGames"
|
||||||
import { preVolunteerAdd, preVolunteerCountGet } from "./gsheets/preVolunteers"
|
import { preVolunteerAdd, preVolunteerCountGet } from "./gsheets/preVolunteers"
|
||||||
import { teamListGet } from "./gsheets/teams"
|
import { teamListGet } from "./gsheets/teams"
|
||||||
@ -34,6 +34,7 @@ import config from "../config"
|
|||||||
import notificationsSubscribe from "./notificationsSubscribe"
|
import notificationsSubscribe from "./notificationsSubscribe"
|
||||||
import checkAccess from "./checkAccess"
|
import checkAccess from "./checkAccess"
|
||||||
import { hasGSheetsAccess } from "./gsheets/accessors"
|
import { hasGSheetsAccess } from "./gsheets/accessors"
|
||||||
|
import { addStatus, showStatusAt } from "./status"
|
||||||
|
|
||||||
checkAccess()
|
checkAccess()
|
||||||
|
|
||||||
@ -122,6 +123,10 @@ if (validCertPath) {
|
|||||||
const httpsOptions = _.mapValues(validCertPath, (pemPath: string) => fs.readFileSync(pemPath))
|
const httpsOptions = _.mapValues(validCertPath, (pemPath: string) => fs.readFileSync(pemPath))
|
||||||
|
|
||||||
servers.push({ protocol: "https", server: https.createServer(httpsOptions, app) })
|
servers.push({ protocol: "https", server: https.createServer(httpsOptions, app) })
|
||||||
|
|
||||||
|
showStatusAt(6)
|
||||||
|
} else {
|
||||||
|
showStatusAt(5)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -139,7 +144,7 @@ servers.forEach(({ protocol, server }) => {
|
|||||||
|
|
||||||
function onError(error: any) {
|
function onError(error: any) {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error(chalk.red(`==> 😭 OMG!!! ${error}`))
|
addStatus("Server listening:", chalk.red(`==> 😭 OMG!!! ${error}`))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,13 +155,35 @@ function onError(error: any) {
|
|||||||
function onListening(server: any) {
|
function onListening(server: any) {
|
||||||
const addr = server.address()
|
const addr = server.address()
|
||||||
const bind = typeof addr === "string" ? `pipe ${addr}` : `port ${addr.port}`
|
const bind = typeof addr === "string" ? `pipe ${addr}` : `port ${addr.port}`
|
||||||
console.error(chalk.green(`\nServer listening on ${bind}`))
|
addStatus("Server listening:", chalk.green(`✅ ${bind}`))
|
||||||
}
|
}
|
||||||
|
|
||||||
hasGSheetsAccess().then((hasApiAccess: boolean) => {
|
hasGSheetsAccess().then((hasApiAccess: boolean) => {
|
||||||
if (hasApiAccess) {
|
if (hasApiAccess) {
|
||||||
console.error(chalk.green(`Database: remote Google Sheet`))
|
addStatus("Database:", chalk.green(`✅ online from Google Sheet`))
|
||||||
} else {
|
} else {
|
||||||
console.error(chalk.green(`Database: local db`))
|
addStatus("Database:", chalk.blue(`🚧 offline, simulated from local db file`))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const hasSendGridApiAccess = !!process.env.SENDGRID_API_KEY
|
||||||
|
if (hasSendGridApiAccess) {
|
||||||
|
addStatus("Emailing:", chalk.green(`✅ online through SendGrid`))
|
||||||
|
} else {
|
||||||
|
addStatus("Emailing:", chalk.blue(`🚧 offline, simulated`))
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasPushNotifAccess = !!process.env.FORCE_ORANGE_PUBLIC_VAPID_KEY
|
||||||
|
if (hasPushNotifAccess) {
|
||||||
|
addStatus("Push notif:", chalk.green(`✅ online with a Vapid key`))
|
||||||
|
} else {
|
||||||
|
addStatus("Push notif:", chalk.blue(`🚧 offline, simulated`))
|
||||||
|
}
|
||||||
|
|
||||||
|
hasSecret().then((has: boolean) => {
|
||||||
|
if (has) {
|
||||||
|
addStatus("JWT secret:", chalk.green(`✅ prod private one from file`))
|
||||||
|
} else {
|
||||||
|
addStatus("JWT secret:", chalk.blue(`🚧 dev public fake one from config`))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -3,7 +3,8 @@ import webpush from "web-push"
|
|||||||
|
|
||||||
const publicKey = process.env.FORCE_ORANGE_PUBLIC_VAPID_KEY
|
const publicKey = process.env.FORCE_ORANGE_PUBLIC_VAPID_KEY
|
||||||
const privateKey = process.env.FORCE_ORANGE_PRIVATE_VAPID_KEY
|
const privateKey = process.env.FORCE_ORANGE_PRIVATE_VAPID_KEY
|
||||||
if (publicKey && privateKey) {
|
const hasPushAccess = publicKey && privateKey
|
||||||
|
if (hasPushAccess) {
|
||||||
webpush.setVapidDetails("mailto: contact@parisestludique.fr", publicKey, privateKey)
|
webpush.setVapidDetails("mailto: contact@parisestludique.fr", publicKey, privateKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,10 +19,19 @@ export default function notificationsSubscribe(
|
|||||||
title: "Hello!",
|
title: "Hello!",
|
||||||
body: "It works.",
|
body: "It works.",
|
||||||
})
|
})
|
||||||
webpush
|
|
||||||
.sendNotification(subscription, payload)
|
if (hasPushAccess) {
|
||||||
.then((result) => console.log(result))
|
webpush
|
||||||
.catch((e) => console.log(e.stack))
|
.sendNotification(subscription, payload)
|
||||||
|
.then((result) => console.log(result))
|
||||||
|
.catch((e) => console.log(e.stack))
|
||||||
|
} else {
|
||||||
|
console.error(
|
||||||
|
`Fake sending push notif to ${JSON.stringify(subscription)} of ${JSON.stringify(
|
||||||
|
payload
|
||||||
|
)})}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
response.status(200).json({ success: true })
|
response.status(200).json({ success: true })
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { NextFunction, Request, Response } from "express"
|
import { NextFunction, Request, Response } from "express"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import { promises as fs } from "fs"
|
import { constants, promises as fs } from "fs"
|
||||||
import { verify, sign } from "jsonwebtoken"
|
import { verify, sign } from "jsonwebtoken"
|
||||||
|
|
||||||
import config from "../config"
|
import config from "../config"
|
||||||
@ -8,6 +8,7 @@ import config from "../config"
|
|||||||
type AuthorizedRequest = Request & { headers: { authorization: string } }
|
type AuthorizedRequest = Request & { headers: { authorization: string } }
|
||||||
|
|
||||||
let cachedSecret: string
|
let cachedSecret: string
|
||||||
|
const SECRET_PATH = path.resolve(process.cwd(), "access/jwt_secret.json")
|
||||||
getSecret() // Necessary until we can make async express middleware
|
getSecret() // Necessary until we can make async express middleware
|
||||||
|
|
||||||
export function secure(request: AuthorizedRequest, response: Response, next: NextFunction): void {
|
export function secure(request: AuthorizedRequest, response: Response, next: NextFunction): void {
|
||||||
@ -35,15 +36,28 @@ export function secure(request: AuthorizedRequest, response: Response, next: Nex
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let hasSecretReturn: boolean | undefined
|
||||||
|
export async function hasSecret(): Promise<boolean> {
|
||||||
|
if (hasSecretReturn !== undefined) {
|
||||||
|
return hasSecretReturn
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line no-bitwise
|
||||||
|
await fs.access(SECRET_PATH, constants.R_OK | constants.W_OK)
|
||||||
|
hasSecretReturn = true
|
||||||
|
} catch {
|
||||||
|
hasSecretReturn = false
|
||||||
|
}
|
||||||
|
return hasSecretReturn
|
||||||
|
}
|
||||||
|
|
||||||
async function getSecret() {
|
async function getSecret() {
|
||||||
if (!cachedSecret) {
|
if (!cachedSecret) {
|
||||||
const SECRET_PATH = path.resolve(process.cwd(), "access/jwt_secret.json")
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const secretContent = await fs.readFile(SECRET_PATH)
|
const secretContent = await fs.readFile(SECRET_PATH)
|
||||||
cachedSecret = secretContent && JSON.parse(secretContent.toString()).secret
|
cachedSecret = secretContent && JSON.parse(secretContent.toString()).secret
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
cachedSecret = config.JWT_SECRET
|
cachedSecret = config.DEV_JWT_SECRET
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
src/server/status.ts
Normal file
20
src/server/status.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
const messages: string[][] = []
|
||||||
|
let _messageCount = 0
|
||||||
|
|
||||||
|
export function addStatus(...messageParams: string[]): void {
|
||||||
|
messages.push(messageParams)
|
||||||
|
if (messages.length === _messageCount) {
|
||||||
|
showStatus()
|
||||||
|
} else if (messages.length > _messageCount) {
|
||||||
|
console.error(...messageParams)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showStatus(): void {
|
||||||
|
console.error("")
|
||||||
|
messages.forEach((messageParams) => console.error(...messageParams))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function showStatusAt(messageCount: number): void {
|
||||||
|
_messageCount = messageCount
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user