mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-14 11:53:49 +00:00
feat: generate authenticated url (#1471)
* refactor: extract info component * feat: generate authenticated url * refactor: add companion select * refactor: ensure behaviour across environments
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { getErrorMessage } from 'ontime-utils';
|
||||
import { ErrorResponse, GetInfo, SessionStats } from 'ontime-types';
|
||||
import { ErrorResponse, GetInfo, GetUrl, SessionStats } from 'ontime-types';
|
||||
|
||||
import type { Request, Response } from 'express';
|
||||
|
||||
@@ -24,3 +24,18 @@ export async function getInfo(_req: Request, res: Response<GetInfo | ErrorRespon
|
||||
res.status(500).send({ message });
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateUrl(req: Request, res: Response<GetUrl | ErrorResponse>) {
|
||||
try {
|
||||
const url = sessionService.generateAuthenticatedUrl(
|
||||
req.body.baseUrl,
|
||||
req.body.path,
|
||||
req.body.lock,
|
||||
req.body.authenticate,
|
||||
);
|
||||
res.status(200).send({ url: url.toString() });
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(500).send({ message });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import express from 'express';
|
||||
|
||||
import { getInfo, getSessionStats } from './session.controller.js';
|
||||
import { getInfo, getSessionStats, generateUrl } from './session.controller.js';
|
||||
import { validateGenerateUrl } from './session.validation.js';
|
||||
|
||||
export const router = express.Router();
|
||||
|
||||
router.get('/', getSessionStats);
|
||||
router.get('/info', getInfo);
|
||||
router.post('/url', validateGenerateUrl, generateUrl);
|
||||
|
||||
@@ -8,6 +8,8 @@ import { getLastLoadedProject } from '../../services/app-state-service/AppStateS
|
||||
import { runtimeService } from '../../services/runtime-service/RuntimeService.js';
|
||||
import { getNetworkInterfaces } from '../../utils/network.js';
|
||||
import { getTimezoneLabel } from '../../utils/time.js';
|
||||
import { password } from '../../externals.js';
|
||||
import { hashPassword } from '../../utils/hash.js';
|
||||
|
||||
const startedAt = new Date();
|
||||
|
||||
@@ -46,3 +48,20 @@ export async function getInfo(): Promise<GetInfo> {
|
||||
publicDir: publicDir.root,
|
||||
};
|
||||
}
|
||||
|
||||
export const hasPassword = Boolean(password);
|
||||
export const hashedPassword = hasPassword ? hashPassword(password as string) : undefined;
|
||||
|
||||
/**
|
||||
* Generates a pre-authenticated URL by injecting a token in the URL params
|
||||
*/
|
||||
export function generateAuthenticatedUrl(baseUrl: string, path: string, lock: boolean, authenticate: boolean): URL {
|
||||
const url = new URL(path, baseUrl);
|
||||
if (authenticate && hashedPassword) {
|
||||
url.searchParams.append('token', hashedPassword);
|
||||
}
|
||||
if (lock) {
|
||||
url.searchParams.append('locked', 'true');
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { Request, Response, NextFunction } from 'express';
|
||||
import { body, validationResult } from 'express-validator';
|
||||
|
||||
export const validateGenerateUrl = [
|
||||
body('baseUrl').exists().isString().notEmpty().trim(),
|
||||
body('path').exists().isString().trim(),
|
||||
body('lock').exists().isBoolean(),
|
||||
body('authenticate').exists().isBoolean(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
|
||||
next();
|
||||
},
|
||||
];
|
||||
Reference in New Issue
Block a user