Skip to content

Commit

Permalink
Merge branch 'dataset_security_feature' into SIMSBIOHUB-379
Browse files Browse the repository at this point in the history
  • Loading branch information
curtisupshall committed Dec 11, 2023
2 parents b5953dd + 49636ee commit e607077
Show file tree
Hide file tree
Showing 38 changed files with 1,636 additions and 371 deletions.
22 changes: 22 additions & 0 deletions api/src/openapi/root-api-doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,28 @@ export const rootAPIDoc = {
}
},
additionalProperties: false
},
feature: {
type: 'object',
required: ['submission_feature_id', 'submission_id', 'feature_type', 'data', 'parent_submission_feature_id'],
properties: {
submission_feature_id: {
type: 'number'
},
submission_id: {
type: 'number'
},
feature_type: {
type: 'string'
},
data: {
type: 'object'
},
parent_submission_feature_id: {
type: 'number',
nullable: true
}
}
}
}
}
Expand Down
133 changes: 133 additions & 0 deletions api/src/paths/administrative/security/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { RequestHandler } from 'express';
import { Operation } from 'express-openapi';
import { SYSTEM_ROLE } from '../../../constants/roles';
import { getDBConnection } from '../../../database/db';
import { authorizeRequestHandler } from '../../../request-handlers/security/authorization';
import { SecurityService } from '../../../services/security-service';
import { getLogger } from '../../../utils/logger';

const defaultLog = getLogger('paths/administrative/security');

export const GET: Operation = [
authorizeRequestHandler(() => {
return {
and: [
{
validSystemRoles: [SYSTEM_ROLE.SYSTEM_ADMIN],
discriminator: 'SystemRole'
}
]
};
}),
() => {}

Check failure on line 22 in api/src/paths/administrative/security/index.ts

View workflow job for this annotation

GitHub Actions / Running Linter and Formatter

Unexpected empty arrow function
];

GET.apiDoc = {
description: 'Get all observations for the survey.',
tags: ['observation'],
security: [
{
Bearer: []
}
],
parameters: [
{
in: 'path',
name: 'projectId',
schema: {
type: 'number',
minimum: 1
},
required: true
},
{
in: 'path',
name: 'surveyId',
schema: {
type: 'number',
minimum: 1
},
required: true
}
],
responses: {
200: {
description: 'Security Rules.',
content: {
'application/json': {
schema: {
type: 'array',
items: {
type: 'object',
properties: {
security_rule_id: {
type: 'number'
},
name: {
type: 'string'
},
description: {
type: 'string'
},
record_effective_date: {
type: 'string'
},
record_end_date: {
type: 'string'
},
create_date: {
type: 'string'
},
create_user: {
type: 'number'
},
update_date: {
type: 'string'
},
update_user: {
type: 'number'
},
revision_count: {
type: 'string'
}
}
}
}
}
}
},
400: {
$ref: '#/components/responses/400'
},
401: {
$ref: '#/components/responses/401'
},
403: {
$ref: '#/components/responses/403'
},
500: {
$ref: '#/components/responses/500'
},
default: {
$ref: '#/components/responses/default'
}
}
};

export function getActiveSecurityRules(): RequestHandler {
return async (req, res) => {
const connection = getDBConnection(req['keycloak_token']);
const service = new SecurityService(connection);

try {
const data = await service.getActiveSecurityRules();
return res.status(200).json(data);
} catch (error) {
defaultLog.error({ label: 'getActiveSecurityRules', message: 'error', error });
await connection.rollback();
throw error;
} finally {
connection.release();
}
};
}
77 changes: 0 additions & 77 deletions api/src/paths/dataset/{datasetId}/index.ts

This file was deleted.

3 changes: 1 addition & 2 deletions api/src/paths/dwc/submission/{datasetId}/artifacts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import * as db from '../../../../database/db';
import { HTTPError } from '../../../../errors/http-error';
import { Artifact } from '../../../../repositories/artifact-repository';
import { SECURITY_APPLIED_STATUS } from '../../../../repositories/security-repository';
import { ArtifactService } from '../../../../services/artifact-service';
import { SecurityService } from '../../../../services/security-service';
Expand Down Expand Up @@ -219,7 +218,7 @@ describe('getArtifactsByDatasetId', () => {
const artifactServiceStub = sinon.stub(ArtifactService.prototype, 'getArtifactsByDatasetId').resolves([
{ artifact_id: 1, security_review_timestamp: new Date('1970-01-01T00:00:00.000Z') },
{ artifact_id: 2, security_review_timestamp: new Date('1970-01-01T00:00:00.000Z') }
] as Artifact[]);
] as any[]);

