diff --git a/@xen-orchestra/rest-api/package.json b/@xen-orchestra/rest-api/package.json index 74b05fb0a33..f130208da05 100644 --- a/@xen-orchestra/rest-api/package.json +++ b/@xen-orchestra/rest-api/package.json @@ -28,6 +28,7 @@ "inversify": "^6.2.1", "inversify-binding-decorators": "^4.0.0", "swagger-ui-express": "^5.0.1", - "tsoa": "^6.6.0" + "tsoa": "^6.6.0", + "xo-common": "^0.8.0" } } diff --git a/@xen-orchestra/rest-api/src/dashboard/dashboard.controller.ts b/@xen-orchestra/rest-api/src/dashboard/dashboard.controller.ts index f8e494bdd03..d0c3e479133 100644 --- a/@xen-orchestra/rest-api/src/dashboard/dashboard.controller.ts +++ b/@xen-orchestra/rest-api/src/dashboard/dashboard.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Request, Route, Security } from 'tsoa' +import { Controller, Get, Request, Route } from 'tsoa' import DashboardService from './dashboard.service.js' import { inject } from 'inversify' import { provideSingleton } from '../ioc/helper.js' @@ -26,7 +26,6 @@ export class DashboardController extends Controller { this.#dashboardService = dashboardService } - @Security('token', ['admin']) @Get() public async getDashboard(@Request() req: ExReq): Promise { const resp = req.res! diff --git a/@xen-orchestra/rest-api/src/index.ts b/@xen-orchestra/rest-api/src/index.ts index d91a8efe6a9..07f6bd97e6f 100644 --- a/@xen-orchestra/rest-api/src/index.ts +++ b/@xen-orchestra/rest-api/src/index.ts @@ -7,7 +7,7 @@ import { XapiXoObject, XoApp } from './xoApp.type.js' import { EventEmitter } from 'events' import DashboardService from './dashboard/dashboard.service.js' import { iocContainer } from './ioc/ioc.js' -import { XoServer } from './servers/server.type.js' +import { errorHandler } from './middleware/error.middleware.js' class RestApi { #sseClients: Map = new Map() @@ -17,8 +17,8 @@ class RestApi { authenticateUser getObject getObjects - getServers - getServer + getServers: XoApp['getAllXenServers'] + getServer: XoApp['getXenServer'] getObjectsByType constructor(xoApp: XoApp) { @@ -31,7 +31,7 @@ class RestApi { this.getObject = xoApp.getObject.bind(xoApp) this.getObjects = xoApp.getObjects.bind(xoApp) this.getServers = () => xoApp.getAllXenServers() - this.getServer = (id: XoServer['id']) => xoApp.getXenServer(id) + this.getServer = id => xoApp.getXenServer(id) // helpers this.getObjectsByType = (type: T) => @@ -120,6 +120,8 @@ export default function setupRestApi(express: Express, xoApp: XoApp) { express.use('/rest/v1/api-doc', swaggerUi.serve, swaggerUi.setup(swaggerOpenApiSpec)) RegisterRoutes(express) + express.use(errorHandler) + // in order to create the instance of the service (and start to listen for dashboard changes) iocContainer.get(DashboardService) } diff --git a/@xen-orchestra/rest-api/src/middleware/error.middleware.ts b/@xen-orchestra/rest-api/src/middleware/error.middleware.ts new file mode 100644 index 00000000000..3594e88941e --- /dev/null +++ b/@xen-orchestra/rest-api/src/middleware/error.middleware.ts @@ -0,0 +1,14 @@ +import { noSuchObject } from 'xo-common/api-errors.js' + +import { NextFunction, Request, Response } from 'express' + +export function errorHandler(err: Error, _req: Request, res: Response, next: NextFunction) { + if (noSuchObject.is(err)) { + res.status(404).json({ error: err.message }) + return next() + } + + res.json({ error: err.message }) + + next() +} diff --git a/@xen-orchestra/rest-api/src/servers/server.controller.ts b/@xen-orchestra/rest-api/src/servers/server.controller.ts index a7c2a536109..d31f0d7ac72 100644 --- a/@xen-orchestra/rest-api/src/servers/server.controller.ts +++ b/@xen-orchestra/rest-api/src/servers/server.controller.ts @@ -9,6 +9,8 @@ export class ServersController extends XoController { constructor() { super('server') } + + @Security('token', ['admin']) @Get() public getServers(): Promise { return this.getObjectIds() diff --git a/@xen-orchestra/rest-api/tsconfig.json b/@xen-orchestra/rest-api/tsconfig.json index 7e2a66b9eed..e8006467472 100644 --- a/@xen-orchestra/rest-api/tsconfig.json +++ b/@xen-orchestra/rest-api/tsconfig.json @@ -6,6 +6,7 @@ "module": "NodeNext", "outDir": "./dist", "rootDir": "./src", + "allowJs": true, /* Strict Type-Checking Options */ "strict": true, diff --git a/yarn.lock b/yarn.lock index 6b9d09e7af9..53214c63560 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4668,9 +4668,9 @@ undici-types "~6.19.2" "@types/node@^22.10.6": - version "22.10.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.9.tgz#b62b5e8485b9b412262466209280405525320108" - integrity sha512-Ir6hwgsKyNESl/gLOcEz3krR4CBGgliDqBQ2ma4wIhEx0w+xnoeTq3tdrNw15kU3SxogDjOgv9sqdtLW8mIHaw== + version "22.10.10" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.10.tgz#85fe89f8bf459dc57dfef1689bd5b52ad1af07e6" + integrity sha512-X47y/mPNzxviAGY5TcYPtYL8JsY3kAq2n8fMmKoRCxq/c4v4pyGNCzM2R6+M5/umG4ZfHuT+sgqDYqWc9rJ6ww== dependencies: undici-types "~6.20.0"