Skip to content

Commit

Permalink
Merge pull request #20 from flow-build/refactor/requests-interfaces
Browse files Browse the repository at this point in the history
Refactor/requests interfaces
  • Loading branch information
imagure authored May 11, 2023
2 parents 87b8abf + 7d26a30 commit 7e581f7
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 34 deletions.
8 changes: 8 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,13 @@ module.exports = {
camelcase: 'off',
indent: ['error', 2],
'no-undef': 'off',
'no-unused-vars': [
'warn', // or "error"
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
},
],
},
};
92 changes: 80 additions & 12 deletions src/controllers/diagrams.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,62 @@ const serializeDiagramNoXml = (diagram) => {
id: diagram.id,
name: diagram.name,
type: diagram.type,
user_id: diagram.user_id,
user_default: diagram.user_default,
workflow_id: diagram.workflow_id,
userId: diagram.user_id,
isDefault: diagram.user_default,
workflowId: diagram.workflow_id,
aligned: diagram.aligned,
created_at: diagram.created_at,
updated_at: diagram.updated_at,
createdAt: diagram.created_at,
updatedAt: diagram.updated_at,
};
};

const forbidDiagramForUser = (user_id, diagram, operation = 'update') => {
if (operation === 'read') {
if (diagram.is_public) {
return false;
}
}
if (diagram.user_id !== user_id) {
return true;
}
return false;
};

const forbiddenResponse = (ctx, _next) => {
ctx.status = 403;
ctx.body = {
message: 'FORBIDDEN',
};
return;
};

const filterDiagrams = (user_id, diagrams) => {
return diagrams.filter((diagram) => {
const isForbid = forbidDiagramForUser(user_id, diagram);
return !isForbid;
});
};