const isSystemUserAdminStub = sinon.stub(UserService.prototype, 'isSystemUserAdmin').resolves(true);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import chai, { expect } from 'chai';
import { describe } from 'mocha';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import { getUnreviewedSubmissions } from '.';
import * as db from '../../../../database/db';
import { HTTPError } from '../../../../errors/http-error';
import { SubmissionService } from '../../../../services/submission-service';
import { getMockDBConnection, getRequestHandlerMocks } from '../../../../__mocks__/db';
import { getReviewedSubmissionsWithSecurity } from '.';
import * as db from '../../database/db';
import { HTTPError } from '../../errors/http-error';
import { SubmissionService } from '../../services/submission-service';
import { getMockDBConnection, getRequestHandlerMocks } from '../../__mocks__/db';

chai.use(sinonChai);

Expand All @@ -26,7 +26,7 @@ describe('list', () => {

const { mockReq, mockRes, mockNext } = getRequestHandlerMocks();

const requestHandler = getUnreviewedSubmissions();
const requestHandler = getReviewedSubmissionsWithSecurity();

try {
await requestHandler(mockReq, mockRes, mockNext);
Expand All @@ -36,7 +36,7 @@ describe('list', () => {
}
});

it('should return an array of unreviewed submission objects', async () => {
it('should return an array of Reviewed submission (with security flag) objects', async () => {
const dbConnectionObj = getMockDBConnection({
commit: sinon.stub(),
rollback: sinon.stub(),
Expand All @@ -47,15 +47,15 @@ describe('list', () => {

const { mockReq, mockRes, mockNext } = getRequestHandlerMocks();

const getUnreviewedSubmissionsStub = sinon
.stub(SubmissionService.prototype, 'getUnreviewedSubmissions')
const getReviewedSubmissionsStub = sinon
.stub(SubmissionService.prototype, 'getReviewedSubmissionsWithSecurity')
.resolves([]);

const requestHandler = getUnreviewedSubmissions();
const requestHandler = getReviewedSubmissionsWithSecurity();

await requestHandler(mockReq, mockRes, mockNext);

expect(getUnreviewedSubmissionsStub).to.have.been.calledOnce;
expect(getReviewedSubmissionsStub).to.have.been.calledOnce;
expect(mockRes.statusValue).to.equal(200);
expect(mockRes.jsonValue).to.eql([]);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,21 @@
import { RequestHandler } from 'express';
import { Operation } from 'express-openapi';
import { SYSTEM_ROLE } from '../../../../constants/roles';
import { getDBConnection } from '../../../../database/db';
import { defaultErrorResponses } from '../../../../openapi/schemas/http-responses';
import { authorizeRequestHandler } from '../../../../request-handlers/security/authorization';
import { SubmissionService } from '../../../../services/submission-service';
import { getLogger } from '../../../../utils/logger';
import { getAPIUserDBConnection } from '../../database/db';
import { defaultErrorResponses } from '../../openapi/schemas/http-responses';
import { SubmissionService } from '../../services/submission-service';
import { getLogger } from '../../utils/logger';

const defaultLog = getLogger('paths/administrative/submission/unreviewed');
const defaultLog = getLogger('paths/submission');

export const GET: Operation = [
authorizeRequestHandler(() => {
return {
and: [
{
validSystemRoles: [SYSTEM_ROLE.SYSTEM_ADMIN, SYSTEM_ROLE.DATA_ADMINISTRATOR],
discriminator: 'SystemRole'
}
]
};
}),
getUnreviewedSubmissions()
];
export const GET: Operation = [getReviewedSubmissionsWithSecurity()];

GET.apiDoc = {
description: 'Get a list of submissions that need security review (are unreviewed).',
tags: ['admin'],
security: [
{
Bearer: []
}
],
description: 'Get a list of reviewed submissions',
tags: ['submisssion', 'reviewed'],
security: [],
responses: {
200: {
description: 'List of submissions that need security review.',
description: 'List of reviewed submissions',
content: {
'application/json': {
schema: {
Expand Down Expand Up @@ -95,25 +77,26 @@ GET.apiDoc = {
};

/**
* Get all unreviewed submissions.
* Get all reviewed submissions (with security status).
*
* @returns {RequestHandler}
*/
export function getUnreviewedSubmissions(): RequestHandler {
return async (req, res) => {
const connection = getDBConnection(req['keycloak_token']);
export function getReviewedSubmissionsWithSecurity(): RequestHandler {
return async (_req, res) => {
const connection = getAPIUserDBConnection();

try {
await connection.open();

await connection.commit();

const service = new SubmissionService(connection);
const response = await service.getUnreviewedSubmissions();
const response = await service.getReviewedSubmissionsWithSecurity();

await connection.commit();

return res.status(200).json(response);
} catch (error) {
defaultLog.error({ label: 'getUnreviewedSubmissions', message: 'error', error });
await connection.rollback();
defaultLog.error({ label: 'getReviewedSubmissionsWithSecurity', message: 'error', error });
throw error;
} finally {
connection.release();
Expand Down
Loading

0 comments on commit e607077

Please sign in to comment.