Skip to content

Commit

Permalink
[OGUI-1494] Refactor: Reuse existing error handling from @alice02/web…
Browse files Browse the repository at this point in the history
…-ui (#2726)

* This pull request simplifies how errors are managed by using the error handling already built in @alice02/web-ui.
  • Loading branch information
mariscalromeroalejandro authored Jan 23, 2025
1 parent e2871da commit 2df6c23
Show file tree
Hide file tree
Showing 10 changed files with 232 additions and 186 deletions.
63 changes: 37 additions & 26 deletions QualityControl/lib/controllers/LayoutController.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
import assert from 'assert';
import { LayoutDto } from './../dtos/LayoutDto.js';
import { LayoutPatchDto } from './../dtos/LayoutPatchDto.js';

import {
updateExpressResponseFromNativeError,
} from './../errors/updateExpressResponseFromNativeError.js';
import { InvalidInputError } from './../errors/InvalidInputError.js';
import { UnauthorizedAccessError } from './../errors/UnauthorizedAccessError.js';
import { NotFoundError } from './../errors/NotFoundError.js';
InvalidInputError,
NotFoundError,
UnauthorizedAccessError,
updateAndSendExpressResponseFromNativeError,
}
from '@aliceo2/web-ui';

/**
* Gateway for all HTTP requests with regards to QCG Layouts
Expand Down Expand Up @@ -59,7 +61,7 @@ export class LayoutController {
const layouts = await this._dataService.listLayouts(filter);
res.status(200).json(layouts);
} catch {
updateExpressResponseFromNativeError(res, new Error('Unable to retrieve layouts'));
updateAndSendExpressResponseFromNativeError(res, new Error('Unable to retrieve layouts'));
}
}

Expand All @@ -74,13 +76,13 @@ export class LayoutController {

try {
if (!id) {
updateExpressResponseFromNativeError(res, new InvalidInputError('Missing parameter "id" of layout'));
updateAndSendExpressResponseFromNativeError(res, new InvalidInputError('Missing parameter "id" of layout'));
} else {
const layout = await this._dataService.readLayout(id);
res.status(200).json(layout);
}
} catch {
updateExpressResponseFromNativeError(res, new Error(`Unable to retrieve layout with id: ${id}`));
updateAndSendExpressResponseFromNativeError(res, new Error(`Unable to retrieve layout with id: ${id}`));
}
}

Expand All @@ -102,14 +104,14 @@ export class LayoutController {
} else if (runDefinition) {
layoutName = runDefinition;
} else {
updateExpressResponseFromNativeError(res, new InvalidInputError('Missing query parameters'));
updateAndSendExpressResponseFromNativeError(res, new InvalidInputError('Missing query parameters'));
return;
}
try {
const layout = await this._dataService.readLayoutByName(layoutName);
res.status(200).json(layout);
} catch (error) {
updateExpressResponseFromNativeError(res, error);
updateAndSendExpressResponseFromNativeError(res, error);
}
}

Expand All @@ -125,15 +127,18 @@ export class LayoutController {
const { id } = req.params;
try {
if (!id) {
updateExpressResponseFromNativeError(res, new InvalidInputError('Missing parameter "id" of layout'));
updateAndSendExpressResponseFromNativeError(res, new InvalidInputError('Missing parameter "id" of layout'));
} else if (!req.body) {
updateExpressResponseFromNativeError(res, new InvalidInputError('Missing body content to update layout with'));
updateAndSendExpressResponseFromNativeError(
res,
new InvalidInputError('Missing body content to update layout with'),
);
} else {
const { personid } = req.session;
const { owner_id } = await this._dataService.readLayout(id);

if (Number(owner_id) !== Number(personid)) {
updateExpressResponseFromNativeError(
updateAndSendExpressResponseFromNativeError(
res,
new UnauthorizedAccessError('Only the owner of the layout can update it'),
);
Expand All @@ -142,7 +147,7 @@ export class LayoutController {
try {
layoutProposed = await LayoutDto.validateAsync(req.body);
} catch (error) {
updateExpressResponseFromNativeError(
updateAndSendExpressResponseFromNativeError(
res,
new Error(`Failed to update layout ${error?.details?.[0]?.message || ''}`),
);
Expand All @@ -152,7 +157,7 @@ export class LayoutController {
const layouts = await this._dataService.listLayouts({ name: layoutProposed.name });
const layoutExistsWithName = layouts.every((layout) => layout.id !== layoutProposed.id);
if (layouts.length > 0 && layoutExistsWithName) {
updateExpressResponseFromNativeError(
updateAndSendExpressResponseFromNativeError(
res,
new InvalidInputError(`Proposed layout name: ${layoutProposed.name} already exists`),
);
Expand All @@ -163,7 +168,7 @@ export class LayoutController {
}
}
} catch (error) {
updateExpressResponseFromNativeError(res, error);
updateAndSendExpressResponseFromNativeError(res, error);
}
}

Expand All @@ -177,12 +182,15 @@ export class LayoutController {
const { id } = req.params;
try {
if (!id) {
updateExpressResponseFromNativeError(res, new InvalidInputError('Missing parameter "id" of layout to delete'));
updateAndSendExpressResponseFromNativeError(
res,
new InvalidInputError('Missing parameter "id" of layout to delete'),
);
} else {
const { personid, name } = req.session;
const { owner_name, owner_id } = await this._dataService.readLayout(id);
if (owner_name !== name || owner_id !== personid) {
updateExpressResponseFromNativeError(
updateAndSendExpressResponseFromNativeError(
res,
new UnauthorizedAccessError('Only the owner of the layout can delete it'),
);
Expand All @@ -192,7 +200,7 @@ export class LayoutController {
}
}
} catch {
updateExpressResponseFromNativeError(res, new Error(`Unable to delete layout with id: ${id}`));
updateAndSendExpressResponseFromNativeError(res, new Error(`Unable to delete layout with id: ${id}`));
}
}

Expand All @@ -207,7 +215,7 @@ export class LayoutController {
try {
layoutProposed = await LayoutDto.validateAsync(req.body);
} catch (error) {
updateExpressResponseFromNativeError(
updateAndSendExpressResponseFromNativeError(
res,
new InvalidInputError(`Failed to validate layout: ${error?.details[0]?.message || ''}`),
);
Expand All @@ -216,7 +224,7 @@ export class LayoutController {
try {
const layouts = await this._dataService.listLayouts({ name: layoutProposed.name });
if (layouts.length > 0) {
updateExpressResponseFromNativeError(
updateAndSendExpressResponseFromNativeError(
res,
new InvalidInputError(`Proposed layout name: ${layoutProposed.name} already exists`),
);
Expand All @@ -225,7 +233,7 @@ export class LayoutController {
const result = await this._dataService.createLayout(layoutProposed);
res.status(201).json(result);
} catch {
updateExpressResponseFromNativeError(res, new Error('Unable to create new layout'));
updateAndSendExpressResponseFromNativeError(res, new Error('Unable to create new layout'));
}
}

Expand All @@ -238,27 +246,30 @@ export class LayoutController {
async patchLayoutHandler(req, res) {
const { id } = req.params;
if (!id) {
updateExpressResponseFromNativeError(res, new InvalidInputError('Missing ID'));
updateAndSendExpressResponseFromNativeError(res, new InvalidInputError('Missing ID'));
} else {
let layout = {};
try {
layout = await LayoutPatchDto.validateAsync(req.body);
} catch {
updateExpressResponseFromNativeError(res, new InvalidInputError('Invalid request body to update layout'));
updateAndSendExpressResponseFromNativeError(
res,
new InvalidInputError('Invalid request body to update layout'),
);
return;
}

try {
await this._dataService.readLayout(id);
} catch {
updateExpressResponseFromNativeError(res, new NotFoundError(`Unable to find layout with id: ${id}`));
updateAndSendExpressResponseFromNativeError(res, new NotFoundError(`Unable to find layout with id: ${id}`));
return;
}
try {
const layoutUpdated = await this._dataService.updateLayout(id, layout);
res.status(201).json(layoutUpdated);
} catch {
updateExpressResponseFromNativeError(res, new Error(`Unable to update layout with id: ${id}`));
updateAndSendExpressResponseFromNativeError(res, new Error(`Unable to update layout with id: ${id}`));
return;
}
}
Expand Down
7 changes: 6 additions & 1 deletion QualityControl/lib/controllers/StatusController.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
* or submit itself to any jurisdiction.
*/