const saveDiagram = async (ctx, next) => {
logger.debug('saveDiagram controller called');
const diagramCore = getDiagramCore();
const user_id = ctx.request.user_data?.user_id;
const user_id = ctx.request.user_data?.userId;

try {
const { diagram_xml, name, user_default, workflow_id } = ctx.request.body;
const {
xml: diagram_xml,
name,
isDefault: user_default,
workflowId: workflow_id,
type,
} = ctx.request.body;

const diagram = await diagramCore.saveDiagram({
diagram_xml,
name,
user_id,
user_default,
type,
});

if (workflow_id) {
Expand Down Expand Up @@ -70,11 +104,15 @@ const saveDiagram = async (ctx, next) => {
const getAllDiagrams = async (ctx, next) => {
logger.debug('getAllDiagrams controller called');
const diagramCore = getDiagramCore();
const user_id = ctx.request.user_data?.userId;

try {
const diagrams = await diagramCore.getAllDiagrams();
const filteredDiagrams = filterDiagrams(user_id, diagrams);
ctx.status = 200;
ctx.body = diagrams.map((diagram) => serializeDiagramNoXml(diagram));
ctx.body = filteredDiagrams.map((diagram) =>
serializeDiagramNoXml(diagram)
);
} catch (err) {
throw new Error(err);
}
Expand Down Expand Up @@ -140,9 +178,14 @@ const getDiagramById = async (ctx, next) => {
const diagramCore = getDiagramCore();

const { id } = ctx.params;
const user_id = ctx.request.user_data?.userId;

try {
const diagram = await diagramCore.getDiagramById(id);
const is_forbidden = forbidDiagramForUser(user_id, diagram, 'read');
if (is_forbidden) {
return forbiddenResponse(ctx, next);
}

if (diagram) {
ctx.status = 200;
Expand All @@ -165,13 +208,16 @@ const getDiagramsByWorkflowId = async (ctx, next) => {
const diagramCore = getDiagramCore();

const { id } = ctx.params;
const user_id = ctx.request.user_data?.userId;

try {
const diagrams = await diagramCore.getDiagramsByWorkflowId(id);

if (diagrams.length > 0) {
const filteredDiagrams = filterDiagrams(user_id, diagrams);
if (filteredDiagrams.length > 0) {
ctx.status = 200;
ctx.body = diagrams.map((diagram) => serializeDiagramNoXml(diagram));
ctx.body = filteredDiagrams.map((diagram) =>
serializeDiagramNoXml(diagram)
);
} else {
ctx.status = 404;
ctx.body = {
Expand All @@ -190,9 +236,14 @@ const getLatestDiagramByWorkflowId = async (ctx, next) => {
const diagramCore = getDiagramCore();

const { id } = ctx.params;
const user_id = ctx.request.user_data?.userId;

try {
const diagram = await diagramCore.getLatestDiagramByWorkflowId(id);
const is_forbidden = forbidDiagramForUser(user_id, diagram, 'read');
if (is_forbidden) {
return forbiddenResponse(ctx, next);
}

if (diagram) {
ctx.status = 200;
Expand All @@ -216,10 +267,15 @@ const updateDiagram = async (ctx, next) => {
const blueprintCore = getBlueprintCore();

const { id } = ctx.params;
const { diagram_xml } = ctx.request.body;
const { xml: diagram_xml } = ctx.request.body;
const user_id = ctx.request.user_data?.userId;

try {
const diagram = await diagramCore.getDiagramById(id);
const is_forbidden = forbidDiagramForUser(user_id, diagram);
if (is_forbidden) {
return forbiddenResponse(ctx, next);
}

if (!diagram) {
ctx.status = 404;
Expand Down Expand Up @@ -261,8 +317,15 @@ const setDefaultDiagram = async (ctx, next) => {
const diagramCore = getDiagramCore();

const { id } = ctx.params;
const user_id = ctx.request.user_data?.userId;

try {
const diagram = await diagramCore.setAsDefault(id);
const is_forbidden = forbidDiagramForUser(user_id, diagram);
if (is_forbidden) {
return forbiddenResponse(ctx, next);
}

if (!diagram) {
ctx.status = 404;
ctx.body = {
Expand All @@ -285,9 +348,14 @@ const deleteDiagram = async (ctx, next) => {
const diagramToWorkflowCore = getDiagramToWorkflowCore();

const { id } = ctx.params;
const user_id = ctx.request.user_data?.userId;

try {
const diagram = await diagramCore.getDiagramById(id);
const is_forbidden = forbidDiagramForUser(user_id, diagram);
if (is_forbidden) {
return forbiddenResponse(ctx, next);
}

if (!diagram) {
ctx.status = 404;
Expand Down
8 changes: 4 additions & 4 deletions src/controllers/token.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ const { logger } = require('../utils/logger');
const getToken = (ctx, next) => {
logger.debug('getToken controller called');

const user_id = ctx.request.body?.user_id || null;
if (user_id) {
const userId = ctx.request.body?.userId || null;
if (userId) {
const secret = ctx.get('x-secret') || jwtSecret;
const duration = parseInt(ctx.get('x-duration')) || 3600;

const jwtToken = createJWTToken(secret, duration, user_id);
const jwtToken = createJWTToken(secret, duration, userId);
ctx.status = 200;
ctx.body = {
jwtToken,
};

return next();
}
throw Error('No user_id informed');
throw Error('No userId informed');
};

module.exports = {
Expand Down
2 changes: 1 addition & 1 deletion src/middlewares/setUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module.exports = async (ctx, next) => {
}

ctx.request['user_data'] = {
user_id: userId,
userId,
};
await next();
};
2 changes: 1 addition & 1 deletion src/routers/mainRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ module.exports = (opts = {}) => {
router.use(cors(opts.corsOptions));

const diagrams = new Router();
diagrams.prefix('/diagrams');
diagrams.prefix('/diagram');
diagrams.get(
'/user/:user_id/workflow/:workflow_id',
baseValidator.validateUUID,
Expand Down
4 changes: 2 additions & 2 deletions src/services/tokenGenerator.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const rs = require('jsrsasign');
const { logger } = require('../utils/logger');

const createJWTToken = (secret, duration, user_id) => {
const createJWTToken = (secret, duration, userId) => {
logger.debug('createJWTToken service called');

const jwtHeader = { alg: 'HS256', typ: 'JWT' };
Expand All @@ -11,7 +11,7 @@ const createJWTToken = (secret, duration, user_id) => {
const payload = {
iat: tNow,
exp: tEnd,
user_id,
user_id: userId,
};

return rs.KJUR.jws.JWS.sign('HS256', jwtHeader, payload, { utf8: secret });
Expand Down
37 changes: 31 additions & 6 deletions src/tests/diagrams.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,20 @@ const blueprintSample = require('../samples/blueprint');
let server;
let request;
let token;
const userId = 'e8089f89-2af7-433f-86de-993e4374c581';

beforeAll(async () => {
server = startServer(5001);
request = supertest(server);
const tokenResponse = await request
.post('/token')
.send({ user_id: 'e8089f89-2af7-433f-86de-993e4374c581' });
const tokenResponse = await request.post('/token').send({ userId });
token = tokenResponse.body.jwtToken;
return await db.raw('START TRANSACTION');
});

afterEach(async () => {
await db.raw('DELETE from diagram');
});

afterAll(async () => {
await db.raw('ROLLBACK');
await server.close();
Expand Down Expand Up @@ -106,19 +109,41 @@ describe('POST /default', () => {
'${id}',
'test',
'<book>Test</book>',
'7ec419de-e9b2-4f19-b6d6-5f17f6061ab8',
'${userId}',
false,
false,
false
) returning *`);

expect(rows[0].user_default).toBe(false);
const postResponse = await request
.patch(`/diagrams/${id}/default`)
.patch(`/diagram/${id}/default`)
.set('Authorization', `Bearer ${token}`);

expect(postResponse.status).toBe(200);
expect(postResponse.body.user_default).toBe(true);
expect(postResponse.body.isDefault).toBe(true);
});

test('should return 403', async () => {
const id = 'da55b972-74d4-4156-bf4f-75ca31b5b52f';
await db.raw(`
insert into diagram (id,name,diagram_xml,user_id,is_public,user_default,is_aligned)
values (
'${id}',
'test',
'<book>Test</book>',
'7ec419de-e9b2-4f19-b6d6-5f17f6061ab8',
false,
false,
false
) returning *`);

const postResponse = await request
.patch(`/diagram/${id}/default`)
.set('Authorization', `Bearer ${token}`);

expect(postResponse.status).toBe(403);
expect(postResponse.body.message).toBe('FORBIDDEN');
});
});

Expand Down
2 changes: 1 addition & 1 deletion src/tests/token.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe('GET /token', () => {
test('should return 200 without payload', async () => {
const response = await request
.post('/token')
.send({ user_id: 'e8089f89-2af7-433f-86de-993e4374c581' });
.send({ userId: 'e8089f89-2af7-433f-86de-993e4374c581' });
expect(response.status).toBe(200);
expect(response.body.jwtToken).toBeDefined();
});
Expand Down
13 changes: 6 additions & 7 deletions src/validators/diagrams.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ const { validateBody } = require('./base');

const validateSaveDiagram = validateBody({
type: 'object',
required: ['name', 'user_id', 'diagram_xml'],
required: ['name', 'xml'],
properties: {
name: { type: 'string' },
user_id: { type: 'string' },
user_default: { type: 'boolean' },
workflow_id: { type: 'string', format: 'uuid' },
diagram_xml: {
isDefault: { type: 'boolean' },
workflowId: { type: 'string', format: 'uuid' },
xml: {
type: 'string',
allOf: [
{
Expand All @@ -27,7 +26,7 @@ const validateUpdateDiagram = validateBody({
type: 'object',
properties: {
name: { type: 'string' },
diagram_xml: {
xml: {
type: 'string',
allOf: [
{
Expand All @@ -39,7 +38,7 @@ const validateUpdateDiagram = validateBody({
],
},
},
anyRequired: ['name', 'diagram_xml'],
anyRequired: ['name', 'xml'],
additionalProperties: false,
});

Expand Down

0 comments on commit 7e581f7

Please sign in to comment.