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

SIMSBIOHUB-424: Support Artifact Intake + Misc Enhancements #230

Merged
merged 45 commits into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
d5e502a
* Support artifact intake.
NickPhura Jan 10, 2024
b1fbf4d
Fix migrations, and some code smells
NickPhura Jan 10, 2024
6aee374
Add back source_system column.
NickPhura Jan 10, 2024
2c60d88
Update submission intake: validation and submission feature insert steps
NickPhura Jan 11, 2024
9922feb
Fix submission intake
NickPhura Jan 12, 2024
5bbe6ec
Fix codes types/endpoint validation errors
NickPhura Jan 12, 2024
d713b8b
Fix most tests
NickPhura Jan 12, 2024
74c40b6
Fix bugs, fix tests
NickPhura Jan 13, 2024
44dacc0
Merge branch 'dev' into SIMSBIOHUB-424
NickPhura Jan 13, 2024
92809e0
Fix tests after merging in dev
NickPhura Jan 13, 2024
4ac27e5
Merge remote-tracking branch 'origin/dev' into SIMSBIOHUB-424
NickPhura Jan 15, 2024
cfcf0d3
Run fix
NickPhura Jan 15, 2024
8bcf94e
Add artifact/intake.test.ts
NickPhura Jan 15, 2024
5cc6362
Update artifact-service.test.ts
NickPhura Jan 15, 2024
19ba18d
Add submission-service.test.ts
NickPhura Jan 15, 2024
472a4b4
SIMSBIOHUB-424: Added tests for searchIndexRepository
curtisupshall Jan 15, 2024
d62dc2f
Merge branch 'SIMSBIOHUB-424' of github.com:bcgov/biohubbc-platform i…
curtisupshall Jan 15, 2024
98ce012
Added test todo
curtisupshall Jan 15, 2024
155132e
Add more submission-service.test.ts
NickPhura Jan 15, 2024
0e15cd4
Add submission-repository.test.ts
NickPhura Jan 15, 2024
7ba312a
Merge branch 'SIMSBIOHUB-424' of https://github.com/bcgov/biohubbc-pl…
NickPhura Jan 15, 2024
aabed16
Add test. Fix multer clamav scan
NickPhura Jan 16, 2024
60740c2
Remove comments
NickPhura Jan 16, 2024
5acf91a
fixed import
al-rosenthal Jan 16, 2024
8ea2036
fixed type checking
al-rosenthal Jan 16, 2024
c91e829
Merge branch 'dev' into SIMSBIOHUB-424
curtisupshall Jan 16, 2024
54cf8f4
fixed import issue
al-rosenthal Jan 16, 2024
2f1ce3b
Remove source_id from submission.
NickPhura Jan 16, 2024
f8fbd1e
Merge branch 'SIMSBIOHUB-424' of https://github.com/bcgov/biohubbc-pl…
NickPhura Jan 16, 2024
fd9f244
Merge remote-tracking branch 'origin/dev' into SIMSBIOHUB-424
NickPhura Jan 17, 2024
34fc994
Merge branch 'dev' into SIMSBIOHUB-424
al-rosenthal Jan 18, 2024
9189a72
fixed seed file, moved region inserts into migration
al-rosenthal Jan 18, 2024
81596e4
Fix submission intake.
NickPhura Jan 19, 2024
b17b98f
Merge branch 'SIMSBIOHUB-424' of https://github.com/bcgov/biohubbc-pl…
NickPhura Jan 19, 2024
16b78ef
Fix submission ingest not assigning parent submission feature id.
NickPhura Jan 19, 2024
7b9f83a
ignore-skip
NickPhura Jan 19, 2024
6ba17a0
Skip deprecated test
NickPhura Jan 19, 2024
d544250
Update getFeatures endpoint to return search keys as data, in place o…
NickPhura Jan 20, 2024
cead2fd
All of the updates/fixes/enhancements
NickPhura Jan 20, 2024
f6c97d2
Fix seeding so it no longer creates submissions with no features (whi…
NickPhura Jan 20, 2024
a3a942e
Fix 2 more endpoint openapi specs.
NickPhura Jan 22, 2024
307b562
ignore-skip
NickPhura Jan 22, 2024
9cc6379
Remove unused code
NickPhura Jan 22, 2024
2656291
PR comments
NickPhura Jan 22, 2024
9448c5c
Merge branch 'dev' into SIMSBIOHUB-424
NickPhura Jan 23, 2024
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
2 changes: 1 addition & 1 deletion api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"fast-xml-parser": "~4.1.3",
"fastq": "^1.15.0",
"json-schema-traverse": "^1.0.0",
"jsonpath-plus": "~7.2.0",
"jsonpath-plus": "^8.0.0",
"jsonwebtoken": "~8.5.1",
"jwks-rsa": "~2.0.5",
"knex": "~2.4.2",
Expand Down
22 changes: 15 additions & 7 deletions api/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
import swaggerUIExperss from 'swagger-ui-express';
import { defaultPoolConfig, initDBPool } from './database/db';
import { initDBConstants } from './database/db-constants';
import { ensureHTTPError, HTTPErrorType } from './errors/http-error';
import { ensureHTTPError, HTTP400, HTTPErrorType } from './errors/http-error';
import { rootAPIDoc } from './openapi/root-api-doc';
import { authenticateRequest, authenticateRequestOptional } from './request-handlers/security/authentication';
import { scanFileForVirus } from './utils/file-utils';
import { getLogger } from './utils/logger';

const defaultLog = getLogger('app');
Expand Down Expand Up @@ -53,22 +54,29 @@
docsPath: '/raw-api-docs', // path to view raw openapi spec
consumesMiddleware: {
'application/json': express.json({ limit: MAX_REQ_BODY_SIZE }),
'multipart/form-data': function (req, res, next) {
'multipart/form-data': async function (req, res, next) {
const multerRequestHandler = multer({
storage: multer.memoryStorage(),
storage: multer.memoryStorage(), // TOOD change to local/PVC storage and stream file uploads to S3?
limits: { fileSize: MAX_UPLOAD_FILE_SIZE }
}).array('media', MAX_UPLOAD_NUM_FILES);

multerRequestHandler(req, res, (error?: any) => {
return multerRequestHandler(req, res, async function (error?: any) {

Check warning on line 63 in api/src/app.ts

View check run for this annotation

Codecov / codecov/patch

api/src/app.ts#L63

Added line #L63 was not covered by tests
if (error) {
return next(error);
}

if (req.files && req.files.length) {
const promises = (req.files as Express.Multer.File[]).map(async function (file) {

Check warning on line 68 in api/src/app.ts

View check run for this annotation

Codecov / codecov/patch

api/src/app.ts#L68

Added line #L68 was not covered by tests
// Set original request file field to empty string to satisfy OpenAPI validation
// See: https://www.npmjs.com/package/express-openapi#argsconsumesmiddleware
(req.files as Express.Multer.File[]).forEach((file) => (req.body[file.fieldname] = ''));
}
req.body[file.fieldname] = '';

Check warning on line 71 in api/src/app.ts

View check run for this annotation

Codecov / codecov/patch

api/src/app.ts#L71

Added line #L71 was not covered by tests

// Scan file for malicious content, if enabled
if (!(await scanFileForVirus(file))) {
throw new HTTP400('Malicious file content detected.', [{ file_name: file.originalname }]);

Check warning on line 75 in api/src/app.ts

View check run for this annotation

Codecov / codecov/patch

api/src/app.ts#L75

Added line #L75 was not covered by tests
}
});

await Promise.all(promises);

Check warning on line 79 in api/src/app.ts

View check run for this annotation

Codecov / codecov/patch

api/src/app.ts#L79

Added line #L79 was not covered by tests

return next();
});
Expand Down
2 changes: 1 addition & 1 deletion api/src/database/db-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
*/
const parseError = (error: any) => {
if (error instanceof z.ZodError) {
throw new ApiExecuteSQLError('SQL response failed schema check', [error]);
throw new ApiExecuteSQLError('SQL response failed schema check', [error as Record<string, any>]);

Check warning on line 44 in api/src/database/db-utils.ts

View check run for this annotation

Codecov / codecov/patch

api/src/database/db-utils.ts#L44

Added line #L44 was not covered by tests
}

if (error.message === 'CONCURRENCY_EXCEPTION') {
Expand Down
2 changes: 1 addition & 1 deletion api/src/database/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@

_systemUserId = response?.rows?.[0].api_set_context;
} catch (error) {
throw new ApiExecuteSQLError('Failed to set user context', [error as object]);
throw new ApiExecuteSQLError('Failed to set user context', [error as Record<string, unknown>]);

Check warning on line 395 in api/src/database/db.ts

View check run for this annotation

Codecov / codecov/patch

api/src/database/db.ts#L395

Added line #L395 was not covered by tests
}
};

Expand Down
10 changes: 5 additions & 5 deletions api/src/errors/api-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ export enum ApiErrorType {
}

export class ApiError extends Error {
errors?: (string | object)[];
errors?: (string | Record<string, unknown>)[];

constructor(name: ApiErrorType, message: string, errors?: (string | object)[], stack?: string) {
constructor(name: ApiErrorType, message: string, errors?: (string | Record<string, unknown>)[], stack?: string) {
super(message);

this.name = name;
Expand All @@ -33,7 +33,7 @@ export class ApiError extends Error {
* @extends {ApiError}
*/
export class ApiGeneralError extends ApiError {
constructor(message: string, errors?: (string | object)[]) {
constructor(message: string, errors?: (string | Record<string, unknown>)[]) {
super(ApiErrorType.GENERAL, message, errors);
}
}
Expand All @@ -46,7 +46,7 @@ export class ApiGeneralError extends ApiError {
* @extends {ApiError}
*/
export class ApiUnknownError extends ApiError {
constructor(message: string, errors?: (string | object)[]) {
constructor(message: string, errors?: (string | Record<string, unknown>)[]) {
super(ApiErrorType.UNKNOWN, message, errors);
}
}
Expand All @@ -63,7 +63,7 @@ export class ApiUnknownError extends ApiError {
* @extends {ApiError}
*/
export class ApiExecuteSQLError extends ApiError {
constructor(message: string, errors?: (string | object)[]) {
constructor(message: string, errors?: (string | Record<string, unknown>)[]) {
super(ApiErrorType.EXECUTE_SQL, message, errors);
}
}
22 changes: 14 additions & 8 deletions api/src/errors/http-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@ export enum HTTPErrorType {

export class HTTPError extends Error {
status: number;
errors?: (string | object)[];

constructor(name: HTTPErrorType, status: number, message: string, errors?: (string | object)[], stack?: string) {
errors?: (string | Record<string, unknown>)[];

constructor(
name: HTTPErrorType,
status: number,
message: string,
errors?: (string | Record<string, unknown>)[],
stack?: string
) {
super(message);

this.name = name;
Expand All @@ -38,7 +44,7 @@ export class HTTPError extends Error {
* @extends {HTTPError}
*/
export class HTTP400 extends HTTPError {
constructor(message: string, errors?: (string | object)[]) {
constructor(message: string, errors?: (string | Record<string, unknown>)[]) {
super(HTTPErrorType.BAD_REQUEST, 400, message, errors);
}
}
Expand All @@ -51,7 +57,7 @@ export class HTTP400 extends HTTPError {
* @extends {HTTPError}
*/
export class HTTP401 extends HTTPError {
constructor(message: string, errors?: (string | object)[]) {
constructor(message: string, errors?: (string | Record<string, unknown>)[]) {
super(HTTPErrorType.UNAUTHORIZE, 401, message, errors);
}
}
Expand All @@ -64,7 +70,7 @@ export class HTTP401 extends HTTPError {
* @extends {HTTPError}
*/
export class HTTP403 extends HTTPError {
constructor(message: string, errors?: (string | object)[]) {
constructor(message: string, errors?: (string | Record<string, unknown>)[]) {
super(HTTPErrorType.FORBIDDEN, 403, message, errors);
}
}
Expand All @@ -77,7 +83,7 @@ export class HTTP403 extends HTTPError {
* @extends {HTTPError}
*/
export class HTTP409 extends HTTPError {
constructor(message: string, errors?: (string | object)[]) {
constructor(message: string, errors?: (string | Record<string, unknown>)[]) {
super(HTTPErrorType.CONFLICT, 409, message, errors);
}
}
Expand All @@ -90,7 +96,7 @@ export class HTTP409 extends HTTPError {
* @extends {HTTPError}
*/
export class HTTP500 extends HTTPError {
constructor(message: string, errors?: (string | object)[]) {
constructor(message: string, errors?: (string | Record<string, unknown>)[]) {
super(HTTPErrorType.INTERNAL_SERVER_ERROR, 500, message, errors);
}
}
Expand Down
51 changes: 15 additions & 36 deletions api/src/openapi/root-api-doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,60 +143,39 @@ export const rootAPIDoc = {
},
SubmissionFeature: {
title: 'BioHub Data Submission Feature',
description:
'The submission feature object is a self-referencing recursive structure designed to support different classes of biotic data, in a hierarchical structure.',
type: 'object',
required: ['id', 'type', 'properties', 'features'],
required: ['type', 'properties', 'child_features'],
properties: {
id: {
title: 'Unique id of the feature',
type: 'string'
title: 'Unique identifer.',
description:
'The unique identifier for the submission feature as supplied by the source system. May not be unique globally or within BioHub.',
type: 'string',
maxLength: 200
},
type: {
title: 'Feature type',
title: 'Feature type.',
description: 'The type of the feature. Must match a supported feature type.',
type: 'string'
},
properties: {
title: 'Feature properties',
title: 'Feature properties.',
description: 'The properties of the feature, which are specific to the feature type.',
type: 'object',
properties: {}
},
features: {
title: 'Feature child features',
child_features: {
title: 'Child features.',
description: 'Child features of the current feature.',
type: 'array',
items: {
$ref: '#/components/schemas/SubmissionFeature'
}
}
},
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'
},
submission_feature_security_ids: {
nullable: true,
type: 'array',
items: {
type: 'number'
}
},
parent_submission_feature_id: {
type: 'number',
nullable: true
}
}
}
}
}
Expand Down
27 changes: 0 additions & 27 deletions api/src/openapi/schemas/biohub-data-submission.ts

This file was deleted.

6 changes: 4 additions & 2 deletions api/src/paths/administrative/security/categories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,15 @@ GET.apiDoc = {
nullable: true
},
update_user: {
type: 'string',
type: 'integer',
minimum: 1,
nullable: true
},
revision_count: {
type: 'integer'
}
}
},
additionalProperties: false
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion api/src/paths/administrative/security/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ GET.apiDoc = {
'description',
'record_effective_date',
'record_end_date',
'security_category_id',
'category_name',
'category_description',
'category_record_effective_date',
Expand All @@ -68,6 +69,10 @@ GET.apiDoc = {
type: 'string',
nullable: true
},
security_category_id: {
type: 'integer',
minimum: 1
},
category_name: {
type: 'string'
},
Expand All @@ -81,7 +86,8 @@ GET.apiDoc = {
type: 'string',
nullable: true
}
}
},
additionalProperties: false
}
}
}
Expand Down
52 changes: 47 additions & 5 deletions api/src/paths/administrative/security/submission/{submissionId}.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,60 @@ GET.apiDoc = {
type: 'array',
items: {
type: 'object',
required: ['submission_feature_security_id', 'submission_feature_id', 'security_rule_id'],
required: [
'submission_feature_security_id',
'submission_feature_id',
'security_rule_id',
'record_effective_date',
'record_end_date',
'create_date',
'create_user',
'update_date',
'update_user',
'revision_count'
],
properties: {
submission_feature_security_id: {
type: 'integer'
type: 'integer',
minimum: 1
},
submission_feature_id: {
type: 'integer'
type: 'integer',
minimum: 1
},
security_rule_id: {
type: 'integer'
type: 'integer',
minimum: 1
},
record_effective_date: {
type: 'string'
},
record_end_date: {
type: 'string',
nullable: true
},
create_date: {
type: 'string'
},
create_user: {
type: 'integer',
minimum: 1
},
update_date: {
type: 'string',
nullable: true
},
update_user: {
type: 'integer',
minimum: 1,
nullable: true
},
revision_count: {
type: 'integer',
minimum: 0
}
}
},
additionalProperties: false
}
}
}
Expand Down
Loading
Loading