version3.2

This commit is contained in:
Flatlogic Bot 2025-07-06 19:58:08 +00:00
parent 3c85cdfb87
commit 16d4ccd49d
6 changed files with 958 additions and 3 deletions

File diff suppressed because one or more lines are too long

View File

@ -17,7 +17,14 @@ module.exports = class Helpers {
return res.status(500).send(error.message);
}
static jwtSign(data) {
return jwt.sign(data, config.secret_key, { expiresIn: '6h' });
static sanitizeWorkflow(workflow) {
const { id, name, description, nodes, createdAt, updatedAt } = workflow;
return { id, name, description, nodes, createdAt, updatedAt };
}
static sanitizeOrganization(org) {
const { id, name, region, industry, logoUrl, createdAt } = org;
return { id, name, region, industry, logoUrl, createdAt };
}
};

View File

@ -3,6 +3,7 @@ const express = require('express');
const OrganizationsService = require('../services/organizations');
const OrganizationsDBApi = require('../db/api/organizations');
const wrapAsync = require('../helpers').wrapAsync;
const Helpers = require('../helpers');
const config = require('../config');

View File

@ -0,0 +1,459 @@
const express = require('express');
const OrganizationsService = require('../services/organizations');
const OrganizationsDBApi = require('../db/api/organizations');
const wrapAsync = require('../helpers').wrapAsync;
const Helpers = require('../helpers');
const config = require('../config');
const router = express.Router();
const { parse } = require('json2csv');
const { checkCrudPermissions } = require('../middlewares/check-permissions');
router.use(checkCrudPermissions('organizations'));
/**
* @swagger
* components:
* schemas:
* Organizations:
* type: object
* properties:
* name:
* type: string
* default: name
*/
/**
* @swagger
* tags:
* name: Organizations
* description: The Organizations managing API
*/
/**
* @swagger
* /api/organizations:
* post:
* security:
* - bearerAuth: []
* tags: [Organizations]
* summary: Add new item
* description: Add new item
* requestBody:
* required: true
* content:
* application/json:
* schema:
* properties:
* data:
* description: Data of the updated item
* type: object
* $ref: "#/components/schemas/Organizations"
* responses:
* 200:
* description: The item was successfully added
* content:
* application/json:
* schema:
* $ref: "#/components/schemas/Organizations"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 405:
* description: Invalid input data
* 500:
* description: Some server error
*/
router.post(
'/',
wrapAsync(async (req, res) => {
const referer =
req.headers.referer ||
`${req.protocol}://${req.hostname}${req.originalUrl}`;
const link = new URL(referer);
await OrganizationsService.create(
req.body.data,
req.currentUser,
true,
link.host,
);
const payload = true;
res.status(200).send(payload);
}),
);
/**
* @swagger
* /api/budgets/bulk-import:
* post:
* security:
* - bearerAuth: []
* tags: [Organizations]
* summary: Bulk import items
* description: Bulk import items
* requestBody:
* required: true
* content:
* application/json:
* schema:
* properties:
* data:
* description: Data of the updated items
* type: array
* items:
* $ref: "#/components/schemas/Organizations"
* responses:
* 200:
* description: The items were successfully imported
* content:
* application/json:
* schema:
* $ref: "#/components/schemas/Organizations"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 405:
* description: Invalid input data
* 500:
* description: Some server error
*
*/
router.post(
'/bulk-import',
wrapAsync(async (req, res) => {
const referer =
req.headers.referer ||
`${req.protocol}://${req.hostname}${req.originalUrl}`;
const link = new URL(referer);
await OrganizationsService.bulkImport(req, res, true, link.host);
const payload = true;
res.status(200).send(payload);
}),
);
/**
* @swagger
* /api/organizations/{id}:
* put:
* security:
* - bearerAuth: []
* tags: [Organizations]
* summary: Update the data of the selected item
* description: Update the data of the selected item
* parameters:
* - in: path
* name: id
* description: Item ID to update
* required: true
* schema:
* type: string
* requestBody:
* description: Set new item data
* required: true
* content:
* application/json:
* schema:
* properties:
* id:
* description: ID of the updated item
* type: string
* data:
* description: Data of the updated item
* type: object
* $ref: "#/components/schemas/Organizations"
* required:
* - id
* responses:
* 200:
* description: The item data was successfully updated
* content:
* application/json:
* schema:
* $ref: "#/components/schemas/Organizations"
* 400:
* description: Invalid ID supplied
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
* description: Item not found
* 500:
* description: Some server error
*/
router.put(
'/:id',
wrapAsync(async (req, res) => {
await OrganizationsService.update(
req.body.data,
req.body.id,
req.currentUser,
);
const payload = true;
res.status(200).send(payload);
}),
);
/**
* @swagger
* /api/organizations/{id}:
* delete:
* security:
* - bearerAuth: []
* tags: [Organizations]
* summary: Delete the selected item
* description: Delete the selected item
* parameters:
* - in: path
* name: id
* description: Item ID to delete
* required: true
* schema:
* type: string
* responses:
* 200:
* description: The item was successfully deleted
* content:
* application/json:
* schema:
* $ref: "#/components/schemas/Organizations"
* 400:
* description: Invalid ID supplied
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
* description: Item not found
* 500:
* description: Some server error
*/
router.delete(
'/:id',
wrapAsync(async (req, res) => {
await OrganizationsService.remove(req.params.id, req.currentUser);
const payload = true;
res.status(200).send(payload);
}),
);
/**
* @swagger
* /api/organizations/deleteByIds:
* post:
* security:
* - bearerAuth: []
* tags: [Organizations]
* summary: Delete the selected item list
* description: Delete the selected item list
* requestBody:
* required: true
* content:
* application/json:
* schema:
* properties:
* ids:
* description: IDs of the updated items
* type: array
* responses:
* 200:
* description: The items was successfully deleted
* content:
* application/json:
* schema:
* $ref: "#/components/schemas/Organizations"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
* description: Items not found
* 500:
* description: Some server error
*/
router.post(
'/deleteByIds',
wrapAsync(async (req, res) => {
await OrganizationsService.deleteByIds(req.body.data, req.currentUser);
const payload = true;
res.status(200).send(payload);
}),
);
/**
* @swagger
* /api/organizations:
* get:
* security:
* - bearerAuth: []
* tags: [Organizations]
* summary: Get all organizations
* description: Get all organizations
* responses:
* 200:
* description: Organizations list successfully received
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: "#/components/schemas/Organizations"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
* description: Data not found
* 500:
* description: Some server error
*/
router.get(
'/',
wrapAsync(async (req, res) => {
const filetype = req.query.filetype;
const globalAccess = req.currentUser.app_role.globalAccess;
const currentUser = req.currentUser;
const payload = await OrganizationsDBApi.findAll(req.query, globalAccess, {
currentUser,
});
if (filetype && filetype === 'csv') {
const fields = ['id', 'name'];
const opts = { fields };
try {
const csv = parse(payload.rows, opts);
res.status(200).attachment(csv);
res.send(csv);
} catch (err) {
console.error(err);
}
} else {
res.status(200).send(payload);
}
}),
);
/**
* @swagger
* /api/organizations/count:
* get:
* security:
* - bearerAuth: []
* tags: [Organizations]
* summary: Count all organizations
* description: Count all organizations
* responses:
* 200:
* description: Organizations count successfully received
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: "#/components/schemas/Organizations"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
* description: Data not found
* 500:
* description: Some server error
*/
router.get(
'/count',
wrapAsync(async (req, res) => {
const globalAccess = req.currentUser.app_role.globalAccess;
const currentUser = req.currentUser;
const payload = await OrganizationsDBApi.findAll(req.query, globalAccess, {
countOnly: true,
currentUser,
});
res.status(200).send(payload);
}),
);
/**
* @swagger
* /api/organizations/autocomplete:
* get:
* security:
* - bearerAuth: []
* tags: [Organizations]
* summary: Find all organizations that match search criteria
* description: Find all organizations that match search criteria
* responses:
* 200:
* description: Organizations list successfully received
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: "#/components/schemas/Organizations"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
* description: Data not found
* 500:
* description: Some server error
*/
router.get('/autocomplete', async (req, res) => {
const globalAccess = req.currentUser.app_role.globalAccess;
const organizationId = req.currentUser.organization?.id;
const payload = await OrganizationsDBApi.findAllAutocomplete(
req.query.query,
req.query.limit,
req.query.offset,
globalAccess,
organizationId,
);
res.status(200).send(payload);
});
/**
* @swagger
* /api/organizations/{id}:
* get:
* security:
* - bearerAuth: []
* tags: [Organizations]
* summary: Get selected item
* description: Get selected item
* parameters:
* - in: path
* name: id
* description: ID of item to get
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Selected item successfully received
* content:
* application/json:
* schema:
* $ref: "#/components/schemas/Organizations"
* 400:
* description: Invalid ID supplied
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
* description: Item not found
* 500:
* description: Some server error
router.get(
'/:id',
wrapAsync(async (req, res) => {
const payload = await OrganizationsDBApi.findBy({ id: req.params.id });
if (!payload) {
return res.status(404).json({ error: 'Not found' });
}
res.json(Helpers.sanitizeOrganization(payload));
})
);
);
router.use('/', require('../helpers').commonErrorHandler);
module.exports = router;

View File

@ -5,6 +5,7 @@ const db = require('../db/models');
const WorkflowsService = require('../services/workflows');
const WorkflowsDBApi = require('../db/api/workflows');
const wrapAsync = require('../helpers').wrapAsync;
const Helpers = require('../helpers');
const config = require('../config');

View File

@ -0,0 +1,486 @@
const express = require('express');
const db = require('../db/models');
const WorkflowsService = require('../services/workflows');
const WorkflowsDBApi = require('../db/api/workflows');
const wrapAsync = require('../helpers').wrapAsync;
const Helpers = require('../helpers');
const config = require('../config');
const router = express.Router();
const { parse } = require('json2csv');
const { checkCrudPermissions } = require('../middlewares/check-permissions');
router.use(checkCrudPermissions('workflows'));
/**
* @swagger
* components:
* schemas:
* Workflows:
* type: object
* properties:
* name:
* type: string
* default: name
* description:
* type: string
* default: description
*/
/**
* @swagger
* tags:
* name: Workflows
* description: The Workflows managing API
*/
/**
* @swagger
* /api/workflows:
* post:
* security:
* - bearerAuth: []
* tags: [Workflows]
* summary: Add new item
* description: Add new item
* requestBody:
* required: true
* content:
* application/json:
* schema:
* properties:
* data:
* description: Data of the updated item
* type: object
* $ref: "#/components/schemas/Workflows"
* responses:
* 200:
* description: The item was successfully added
* content:
* application/json:
* schema:
* $ref: "#/components/schemas/Workflows"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 405:
* description: Invalid input data
* 500:
* description: Some server error
*/
router.post(
'/',
wrapAsync(async (req, res) => {
const referer =
req.headers.referer ||
`${req.protocol}://${req.hostname}${req.originalUrl}`;
const link = new URL(referer);
await WorkflowsService.create(
req.body.data,
req.currentUser,
true,
link.host,
);
const payload = true;
res.status(200).send(payload);
}),
);
/**
* @swagger
* /api/budgets/bulk-import:
* post:
* security:
* - bearerAuth: []
* tags: [Workflows]
* summary: Bulk import items
* description: Bulk import items
* requestBody:
* required: true
* content:
* application/json:
* schema:
* properties:
* data:
* description: Data of the updated items
* type: array
* items:
* $ref: "#/components/schemas/Workflows"
* responses:
* 200:
* description: The items were successfully imported
* content:
* application/json:
* schema:
* $ref: "#/components/schemas/Workflows"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 405:
* description: Invalid input data
* 500:
* description: Some server error
*
*/
router.post(
'/bulk-import',
wrapAsync(async (req, res) => {
const referer =
req.headers.referer ||
`${req.protocol}://${req.hostname}${req.originalUrl}`;
const link = new URL(referer);
await WorkflowsService.bulkImport(req, res, true, link.host);
const payload = true;
res.status(200).send(payload);
}),
);
/**
* @swagger
* /api/workflows/{id}:
* put:
* security:
* - bearerAuth: []
* tags: [Workflows]
* summary: Update the data of the selected item
* description: Update the data of the selected item
* parameters:
* - in: path
* name: id
* description: Item ID to update
* required: true
* schema:
* type: string
* requestBody:
* description: Set new item data
* required: true
* content:
* application/json:
* schema:
* properties:
* id:
* description: ID of the updated item
* type: string
* data:
* description: Data of the updated item
* type: object
* $ref: "#/components/schemas/Workflows"
* required:
* - id
* responses:
* 200:
* description: The item data was successfully updated
* content:
* application/json:
* schema:
* $ref: "#/components/schemas/Workflows"
* 400:
* description: Invalid ID supplied
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
* description: Item not found
* 500:
* description: Some server error
*/
router.put(
'/:id',
wrapAsync(async (req, res) => {
await WorkflowsService.update(req.body.data, req.body.id, req.currentUser);
const payload = true;
res.status(200).send(payload);
}),
);
/**
* @swagger
* /api/workflows/{id}:
* delete:
* security:
* - bearerAuth: []
* tags: [Workflows]
* summary: Delete the selected item
* description: Delete the selected item
* parameters:
* - in: path
* name: id
* description: Item ID to delete
* required: true
* schema:
* type: string
* responses:
* 200:
* description: The item was successfully deleted
* content:
* application/json:
* schema:
* $ref: "#/components/schemas/Workflows"
* 400:
* description: Invalid ID supplied
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
* description: Item not found
* 500:
* description: Some server error
*/
router.delete(
'/:id',
wrapAsync(async (req, res) => {
await WorkflowsService.remove(req.params.id, req.currentUser);
const payload = true;
res.status(200).send(payload);
}),
);
/**
* @swagger
* /api/workflows/deleteByIds:
* post:
* security:
* - bearerAuth: []
* tags: [Workflows]
* summary: Delete the selected item list
* description: Delete the selected item list
* requestBody:
* required: true
* content:
* application/json:
* schema:
* properties:
* ids:
* description: IDs of the updated items
* type: array
* responses:
* 200:
* description: The items was successfully deleted
* content:
* application/json:
* schema:
* $ref: "#/components/schemas/Workflows"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
* description: Items not found
* 500:
* description: Some server error
*/
router.post(
'/deleteByIds',
wrapAsync(async (req, res) => {
await WorkflowsService.deleteByIds(req.body.data, req.currentUser);
const payload = true;
res.status(200).send(payload);
}),
);
/**
* @swagger
* /api/workflows:
* get:
* security:
* - bearerAuth: []
* tags: [Workflows]
* summary: Get all workflows
* description: Get all workflows
* responses:
* 200:
* description: Workflows list successfully received
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: "#/components/schemas/Workflows"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
* description: Data not found
* 500:
* description: Some server error
*/
router.get(
'/',
wrapAsync(async (req, res) => {
const filetype = req.query.filetype;
const globalAccess = req.currentUser.app_role.globalAccess;
const currentUser = req.currentUser;
const payload = await WorkflowsDBApi.findAll(req.query, globalAccess, {
currentUser,
});
if (filetype && filetype === 'csv') {
const fields = ['id', 'name', 'description'];
const opts = { fields };
try {
const csv = parse(payload.rows, opts);
res.status(200).attachment(csv);
res.send(csv);
} catch (err) {
console.error(err);
}
} else {
res.status(200).send(payload);
}
}),
);
/**
* @swagger
* /api/workflows/count:
* get:
* security:
* - bearerAuth: []
* tags: [Workflows]
* summary: Count all workflows
* description: Count all workflows
* responses:
* 200:
* description: Workflows count successfully received
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: "#/components/schemas/Workflows"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
* description: Data not found
* 500:
* description: Some server error
*/
router.get(
'/count',
wrapAsync(async (req, res) => {
const globalAccess = req.currentUser.app_role.globalAccess;
const currentUser = req.currentUser;
const payload = await WorkflowsDBApi.findAll(req.query, globalAccess, {
countOnly: true,
currentUser,
});
res.status(200).send(payload);
}),
);
/**
* @swagger
* /api/workflows/autocomplete:
* get:
* security:
* - bearerAuth: []
* tags: [Workflows]
* summary: Find all workflows that match search criteria
* description: Find all workflows that match search criteria
* responses:
* 200:
* description: Workflows list successfully received
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: "#/components/schemas/Workflows"
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
* description: Data not found
* 500:
* description: Some server error
*/
router.get('/autocomplete', async (req, res) => {
const globalAccess = req.currentUser.app_role.globalAccess;
const organizationId = req.currentUser.organization?.id;
const payload = await WorkflowsDBApi.findAllAutocomplete(
req.query.query,
req.query.limit,
req.query.offset,
globalAccess,
organizationId,
);
res.status(200).send(payload);
});
/**
* @swagger
* /api/workflows/{id}:
* get:
* security:
* - bearerAuth: []
* tags: [Workflows]
* summary: Get selected item
* description: Get selected item
* parameters:
* - in: path
* name: id
* description: ID of item to get
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Selected item successfully received
* content:
* application/json:
* schema:
* $ref: "#/components/schemas/Workflows"
* 400:
* description: Invalid ID supplied
* 401:
* $ref: "#/components/responses/UnauthorizedError"
* 404:
* description: Item not found
* 500:
// Route: Get latest execution status for a workflow
router.get(
'/:id/execution-status',
wrapAsync(async (req, res) => {
const workflowId = req.params.id;
const execution = await db.executions.findOne({
where: { workflowId },
order: [['createdAt', 'DESC']],
include: [{ model: db.compliance_logs, as: 'compliance_logs_execution' }],
});
if (!execution) {
return res.status(404).json({ error: 'No execution found for workflow.' });
}
const alerts = execution.compliance_logs_execution
? execution.compliance_logs_execution.map((log) => log.message)
: [];
res.json({
status: execution.status,
durationMs: execution.durationMs,
outputSnippet: execution.output_snippet,
alerts,
});
})
);
* description: Some server error
*/
router.get(
'/:id',
wrapAsync(async (req, res) => {
const payload = await WorkflowsDBApi.findBy({ id: req.params.id });
if (!payload) {
return res.status(404).json({ error: 'Not found' });
}
res.json(Helpers.sanitizeWorkflow(payload));
})
);
);
router.use('/', require('../helpers').commonErrorHandler);
module.exports = router;