mirror of
https://github.com/bpatrik/pigallery2.git
synced 2025-03-11 14:59:21 +02:00
Add RestApi extendability #753
This commit is contained in:
parent
f7dba927b8
commit
7a0f0c743c
72
src/backend/model/extension/ExpressRouterWrapper.ts
Normal file
72
src/backend/model/extension/ExpressRouterWrapper.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import * as express from 'express';
|
||||
import {NextFunction, Request, Response} from 'express';
|
||||
import {UserDTO, UserRoles} from '../../../common/entities/UserDTO';
|
||||
import {AuthenticationMWs} from '../../middlewares/user/AuthenticationMWs';
|
||||
import {RenderingMWs} from '../../middlewares/RenderingMWs';
|
||||
import {ParamsDictionary} from 'express-serve-static-core';
|
||||
import {IExtensionRESTApi, IExtensionRESTRoute} from './IExtension';
|
||||
import {Logger} from '../../Logger';
|
||||
import {ExtensionManager} from './ExtensionManager';
|
||||
import {Utils} from '../../../common/Utils';
|
||||
|
||||
|
||||
export class ExpressRouterWrapper implements IExtensionRESTApi {
|
||||
|
||||
constructor(private readonly router: express.Router, private readonly name: string) {
|
||||
}
|
||||
|
||||
get use() {
|
||||
return new ExpressRouteWrapper(this.router, this.name, 'use');
|
||||
}
|
||||
|
||||
get get() {
|
||||
return new ExpressRouteWrapper(this.router, this.name, 'get');
|
||||
}
|
||||
|
||||
get put() {
|
||||
return new ExpressRouteWrapper(this.router, this.name, 'put');
|
||||
}
|
||||
|
||||
get post() {
|
||||
return new ExpressRouteWrapper(this.router, this.name, 'post');
|
||||
}
|
||||
|
||||
get delete() {
|
||||
return new ExpressRouteWrapper(this.router, this.name, 'delete');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class ExpressRouteWrapper implements IExtensionRESTRoute {
|
||||
|
||||
constructor(private readonly router: express.Router,
|
||||
private readonly name: string,
|
||||
private readonly func: 'get' | 'use' | 'put' | 'post' | 'delete') {
|
||||
}
|
||||
|
||||
private getAuthMWs(minRole: UserRoles) {
|
||||
return minRole ? [AuthenticationMWs.authenticate,
|
||||
AuthenticationMWs.authorise(minRole)] : [];
|
||||
}
|
||||
|
||||
public jsonResponse(paths: string[], minRole: UserRoles, cb: (params?: ParamsDictionary, body?: any, user?: UserDTO) => Promise<unknown> | unknown) {
|
||||
const fullPaths = paths.map(p => (Utils.concatUrls('/' + this.name + '/' + p)));
|
||||
this.router[this.func](fullPaths,
|
||||
...(this.getAuthMWs(minRole).concat([
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
req.resultPipe = await cb(req.params, req.body, req.session['user']);
|
||||
next();
|
||||
},
|
||||
RenderingMWs.renderResult
|
||||
])));
|
||||
Logger.silly(`[ExtensionRest:${this.name}]`, `Listening on ${this.func} ${ExtensionManager.EXTENSION_API_PATH}${fullPaths}`);
|
||||
}
|
||||
|
||||
public rawMiddleware(paths: string[], minRole: UserRoles, mw: (req: Request, res: Response, next: NextFunction) => void | Promise<void>) {
|
||||
const fullPaths = paths.map(p => (Utils.concatUrls('/' + this.name + '/' + p)));
|
||||
this.router[this.func](fullPaths,
|
||||
...this.getAuthMWs(minRole),
|
||||
mw);
|
||||
Logger.silly(`[ExtensionRest:${this.name}]`, `Listening on ${this.func} ${ExtensionManager.EXTENSION_API_PATH}${fullPaths}`);
|
||||
}
|
||||
}
|
@ -8,11 +8,15 @@ import {IExtensionEvents, IExtensionObject, IServerExtension} from './IExtension
|
||||
import {ObjectManagers} from '../ObjectManagers';
|
||||
import {Server} from '../../server';
|
||||
import {ExtensionEvent} from './ExtensionEvent';
|
||||
import {ExpressRouterWrapper} from './ExpressRouterWrapper';
|
||||
import * as express from 'express';
|
||||
|
||||
const LOG_TAG = '[ExtensionManager]';
|
||||
|
||||
export class ExtensionManager implements IObjectManager {
|
||||
|
||||
public static EXTENSION_API_PATH = Config.Server.apiPath + '/extension';
|
||||
|
||||
events: IExtensionEvents = {
|
||||
gallery: {
|
||||
MetadataLoader: {
|
||||
@ -32,8 +36,13 @@ export class ExtensionManager implements IObjectManager {
|
||||
}
|
||||
}
|
||||
};
|
||||
extObjects: { [key: string]: IExtensionObject } = {};
|
||||
router: express.Router;
|
||||
|
||||
public async init() {
|
||||
this.extObjects = {};
|
||||
this.router = express.Router();
|
||||
Server.getInstance().app.use(ExtensionManager.EXTENSION_API_PATH, this.router);
|
||||
this.loadExtensionsList();
|
||||
await this.initExtensions();
|
||||
}
|
||||
@ -69,16 +78,23 @@ export class ExtensionManager implements IObjectManager {
|
||||
}
|
||||
|
||||
private createExtensionObject(name: string): IExtensionObject {
|
||||
return {
|
||||
_app: {
|
||||
objectManagers: ObjectManagers.getInstance(),
|
||||
expressApp: Server.getInstance().app,
|
||||
config: Config
|
||||
},
|
||||
paths: ProjectPath,
|
||||
Logger: createLoggerWrapper(`[Extension: ${name}]`),
|
||||
events: this.events
|
||||
};
|
||||
if (!this.extObjects[name]) {
|
||||
const rw = new ExpressRouterWrapper(this.router, name);
|
||||
this.extObjects[name] = {
|
||||
_app: {
|
||||
get objectManagers() {
|
||||
return ObjectManagers.getInstance();
|
||||
},
|
||||
expressApp: Server.getInstance().app,
|
||||
config: Config
|
||||
},
|
||||
paths: ProjectPath,
|
||||
Logger: createLoggerWrapper(`[Extension: ${name}]`),
|
||||
events: this.events,
|
||||
RESTApi: rw
|
||||
};
|
||||
}
|
||||
return this.extObjects[name];
|
||||
}
|
||||
|
||||
private async initExtensions() {
|
||||
@ -102,5 +118,7 @@ export class ExtensionManager implements IObjectManager {
|
||||
|
||||
public async cleanUp() {
|
||||
await this.cleanUpExtensions();
|
||||
Server.getInstance().app.use(ExtensionManager.EXTENSION_API_PATH, express.Router());
|
||||
this.extObjects = {};
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,11 @@
|
||||
import * as express from 'express';
|
||||
import {NextFunction, Request, Response} from 'express';
|
||||
import {PrivateConfigClass} from '../../../common/config/private/Config';
|
||||
import {ObjectManagers} from '../ObjectManagers';
|
||||
import {ProjectPathClass} from '../../ProjectPath';
|
||||
import {ILogger} from '../../Logger';
|
||||
import {UserDTO, UserRoles} from '../../../common/entities/UserDTO';
|
||||
import {ParamsDictionary} from 'express-serve-static-core';
|
||||
|
||||
|
||||
export type IExtensionBeforeEventHandler<I, O> = (input: { inputs: I }, event: { stopPropagation: boolean }) => Promise<{ inputs: I } | O>;
|
||||
@ -59,11 +62,41 @@ export interface IExtensionApp {
|
||||
config: PrivateConfigClass;
|
||||
}
|
||||
|
||||
export interface IExtensionRESTRoute {
|
||||
jsonResponse(paths: string[], minRole: UserRoles, cb: (params?: ParamsDictionary, body?: any, user?: UserDTO) => Promise<unknown> | unknown): void;
|
||||
|
||||
rawMiddleware(paths: string[], minRole: UserRoles, mw: (req: Request, res: Response, next: NextFunction) => void | Promise<void>): void;
|
||||
}
|
||||
|
||||
export interface IExtensionRESTApi {
|
||||
use: IExtensionRESTRoute;
|
||||
get: IExtensionRESTRoute;
|
||||
post: IExtensionRESTRoute;
|
||||
put: IExtensionRESTRoute;
|
||||
delete: IExtensionRESTRoute;
|
||||
}
|
||||
|
||||
export interface IExtensionObject {
|
||||
/**
|
||||
* Inner functionality of the app. Use this wit caution
|
||||
*/
|
||||
_app: IExtensionApp;
|
||||
/**
|
||||
* Paths to the main components of the app.
|
||||
*/
|
||||
paths: ProjectPathClass;
|
||||
/**
|
||||
* Logger of the app
|
||||
*/
|
||||
Logger: ILogger;
|
||||
/**
|
||||
* Main app events. Use this change indexing, cover or serving gallery
|
||||
*/
|
||||
events: IExtensionEvents;
|
||||
/**
|
||||
* Use this to define REST calls related to the extension
|
||||
*/
|
||||
RESTApi: IExtensionRESTApi;
|
||||
}
|
||||
|
||||
|
||||
@ -72,5 +105,6 @@ export interface IExtensionObject {
|
||||
*/
|
||||
export interface IServerExtension {
|
||||
init(extension: IExtensionObject): Promise<void>;
|
||||
|
||||
cleanUp?: (extension: IExtensionObject) => Promise<void>;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user