@overture-stack/lyric
Version:
Data Submission system
171 lines (170 loc) • 9.56 kB
JavaScript
import * as _ from 'lodash-es';
import { shouldBypassAuth } from '../middleware/auth.js';
import submittedDataService from '../services/submittedData/submmittedData.js';
import { getUserReadableOrganizations, hasUserReadAccess } from '../utils/authUtils.js';
import { parseSQON } from '../utils/convertSqonToQuery.js';
import { Forbidden, NotFound } from '../utils/errors.js';
import { asArray } from '../utils/formatUtils.js';
import { validateRequest } from '../utils/requestValidation.js';
import { dataGetByCategoryRequestSchema, dataGetByOrganizationRequestSchema, dataGetByQueryRequestSchema, DataGetBySystemIdRequestSchema, } from '../utils/schemas.js';
import { convertToViewType } from '../utils/submittedDataUtils.js';
import { VIEW_TYPE } from '../utils/types.js';
const controller = ({ baseDependencies, authConfig, }) => {
const service = submittedDataService(baseDependencies);
const { logger } = baseDependencies;
const LOG_MODULE = 'SUBMITTED_DATA_CONTROLLER';
const defaultPage = 1;
const defaultPageSize = 20;
const defaultView = VIEW_TYPE.Values.flat;
return {
getSubmittedDataByCategory: validateRequest(dataGetByCategoryRequestSchema, async (req, res, next) => {
try {
const categoryId = Number(req.params.categoryId);
// query params
const entityName = asArray(req.query.entityName || []);
const page = parseInt(String(req.query.page)) || defaultPage;
const pageSize = parseInt(String(req.query.pageSize)) || defaultPageSize;
const view = convertToViewType(req.query.view) || defaultView;
const user = req.user;
logger.info(LOG_MODULE, `Request Submitted Data on categoryId '${categoryId}'`, `pagination params: page '${page}' pageSize '${pageSize}'`, `view '${view}'`);
const organizations = getUserReadableOrganizations(user);
const submittedDataResult = await service.getSubmittedDataByCategory(categoryId, { page, pageSize }, { entityName, view, organizations });
if (_.isEmpty(submittedDataResult.result)) {
throw new NotFound('No Submitted Data found');
}
const response = {
pagination: {
currentPage: page,
pageSize: pageSize,
totalPages: Math.ceil(submittedDataResult.metadata.totalRecords / pageSize),
totalRecords: submittedDataResult.metadata.totalRecords,
},
records: submittedDataResult.result,
};
return res.status(200).send(response);
}
catch (error) {
next(error);
}
}),
getSubmittedDataByOrganization: validateRequest(dataGetByOrganizationRequestSchema, async (req, res, next) => {
try {
const categoryId = Number(req.params.categoryId);
const organization = req.params.organization;
// query parameters
const entityName = asArray(req.query.entityName || []);
const page = parseInt(String(req.query.page)) || defaultPage;
const pageSize = parseInt(String(req.query.pageSize)) || defaultPageSize;
const view = convertToViewType(String(req.query.view)) || defaultView;
const user = req.user;
logger.info(LOG_MODULE, `Request Submitted Data on categoryId '${categoryId}' and organization '${organization}'`, `pagination params: page '${page}' pageSize '${pageSize}'`, `view '${view}'`);
if (!shouldBypassAuth(req, authConfig) && !hasUserReadAccess(organization, user)) {
throw new Forbidden(`User is not authorized to read submitted data for organization '${organization}'`);
}
const submittedDataResult = await service.getSubmittedDataByOrganization(categoryId, organization, {
page,
pageSize,
}, { entityName, view });
if (submittedDataResult.metadata.errorMessage) {
throw new NotFound(submittedDataResult.metadata.errorMessage);
}
const responsePaginated = {
pagination: {
currentPage: page,
pageSize: pageSize,
totalPages: Math.ceil(submittedDataResult.metadata.totalRecords / pageSize),
totalRecords: submittedDataResult.metadata.totalRecords,
},
records: submittedDataResult.result,
};
return res.status(200).send(responsePaginated);
}
catch (error) {
next(error);
}
}),
getSubmittedDataByQuery: validateRequest(dataGetByQueryRequestSchema, async (req, res, next) => {
try {
const categoryId = Number(req.params.categoryId);
const organization = req.params.organization;
const sqon = parseSQON(req.body);
// query parameters
const entityName = asArray(req.query.entityName || []);
const page = parseInt(String(req.query.page)) || defaultPage;
const pageSize = parseInt(String(req.query.pageSize)) || defaultPageSize;
const user = req.user;
logger.info(LOG_MODULE, 'Request Query Submitted Data', `categoryId '${categoryId}'`, `organization '${organization}'`, `sqon '${JSON.stringify(sqon)}'`, `pagination params: page '${page}' pageSize '${pageSize}'`);
if (!shouldBypassAuth(req, authConfig) && !hasUserReadAccess(organization, user)) {
throw new Forbidden(`User is not authorized to read submitted data for organization '${organization}'`);
}
const submittedDataResult = await service.getSubmittedDataByOrganization(categoryId, organization, {
page,
pageSize,
}, { sqon, entityName, view: VIEW_TYPE.Values.flat });
if (submittedDataResult.metadata.errorMessage) {
throw new NotFound(submittedDataResult.metadata.errorMessage);
}
const responsePaginated = {
pagination: {
currentPage: page,
pageSize: pageSize,
totalPages: Math.ceil(submittedDataResult.metadata.totalRecords / pageSize),
totalRecords: submittedDataResult.metadata.totalRecords,
},
records: submittedDataResult.result,
};
return res.status(200).send(responsePaginated);
}
catch (error) {
next(error);
}
}),
getSubmittedDataBySystemId: validateRequest(DataGetBySystemIdRequestSchema, async (req, res, next) => {
try {
const categoryId = Number(req.params.categoryId);
const systemId = req.params.systemId;
const view = convertToViewType(String(req.query.view)) || defaultView;
const user = req.user;
logger.info(LOG_MODULE, 'Request Submitted Data', `categoryId '${categoryId}'`, `systemId '${systemId}'`, `params: view '${view}'`);
const submittedDataResult = await service.getSubmittedDataBySystemId(categoryId, systemId, {
view,
});
if (submittedDataResult.metadata.errorMessage) {
throw new NotFound(submittedDataResult.metadata.errorMessage);
}
if (!shouldBypassAuth(req, authConfig) &&
!hasUserReadAccess(submittedDataResult.result?.organization || '', user)) {
throw new Forbidden(`User is not authorized to read submitted data for organization '${submittedDataResult.result?.organization}'`);
}
return res.status(200).send(submittedDataResult.result);
}
catch (error) {
next(error);
}
}),
getSubmittedDataByCategoryStream: validateRequest(dataGetByCategoryRequestSchema, async (req, res, next) => {
try {
const categoryId = Number(req.params.categoryId);
const entityName = asArray(req.query.entityName || []);
const view = convertToViewType(String(req.query.view)) || defaultView;
const user = req.user;
logger.info(LOG_MODULE, `Request stream for submitted data on categoryId '${categoryId}'`);
const organizations = getUserReadableOrganizations(user);
res.setHeader('Transfer-Encoding', 'chunked');
res.setHeader('Content-Type', 'application/x-ndjson');
for await (const data of service.getSubmittedDataByCategoryStream(categoryId, {
view,
entityName,
organizations,
})) {
res.write(JSON.stringify(data) + '\n');
}
res.end();
}
catch (error) {
next(error);
}
}),
};
};
export default controller;