Skip to content

Commit

Permalink
partial rework of config to use local object instead of import where …
Browse files Browse the repository at this point in the history
…possible
  • Loading branch information
sdumetz committed Feb 12, 2024
1 parent 3ec8f76 commit 12405fc
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 14 deletions.
4 changes: 2 additions & 2 deletions source/server/routes/api/v1/admin/mailtest.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Request, Response } from "express";
import sendmail from "../../../../utils/mails/send.js";
import { getUser } from "../../../../utils/locals.js";
import config from "../../../../utils/config.js";
import { getLocals, getUser } from "../../../../utils/locals.js";
import { BadRequestError } from "../../../../utils/errors.js";

/**
Expand All @@ -10,6 +9,7 @@ import { BadRequestError } from "../../../../utils/errors.js";
* This is a protected route and requires admin privileges
*/
export default async function handleMailtest(req :Request, res :Response){
const {config} = getLocals(req);
const {username :requester, email:to} = getUser(req);
if(!to){
throw new BadRequestError("No email address found for user "+ requester);
Expand Down
4 changes: 2 additions & 2 deletions source/server/routes/api/v1/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createHmac } from "crypto";
import { Request, RequestHandler, Response } from "express";
import User, { SafeUser } from "../../../auth/User.js";
import { BadRequestError, ForbiddenError, NotFoundError, UnauthorizedError } from "../../../utils/errors.js";
import { AppLocals, getHost, getUser, getUserManager } from "../../../utils/locals.js";
import { AppLocals, getHost, getLocals, getUser, getUserManager } from "../../../utils/locals.js";
import sendmail from "../../../utils/mails/send.js";
/**
*
Expand Down Expand Up @@ -122,7 +122,7 @@ export async function sendLoginLink(req :Request, res :Response){
);

let lang = "fr";
const mail_content = await (res.app.locals as AppLocals).templates.render(`emails/connection_${lang}`, {
const mail_content = await getLocals(req).templates.render(`emails/connection_${lang}`, {
name: user.username,
lang: "fr",
url: link.toString()
Expand Down
4 changes: 2 additions & 2 deletions source/server/routes/scenes/propfind.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Request, RequestHandler, Response } from "express";
import xml from 'xml-js';
import path from "path";
import { AppLocals, getHost, getUser } from "../../utils/locals.js";
import { AppLocals, getHost, getLocals, getUser } from "../../utils/locals.js";
import Vfs, { FileProps, ItemProps } from "../../vfs/index.js";

interface ElementProps{
Expand Down Expand Up @@ -198,7 +198,7 @@ async function getScenes(vfs :Vfs, rootUrl:URL, recurse :number, user_id ?:numbe
export async function handlePropfind(req :Request, res:Response){
let u = getUser(req);
const {scene:scene_name} = req.params;
const {vfs} = req.app.locals as AppLocals;
const {vfs} = getLocals(req);
let recurse = parseInt(req.get("Depth")??"-1");
if(!Number.isSafeInteger(recurse)) throw new Error("Invalid Depth header : "+req.get("Depth"));

Expand Down
1 change: 1 addition & 0 deletions source/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export default async function createServer(config = defaultConfig) :Promise<expr
fileDir: config.files_dir,
vfs,
templates,
config,
}) as AppLocals;

app.use(cookieSession({
Expand Down
14 changes: 10 additions & 4 deletions source/server/tests-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import chaiAsPromised from "chai-as-promised";
//@ts-ignore
import sourceMaps from "source-map-support";
import { AppLocals } from "./utils/locals.js";
import { parse } from "./utils/config.js";
import { Config, parse } from "./utils/config.js";
sourceMaps.install();

chai.use(chaiAsPromised);
Expand All @@ -17,7 +17,7 @@ process.env["TEST"] ??= "true";
declare global{
var dataStream:(src ?:Array<Buffer|string>)=>AsyncGenerator<Buffer, void, unknown>;
var expect :typeof chai["expect"];
var createIntegrationContext :(c:Mocha.Context)=>Promise<AppLocals>;
var createIntegrationContext :(c:Mocha.Context, config_override ?:Partial<Config>)=>Promise<AppLocals>;
var cleanIntegrationContext :(c:Mocha.Context)=>Promise<void>;
}

Expand All @@ -30,11 +30,17 @@ global.dataStream = async function* (src :Array<Buffer|string> =["foo", "\n"]){
}
}

global.createIntegrationContext = async function(c :Mocha.Context){
global.createIntegrationContext = async function(c :Mocha.Context, config_override :Partial<Config>={}){
let {default:createServer} = await import("./server.js");
let titleSlug = c.currentTest?.title.replace(/[^\w]/g, "_") ?? `eThesaurus_integration_test`;
c.dir = await fs.mkdtemp(path.join(tmpdir(), titleSlug));
c.config = parse({ROOT_DIR: c.dir, CLEAN_DATABASE: "false", VERBOSE: "false", HOT_RELOAD: "false"});
c.config = Object.assign(
parse({ //Common options
ROOT_DIR: c.dir, CLEAN_DATABASE: "false", VERBOSE: "false", HOT_RELOAD: "false",
}),
//Options we might want to customize
config_override
);
c.server = await createServer( c.config );
return c.server.locals;
}
Expand Down
5 changes: 4 additions & 1 deletion source/server/utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const values = {

type Key = keyof typeof values;
type ValueType<T extends Key> = ReturnType<typeof values[T][1]>;
type Config = {
export type Config = {
[T in Key]: typeof values[T][0] extends BuildKey<T>? ReturnType<typeof values[T][0]> : ValueType<T>;
}

Expand All @@ -51,6 +51,9 @@ function toBool(s:string):boolean{
return !(!s || s.toLowerCase() === "false" || s == "0");
}

/**
* Parses a set of environment variables into a configuration object
*/
export function parse(env :NodeJS.ProcessEnv = process.env):Config{
let c :Partial<Config> = {};
for(let [key, value] of Object.entries(values)){
Expand Down
12 changes: 9 additions & 3 deletions source/server/utils/locals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,33 @@ import UserManager, { AccessType, AccessTypes } from "../auth/UserManager.js";
import Vfs, { GetFileParams } from "../vfs/index.js";
import { BadRequestError, ForbiddenError, HTTPError, InternalError, NotFoundError, UnauthorizedError } from "./errors.js";
import Templates from "./templates.js";
import { Config } from "./config.js";

export interface AppLocals extends Record<string, any>{
port :number;
fileDir :string;
userManager :UserManager;
vfs :Vfs;
templates :Templates;
config: Config;
}

export function getLocals(req :Request){
return req.app.locals as AppLocals;
}

/**
* @throws {InternalError} if app.locals.userManager is not defined for this request
*/
export function getUserManager(req :Request) :UserManager {
let userManager :UserManager = (req.app.locals as AppLocals).userManager;
let userManager :UserManager = getLocals(req).userManager;
//istanbul ignore if
if(!userManager) throw new InternalError("Badly configured app : userManager is not defined in app.locals");
return userManager
}

export function getFileDir(req :Request) :string{
let fileDir = (req.app.locals as AppLocals).fileDir;
let fileDir = getLocals(req).fileDir;
if(!fileDir) throw new InternalError("Badly configured app : fileDir is not a valid string");
return fileDir;
}
Expand Down Expand Up @@ -145,7 +151,7 @@ export function getFileParams(req :Request):GetFileParams{
}

export function getVfs(req :Request){
let vfs :Vfs = (req.app.locals as AppLocals).vfs;
let vfs :Vfs = getLocals(req).vfs;
//istanbul ignore if
if(!vfs) throw new InternalError("Badly configured app : vfs is not defined in app.locals");
return vfs;
Expand Down

0 comments on commit 12405fc

Please sign in to comment.