Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[OGUI-1604] Add middleware to 'edit layout' requests #2734

Open
wants to merge 25 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c1b415d
add layoutId middleware to 'put/patch layout' requests
mariscalromeroalejandro Jan 29, 2025
2a19317
add layoutService middleware to put/patch layout requests
mariscalromeroalejandro Jan 29, 2025
8e38d91
add layoutOwner middleware to 'put layout' requests
mariscalromeroalejandro Jan 29, 2025
ea10e9f
add new middleware: check body in request
mariscalromeroalejandro Jan 29, 2025
7a4cba9
Merge branch 'dev' of https://github.com/AliceO2Group/WebUi into feat…
mariscalromeroalejandro Jan 29, 2025
9446163
fix eslint error: no-unused-vars
mariscalromeroalejandro Jan 29, 2025
4a797f6
fix: correct middleware call syntax
mariscalromeroalejandro Jan 29, 2025
dcfa46c
fix requestBodyMiddlewareTest
mariscalromeroalejandro Jan 29, 2025
99579e9
add new test to 'Middleware - Test Suite'
mariscalromeroalejandro Jan 29, 2025
cf12d57
undo not needed requestBody middleware
mariscalromeroalejandro Jan 29, 2025
4c22dbf
apiPutLayoutTests
mariscalromeroalejandro Jan 30, 2025
2294e2d
new specific config for api tests
mariscalromeroalejandro Jan 30, 2025
a1bf9b1
api put layout tests: 403 error and 201 OK
mariscalromeroalejandro Jan 30, 2025
43d9791
add tests for put request: body provided and name already exists
mariscalromeroalejandro Jan 31, 2025
eae50ab
remove unnecesary check in LayoutController
mariscalromeroalejandro Jan 31, 2025
717da0a
fix test when the layout id is not provided
mariscalromeroalejandro Jan 31, 2025
57029ab
refactor layoutController
mariscalromeroalejandro Jan 31, 2025
d0e275b
layoutController (patch): changed response to return { id: layoutId }…
mariscalromeroalejandro Jan 31, 2025
7f47602
api tests for patch requests
mariscalromeroalejandro Jan 31, 2025
7c15b19
Merge branch 'dev' of https://github.com/AliceO2Group/WebUi into feat…
mariscalromeroalejandro Jan 31, 2025
fa78af1
fix test descriptions
mariscalromeroalejandro Jan 31, 2025
0fd8993
fix layout controller tests
mariscalromeroalejandro Jan 31, 2025
fca8c02
move Api tests after frontend tests
mariscalromeroalejandro Jan 31, 2025
acaf9c4
remove unreachable test
mariscalromeroalejandro Feb 12, 2025
a5f3959
Merge branch 'dev' of https://github.com/AliceO2Group/WebUi into feat…
mariscalromeroalejandro Feb 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion QualityControl/lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,13 @@ export const setup = (http, ws) => {
http.get('/layout/:id', layoutService.getLayoutHandler.bind(layoutService));
http.get('/layout', layoutService.getLayoutByNameHandler.bind(layoutService));
http.post('/layout', layoutService.postLayoutHandler.bind(layoutService));
http.put('/layout/:id', layoutService.putLayoutHandler.bind(layoutService));
http.put(
'/layout/:id',
layoutServiceMiddleware(jsonDb),
layoutIdMiddleware(jsonDb),
layoutOwnerMiddleware(jsonDb),
layoutService.putLayoutHandler.bind(layoutService),
);
http.delete(
'/layout/:id',
layoutServiceMiddleware(jsonDb),
Expand All @@ -53,6 +59,8 @@ export const setup = (http, ws) => {
);
http.patch(
'/layout/:id',
layoutServiceMiddleware(jsonDb),
layoutIdMiddleware(jsonDb),
minimumRoleMiddleware(UserRole.GLOBAL),
layoutService.patchLayoutHandler.bind(layoutService),
);
Expand Down
105 changes: 40 additions & 65 deletions QualityControl/lib/controllers/LayoutController.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import { LayoutPatchDto } from './../dtos/LayoutPatchDto.js';

import {
InvalidInputError,
NotFoundError,
UnauthorizedAccessError,
updateAndSendExpressResponseFromNativeError,
}
from '@aliceo2/web-ui';
Expand Down Expand Up @@ -126,47 +124,35 @@ export class LayoutController {
async putLayoutHandler(req, res) {
const { id } = req.params;
try {
if (!id) {
updateAndSendExpressResponseFromNativeError(res, new InvalidInputError('Missing parameter "id" of layout'));
} else if (!req.body) {
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)) {
let layoutProposed = {};
try {
if (!req.body) {
updateAndSendExpressResponseFromNativeError(
res,
new UnauthorizedAccessError('Only the owner of the layout can update it'),
new InvalidInputError('Missing request body to update layout'),
);
} else {
let layoutProposed = {};
try {
layoutProposed = await LayoutDto.validateAsync(req.body);
} catch (error) {
updateAndSendExpressResponseFromNativeError(
res,
new Error(`Failed to update layout ${error?.details?.[0]?.message || ''}`),
);
return;
}

const layouts = await this._dataService.listLayouts({ name: layoutProposed.name });
const layoutExistsWithName = layouts.every((layout) => layout.id !== layoutProposed.id);
if (layouts.length > 0 && layoutExistsWithName) {
updateAndSendExpressResponseFromNativeError(
res,
new InvalidInputError(`Proposed layout name: ${layoutProposed.name} already exists`),
);
return;
}
const layout = await this._dataService.updateLayout(id, layoutProposed);
res.status(201).json({ id: layout });
return;
}
layoutProposed = await LayoutDto.validateAsync(req.body);
} catch (error) {
updateAndSendExpressResponseFromNativeError(
res,
new InvalidInputError(`Failed to update layout ${error?.details?.[0]?.message || ''}`),
);
return;
}

const layouts = await this._dataService.listLayouts({ name: layoutProposed.name });
const layoutExistsWithName = layouts.every((layout) => layout.id !== layoutProposed.id);
if (layouts.length > 0 && layoutExistsWithName) {
updateAndSendExpressResponseFromNativeError(
res,
new InvalidInputError(`Proposed layout name: ${layoutProposed.name} already exists`),
);
return;
}
const layout = await this._dataService.updateLayout(id, layoutProposed);
res.status(201).json({ id: layout });
} catch (error) {
updateAndSendExpressResponseFromNativeError(res, error);
}
Expand Down Expand Up @@ -229,33 +215,22 @@ export class LayoutController {
*/
async patchLayoutHandler(req, res) {
const { id } = req.params;
if (!id) {
updateAndSendExpressResponseFromNativeError(res, new InvalidInputError('Missing ID'));
} else {
let layout = {};
try {
layout = await LayoutPatchDto.validateAsync(req.body);
} catch {
updateAndSendExpressResponseFromNativeError(
res,
new InvalidInputError('Invalid request body to update layout'),
);
return;
}

try {
await this._dataService.readLayout(id);
} catch {
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 {
updateAndSendExpressResponseFromNativeError(res, new Error(`Unable to update layout with id: ${id}`));
return;
}
let layout = {};
try {
layout = await LayoutPatchDto.validateAsync(req.body);
} catch {
updateAndSendExpressResponseFromNativeError(
res,
new InvalidInputError('Invalid request body to update layout'),
);
return;
}
try {
const layoutUpdated = await this._dataService.updateLayout(id, layout);
res.status(201).json(layoutUpdated);
} catch {
updateAndSendExpressResponseFromNativeError(res, new Error(`Unable to update layout with id: ${id}`));
return;
}
}
}
118 changes: 117 additions & 1 deletion QualityControl/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion QualityControl/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
"globals": "^15.14.0",
"nock": "^13.5.0",
"puppeteer": "^24.0.0",
"sinon": "^19.0.2"
"sinon": "^19.0.2",
"supertest": "^7.0.0"
},
"bundleDependencies": [
"@aliceo2/web-ui",
Expand Down
48 changes: 48 additions & 0 deletions QualityControl/test/api/layouts/api-put-layout.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* @license
* Copyright 2019-2020 CERN and copyright holders of ALICE O2.
* See http://alice-o2.web.cern.ch/copyright for details of the copyright holders.
* All rights not expressly granted are reserved.
*
* This software is distributed under the terms of the GNU General Public
* License v3 (GPL Version 3), copied verbatim in the file "COPYING".
*
* In applying this license CERN does not waive the privileges and immunities
* granted to it by virtue of its status as an Intergovernmental Organization
* or submit itself to any jurisdiction.
*/

import { suite, test } from 'node:test';
import { ADMIN_TEST_TOKEN } from '../../setup/testServerSetup.js';
import request from 'supertest';

export const apiPutLayoutTests = () => {
suite('PUT /layout/:id', () => {
test('should return a 404 error if the id of the layout does not exist', async () => {
await request('localhost:8080/api/layout/test')
.put(`?token=${ADMIN_TEST_TOKEN}`)
.expect(404, {
message: 'layout (test) not found',
status: 404,
title: 'Not Found',
});
});

test('should return a 404 error if the layout id is not provided', async () => {
await request('localhost:8080/api/layout/')
.put(`?id=${null}&token=${ADMIN_TEST_TOKEN}`)
.expect(404, {
message: 'layout id not provided',
status: 404,
title: 'Not Found',
});
});

test.skip('should return a 401 error if the user is not the owner of the layout', async () => {

});
test.skip('should successfully update a layout', async () => {

});
});
};
Loading