import { ServiceUnavailableError, updateAndSendExpressResponseFromNativeError } from '@aliceo2/web-ui';

/**
* Gateway for all calls with regards to the status of the framework and its dependencies
*/
Expand Down Expand Up @@ -48,7 +50,10 @@ export class StatusController {
const info = await this._statusService.retrieveFrameworkInfo();
res.status(200).json(info);
} catch (error) {
res.status(503).json({ message: error.message || error });
updateAndSendExpressResponseFromNativeError(
res,
new ServiceUnavailableError(error.message || error),
);
}
}
}
17 changes: 0 additions & 17 deletions QualityControl/lib/errors/InvalidInputError.js

This file was deleted.

17 changes: 0 additions & 17 deletions QualityControl/lib/errors/NotFoundError.js

This file was deleted.

17 changes: 0 additions & 17 deletions QualityControl/lib/errors/UnauthorizedAccessError.js

This file was deleted.

40 changes: 0 additions & 40 deletions QualityControl/lib/errors/updateExpressResponseFromNativeError.js

This file was deleted.

9 changes: 3 additions & 6 deletions QualityControl/lib/middleware/minimumRole.middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,8 @@
* or submit itself to any jurisdiction.
*/

import { UnauthorizedAccessError, updateAndSendExpressResponseFromNativeError } from '@aliceo2/web-ui';
import { isUserRoleSufficient } from './../../common/library/userRole.enum.js';
import { UnauthorizedAccessError } from './../errors/UnauthorizedAccessError.js';
import {
updateExpressResponseFromNativeError,
} from './../errors/updateExpressResponseFromNativeError.js';

/**
* Method to receive a minimum role that needs to be met by owner of request and to return a middleware function
Expand Down Expand Up @@ -44,14 +41,14 @@ export const minimumRoleMiddleware = (minimumRole) =>
}
const isAllowed = accessList.some((role) => isUserRoleSufficient(role, minimumRole));
if (!isAllowed) {
updateExpressResponseFromNativeError(
updateAndSendExpressResponseFromNativeError(
res,
new UnauthorizedAccessError('Not enough permissions for this operation'),
);
} else {
next();
}
} catch (error) {
updateExpressResponseFromNativeError(res, error);
updateAndSendExpressResponseFromNativeError(res, error);
}
};
3 changes: 1 addition & 2 deletions QualityControl/lib/services/JsonFileService.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@
* or submit itself to any jurisdiction.
*/

import { LogManager } from '@aliceo2/web-ui';
import { LogManager, NotFoundError } from '@aliceo2/web-ui';
const logger = LogManager.getLogger(`${process.env.npm_config_log_label ?? 'qcg'}/json`);
import fs from 'fs';
import path from 'path';
import { NotFoundError } from './../errors/NotFoundError.js';

/**
* Store layouts inside JSON based file with atomic write
Expand Down
Loading

0 comments on commit 2df6c23

Please sign in to comment.