From 2d85ed1bfebc8e44c9a4f31ad6b83bd99d629115 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Guti=C3=A9rrez=20Hermoso?= Date: Mon, 22 Jul 2024 09:47:52 -0400 Subject: [PATCH] config: new API endpoint This adds PATCH and GET endpoints to handle `config.json`. --- app/server/lib/ConfigBackendAPI.ts | 35 ++++++++++++++++++++++++++++++ app/server/lib/FlexServer.ts | 11 +++++++++- app/server/mergedServerMain.ts | 1 + 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 app/server/lib/ConfigBackendAPI.ts diff --git a/app/server/lib/ConfigBackendAPI.ts b/app/server/lib/ConfigBackendAPI.ts new file mode 100644 index 00000000..afb475fa --- /dev/null +++ b/app/server/lib/ConfigBackendAPI.ts @@ -0,0 +1,35 @@ +import * as express from 'express'; +import {expressWrap} from 'app/server/lib/expressWrap'; + +import {getGlobalConfig} from 'app/server/lib/globalConfig'; + +import log from "app/server/lib/log"; + +export class ConfigBackendAPI { + public addEndpoints(app: express.Express, requireInstallAdmin: express.RequestHandler) { + app.get('/api/config/:key', requireInstallAdmin, expressWrap((req, resp) => { + log.debug('config: requesting configuration', req.params); + + // Only one key is valid for now + if (req.params.key === 'edition') { + resp.send({value: getGlobalConfig().edition.get()}); + } else { + resp.status(404).send({ error: 'Configuration key not found.' }); + } + })); + + app.patch('/api/config', requireInstallAdmin, expressWrap(async (req, resp) => { + const config = req.body.config; + log.debug('config: received new configuration item', config); + + // Only one key is valid for now + if(config.edition !== undefined) { + await getGlobalConfig().edition.set(config.edition); + + resp.send({ msg: 'ok' }); + } else { + resp.status(400).send({ error: 'Invalid configuration key' }); + } + })); + } +} diff --git a/app/server/lib/FlexServer.ts b/app/server/lib/FlexServer.ts index 06e9b855..0b5f9ea8 100644 --- a/app/server/lib/FlexServer.ts +++ b/app/server/lib/FlexServer.ts @@ -87,7 +87,8 @@ import {AddressInfo} from 'net'; import fetch from 'node-fetch'; import * as path from 'path'; import * as serveStatic from "serve-static"; -import {IGristCoreConfig} from "./configCore"; +import {ConfigBackendAPI} from "app/server/lib/ConfigBackendAPI"; +import {IGristCoreConfig} from "app/server/lib/configCore"; // Health checks are a little noisy in the logs, so we don't show them all. // We show the first N health checks: @@ -1948,6 +1949,14 @@ export class FlexServer implements GristServer { })); } + public addConfigEndpoints() { + // Need to be an admin to change the Grist config + const requireInstallAdmin = this.getInstallAdmin().getMiddlewareRequireAdmin(); + + const configBackendAPI = new ConfigBackendAPI(); + configBackendAPI.addEndpoints(this.app, requireInstallAdmin); + } + // Get the HTML template sent for document pages. public async getDocTemplate(): Promise { const page = await fse.readFile(path.join(getAppPathTo(this.appRoot, 'static'), diff --git a/app/server/mergedServerMain.ts b/app/server/mergedServerMain.ts index 466eddaf..1bef819d 100644 --- a/app/server/mergedServerMain.ts +++ b/app/server/mergedServerMain.ts @@ -165,6 +165,7 @@ export async function main(port: number, serverTypes: ServerType[], server.addLogEndpoint(); server.addGoogleAuthEndpoint(); server.addInstallEndpoints(); + server.addConfigEndpoints(); } if (includeDocs) {