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-627: Fix Manage Telemetry Page #1452

Merged
merged 13 commits into from
Dec 16, 2024
4 changes: 0 additions & 4 deletions api/.pipeline/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ const phases = {
backboneArtifactIntakePath: '/api/artifact/intake',
biohubTaxonPath: '/api/taxonomy/taxon',
biohubTaxonTsnPath: '/api/taxonomy/taxon/tsn',
bctwApiHost: 'https://moe-bctw-api-dev.apps.silver.devops.gov.bc.ca',
critterbaseApiHost: 'https://moe-critterbase-api-dev.apps.silver.devops.gov.bc.ca/api',
nodeEnv: 'development',
s3KeyPrefix: (isStaticDeployment && 'sims') || `local/${deployChangeId}/sims`,
Expand Down Expand Up @@ -130,7 +129,6 @@ const phases = {
backboneArtifactIntakePath: '/api/artifact/intake',
biohubTaxonPath: '/api/taxonomy/taxon',
biohubTaxonTsnPath: '/api/taxonomy/taxon/tsn',
bctwApiHost: 'https://moe-bctw-api-test.apps.silver.devops.gov.bc.ca',
critterbaseApiHost: 'https://moe-critterbase-api-test.apps.silver.devops.gov.bc.ca/api',
nodeEnv: 'production',
s3KeyPrefix: 'sims',
Expand Down Expand Up @@ -175,7 +173,6 @@ const phases = {
backboneArtifactIntakePath: '/api/artifact/intake',
biohubTaxonPath: '/api/taxonomy/taxon',
biohubTaxonTsnPath: '/api/taxonomy/taxon/tsn',
bctwApiHost: 'https://moe-bctw-api-test.apps.silver.devops.gov.bc.ca',
critterbaseApiHost: 'https://moe-critterbase-api-test.apps.silver.devops.gov.bc.ca/api',
nodeEnv: 'production',
s3KeyPrefix: 'sims',
Expand Down Expand Up @@ -220,7 +217,6 @@ const phases = {
backboneArtifactIntakePath: '/api/artifact/intake',
biohubTaxonPath: '/api/taxonomy/taxon',
biohubTaxonTsnPath: '/api/taxonomy/taxon/tsn',
bctwApiHost: 'https://moe-bctw-api-prod.apps.silver.devops.gov.bc.ca',
critterbaseApiHost: 'https://moe-critterbase-api-prod.apps.silver.devops.gov.bc.ca/api',
nodeEnv: 'production',
s3KeyPrefix: 'sims',
Expand Down
3 changes: 1 addition & 2 deletions api/.pipeline/lib/api.deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ const apiDeploy = async (settings) => {
BACKBONE_ARTIFACT_INTAKE_PATH: phases[phase].backboneArtifactIntakePath,
BIOHUB_TAXON_PATH: phases[phase].biohubTaxonPath,
BIOHUB_TAXON_TSN_PATH: phases[phase].biohubTaxonTsnPath,
// BCTW / Critterbase
BCTW_API_HOST: phases[phase].bctwApiHost,
// Critterbase
CB_API_HOST: phases[phase].critterbaseApiHost,
// S3
S3_KEY_PREFIX: phases[phase].s3KeyPrefix,
Expand Down
9 changes: 2 additions & 7 deletions api/.pipeline/templates/api.dc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,10 @@ parameters:
- name: BIOHUB_TAXON_PATH
required: true
description: API path for BioHub Platform Backbone taxon endpoint. Example "/api/path/to/taxon".
# BCTW / Critterbase
# Critterbase
- name: CB_API_HOST
description: API host for the Critterbase service, SIMS API will hit this to retrieve critter metadata. Example "https://critterbase.com".
required: true
- name: BCTW_API_HOST
description: API host for the BC Telemetry Warehouse service. SIMS API will hit this for device deployments and other telemetry operations. Example "https://bctw.com".
required: true
# Database
- name: TZ
description: Application timezone
Expand Down Expand Up @@ -309,11 +306,9 @@ objects:
value: ${BIOHUB_TAXON_TSN_PATH}
- name: BIOHUB_TAXON_PATH
value: ${BIOHUB_TAXON_PATH}
# BCTW / Critterbase
# Critterbase
- name: CB_API_HOST
value: ${CB_API_HOST}
- name: BCTW_API_HOST
value: ${BCTW_API_HOST}
# Clamav
- name: ENABLE_FILE_VIRUS_SCAN
value: ${ENABLE_FILE_VIRUS_SCAN}
Expand Down
99 changes: 0 additions & 99 deletions api/src/models/bctw.ts

This file was deleted.

25 changes: 25 additions & 0 deletions api/src/models/deployment-view.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export interface IDeploymentAdvancedFilters {
/**
* Filter results by system user id.
*
* Note: This is not the id of the user making the request.
*
* @type {number}
* @memberof IAnimalAdvancedFilters
*/
system_user_id?: number;
/**
* Filter results by deployment ids.
*
* @type {number[]}
* @memberof IDeploymentAdvancedFilters
*/
deployment_ids?: number[];
/**
* Filter results by survey ids.
*
* @type {number[]}
* @memberof IAnimalAdvancedFilters
*/
survey_ids?: number[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import * as db from '../../../../../../../database/db';
import { HTTPError } from '../../../../../../../errors/http-error';
import { SurveyTelemetryCredentialAttachment } from '../../../../../../../repositories/attachment-repository';
import { AttachmentService } from '../../../../../../../services/attachment-service';
import { BctwKeyxService } from '../../../../../../../services/bctw-service/bctw-keyx-service';
import * as file_utils from '../../../../../../../utils/file-utils';
import { KeycloakUserInformation } from '../../../../../../../utils/keycloak-utils';
import { getMockDBConnection, getRequestHandlerMocks } from '../../../../../../../__mocks__/db';
Expand Down Expand Up @@ -53,7 +52,7 @@ describe('postSurveyTelemetryCredentialAttachment', () => {
}
});

it('succeeds and uploads a KeyX file to BCTW', async () => {
it('successfully imports a credential file', async () => {
const dbConnectionObj = getMockDBConnection();
sinon.stub(db, 'getDBConnection').returns(dbConnectionObj);

Expand All @@ -63,47 +62,6 @@ describe('postSurveyTelemetryCredentialAttachment', () => {

const uploadFileToS3Stub = sinon.stub(file_utils, 'uploadFileToS3').resolves();

const uploadKeyXStub = sinon.stub(BctwKeyxService.prototype, 'uploadKeyX').resolves();

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

mockReq.keycloak_token = {} as KeycloakUserInformation;
mockReq.params = {
projectId: '1',
surveyId: '2'
};
mockReq.files = [
{
fieldname: 'media',
originalname: 'test.keyx',
encoding: '7bit',
mimetype: 'text/plain',
size: 340
}
] as Express.Multer.File[];

const requestHandler = postSurveyTelemetryCredentialAttachment();

await requestHandler(mockReq, mockRes, mockNext);

expect(mockRes.jsonValue).to.eql({ survey_telemetry_credential_attachment_id: 44 });
expect(upsertSurveyTelemetryCredentialAttachmentStub).to.be.calledOnce;
expect(uploadKeyXStub).to.be.calledOnce;
expect(uploadFileToS3Stub).to.be.calledOnce;
});

it('succeeds and does not upload a Cfg file to BCTW', async () => {
const dbConnectionObj = getMockDBConnection();
sinon.stub(db, 'getDBConnection').returns(dbConnectionObj);

const upsertSurveyTelemetryCredentialAttachmentStub = sinon
.stub(AttachmentService.prototype, 'upsertSurveyTelemetryCredentialAttachment')
.resolves({ survey_telemetry_credential_attachment_id: 44, key: 'path/to/file/test.keyx' });

const uploadFileToS3Stub = sinon.stub(file_utils, 'uploadFileToS3').resolves();

const uploadKeyXStub = sinon.stub(BctwKeyxService.prototype, 'uploadKeyX').resolves();

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

mockReq.keycloak_token = {} as KeycloakUserInformation;
Expand All @@ -127,20 +85,18 @@ describe('postSurveyTelemetryCredentialAttachment', () => {

expect(mockRes.jsonValue).to.eql({ survey_telemetry_credential_attachment_id: 44 });
expect(upsertSurveyTelemetryCredentialAttachmentStub).to.be.calledOnce;
expect(uploadKeyXStub).not.to.be.called; // not called
expect(uploadFileToS3Stub).to.be.calledOnce;
});

it('should catch and re-throw an error', async () => {
const dbConnectionObj = getMockDBConnection();
sinon.stub(db, 'getDBConnection').returns(dbConnectionObj);

const mockError = new Error('A test error');

const upsertSurveyTelemetryCredentialAttachmentStub = sinon
.stub(AttachmentService.prototype, 'upsertSurveyTelemetryCredentialAttachment')
.resolves({ survey_telemetry_credential_attachment_id: 44, key: 'path/to/file/test.keyx' });

const mockError = new Error('A test error');
const uploadKeyXStub = sinon.stub(BctwKeyxService.prototype, 'uploadKeyX').rejects(mockError);
.rejects(mockError);

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

Expand Down Expand Up @@ -168,7 +124,6 @@ describe('postSurveyTelemetryCredentialAttachment', () => {
expect((actualError as HTTPError).message).to.equal(mockError.message);

expect(upsertSurveyTelemetryCredentialAttachmentStub).to.have.been.calledOnce;
expect(uploadKeyXStub).to.have.been.calledOnce;
}
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { RequestHandler } from 'express';
import { Operation } from 'express-openapi';
import { TELEMETRY_CREDENTIAL_ATTACHMENT_TYPE } from '../../../../../../../constants/attachments';
import { PROJECT_PERMISSION, SYSTEM_ROLE } from '../../../../../../../constants/roles';
import { getDBConnection } from '../../../../../../../database/db';
import { HTTP400 } from '../../../../../../../errors/http-error';
import { fileSchema } from '../../../../../../../openapi/schemas/file';
import { authorizeRequestHandler } from '../../../../../../../request-handlers/security/authorization';
import { AttachmentService } from '../../../../../../../services/attachment-service';
import { BctwKeyxService } from '../../../../../../../services/bctw-service/bctw-keyx-service';
import { getBctwUser } from '../../../../../../../services/bctw-service/bctw-service';
import { uploadFileToS3 } from '../../../../../../../utils/file-utils';
import { getLogger } from '../../../../../../../utils/logger';
import { isValidTelementryCredentialFile } from '../../../../../../../utils/media/media-utils';
Expand Down Expand Up @@ -157,12 +154,6 @@ export function postSurveyTelemetryCredentialAttachment(): RequestHandler {
isTelemetryCredentialFile.type
);

// Upload telemetry credential file content to BCTW (for supported file types)
if (isTelemetryCredentialFile.type === TELEMETRY_CREDENTIAL_ATTACHMENT_TYPE.KEYX) {
const bctwKeyxService = new BctwKeyxService(getBctwUser(req));
await bctwKeyxService.uploadKeyX(rawMediaFile);
}

// Upload telemetry credential file to SIMS S3 Storage
const metadata = {
filename: rawMediaFile.originalname,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { TelemetryDeploymentService } from '../../../../../../../../services/tel
import { getLogger } from '../../../../../../../../utils/logger';
import { numberOrNull } from '../../../../../../../../utils/string-utils';

const defaultLog = getLogger('paths/project/{projectId}/survey/{surveyId}/critters/{critterId}/deployments');
const defaultLog = getLogger('paths/project/{projectId}/survey/{surveyId}/critters/{critterId}/deployments2');

export const POST: Operation = [
authorizeRequestHandler((req) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import { getDBConnection } from '../../../../../../../database/db';
import { HTTP400, HTTPError, HTTPErrorType } from '../../../../../../../errors/http-error';
import { bulkUpdateResponse, critterBulkRequestObject } from '../../../../../../../openapi/schemas/critter';
import { authorizeRequestHandler } from '../../../../../../../request-handlers/security/authorization';
import { getBctwUser } from '../../../../../../../services/bctw-service/bctw-service';
import { CritterAttachmentService } from '../../../../../../../services/critter-attachment-service';
import { CritterbaseService, ICritterbaseUser } from '../../../../../../../services/critterbase-service';
import {
CritterbaseService,
getCritterbaseUser,
ICritterbaseUser
} from '../../../../../../../services/critterbase-service';
import { SurveyCritterService } from '../../../../../../../services/survey-critter-service';
import { getLogger } from '../../../../../../../utils/logger';

Expand Down Expand Up @@ -95,7 +98,7 @@ export function updateSurveyCritter(): RequestHandler {
const connection = getDBConnection(req.keycloak_token);
try {
await connection.open();
const user = getBctwUser(req);
const user = getCritterbaseUser(req);

if (!critterbaseCritterId) {
throw new HTTPError(HTTPErrorType.BAD_REQUEST, 400, 'No external critter ID was found.');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const GET: Operation = [

GET.apiDoc = {
description: 'Get telemetry points for a specific critter.',
tags: ['bctw'],
tags: ['telemetry'],
security: [
{
Bearer: []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,15 @@ describe('getDeploymentsInSurvey', () => {
critterbase_end_capture_id: null,
critterbase_end_mortality_id: null,
// device data
serial: '1234',
device_make_id: 1,
model: 'ModelX',
// critter data
critterbase_critter_id: 'critter123'
}
];

sinon.stub(TelemetryDeploymentService.prototype, 'getDeploymentsForSurveyId').resolves(mockDeployments);
sinon.stub(TelemetryDeploymentService.prototype, 'getDeploymentsForSurvey').resolves(mockDeployments);
sinon.stub(TelemetryDeploymentService.prototype, 'getDeploymentsCount').resolves(1);

const { mockReq, mockRes, mockNext } = getRequestHandlerMocks();
Expand Down Expand Up @@ -78,7 +79,7 @@ describe('getDeploymentsInSurvey', () => {
const mockError = new Error('Test error');

const getDeploymentsForSurveyIdStub = sinon
.stub(TelemetryDeploymentService.prototype, 'getDeploymentsForSurveyId')
.stub(TelemetryDeploymentService.prototype, 'getDeploymentsForSurvey')
.rejects(mockError);

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