UNPKG

@researchdatabox/sails-hook-redbox-redcap

Version:

Redbox hook for REDCap API

204 lines 20.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Controllers = void 0; require("rxjs/add/operator/map"); const redbox_core_types_1 = require("@researchdatabox/redbox-core-types"); /** * Package that contains all Controllers. */ const Config_1 = require("../Config"); var Controllers; (function (Controllers) { /** * Redcap related features.... * */ class RedcapController extends redbox_core_types_1.Controllers.Core.Controller { _exportedMethods = [ 'project', 'link' ]; config; logHeader = "RedcapController::"; constructor() { super(); let that = this; sails.after(['ready'], function () { that.config = new Config_1.Config(sails.config.workspaces); }); } async project(req, res) { try { var tokenReq = req.param('token'); const token = tokenReq.token; sails.log.debug(token); sails.log.error('Config Object:' + JSON.stringify(this.config)); let config = { url: this.config.location, path: this.config.path }; if (this.config.http != null) { config = { http: this.config.http, host: this.config.host, path: this.config.path }; } sails.log.verbose(`${this.logHeader} project() -> Config: ${JSON.stringify(config)}`); sails.log.verbose(`${this.logHeader} project() -> notesHeader: ${sails.config.redcap.notesHeader}`); const projectInfo = await RedcapService.project(config, token); let linked = false; if (projectInfo && projectInfo.project_notes) { const projectNotes = projectInfo.project_notes; linked = projectNotes.indexOf(sails.config.redcap.notesHeader) !== -1; } this.ajaxOk(req, res, null, { status: true, linked: linked, project: projectInfo }); } catch (error) { this.ajaxFail(req, res, error.message, { status: false, message: error.message }); } } async link(req, res) { const brand = BrandingService.getBrand(req.session.branding); const user = req.user; this.config.brandingAndPortalUrl = BrandingService.getFullPath(req); const rdmp = req.param('rdmp'); const project = req.param('workspace'); const token = req.param('token'); sails.log.debug('Token to be linked is: ' + token); if (!project || !rdmp) { const message = 'rdmp, project are missing'; this.ajaxFail(req, res, message, { status: false, message: message }); return; } const projectID = project.project_id; const projectName = project.project_title; const projectNotes = project.project_notes; //const project_link = this.config.location; let newNotes = ''; let workspace = null; let rdmpTitle = ''; let recordMetadata = null; let config = { url: this.config.location, path: this.config.path }; if (this.config.http != null) { config = { http: this.config.http, host: this.config.host, path: this.config.path }; } const notesHeader = sails.config.redcap.notesHeader; if (projectNotes.indexOf(notesHeader) == -1) { sails.log.debug('project id: ' + projectID); sails.log.debug('project description: ' + projectNotes); let newNotesObject = { project_notes: `${projectNotes} ${notesHeader}: ${rdmp}.` }; newNotes = JSON.stringify(newNotesObject); sails.log.debug('New Project Notes: ' + newNotes); try { let recordMetadata = await RecordsService.getMeta(rdmp); if (_.isEmpty(recordMetadata)) { sails.log.error(`${this.logHeader} link() -> Failed to find RDMP: ${rdmp}`); throw new Error(`Failed to find RDMP: ${rdmp}, please contact an administrator`); } let redCapResponse = await RedcapService.addlinkinfo(config, token, newNotes); sails.log.verbose(`${this.logHeader} link() -> Redcap response:`); sails.log.verbose(redCapResponse); rdmpTitle = recordMetadata.title; const record = { rdmpOid: rdmp, rdmpTitle: rdmpTitle, redcap_id: projectID, title: projectName, location: `${this.config.location}/${this.config.redcapVersion}/index.php?pid=${projectID}`, description: this.config.description, //'RedCap Workspace', type: this.config.recordType }; //sails.log.debug(record); let workspace = await this.createRecordByType(brand, this.config.recordType, record, user); if (workspace.isSuccessful()) { const appendWsResp = await WorkspaceService.addWorkspaceToRecord(rdmp, workspace.oid); if (!appendWsResp.isSuccessful()) { sails.log.error(`${this.logHeader} link() -> Appending workspace to record failed:`); sails.log.error(appendWsResp); throw new Error(`Failed to append workspace to RDMP record`); } } else { sails.log.error(`${this.logHeader} link() -> Failed to create workspace record:`); sails.log.error(workspace); throw new Error(`Failed to add workspace record`); } this.ajaxOk(req, res, null, { status: true, message: 'workspaceRecordCreated' }); } catch (error) { sails.log.error(`${this.logHeader} link() -> Failed to link project:`); sails.log.error(error); this.ajaxFail(req, res, error.message, { status: false, message: `Failed to link project with RDMP, please contact an administrator.` }); } } else { this.ajaxFail(req, res, null, { status: false, message: `Project has already been linked to an RDMP, see '${notesHeader}' value in the 'Notes' section.`, linked: true }); } } async createRecordByType(brand, recordType, recordMetadata, user, targetStep = null) { let record = { metaMetadata: {} }; record.authorization = { view: [user.username], edit: [user.username] }; record.metaMetadata.brandId = brand.id; record.metaMetadata.createdBy = user.username; record.metaMetadata.type = recordType; record.metadata = recordMetadata; let recType = await RecordTypesService.get(brand, recordType).toPromise(); if (recType.packageType) { record.metaMetadata.packageType = recType.packageType; } if (recType.packageName) { record.metaMetadata.packageName = recType.packageName; } let wfStep = await WorkflowStepsService.getFirst(recType).toPromise(); if (targetStep) { wfStep = await WorkflowStepsService.get(recType, targetStep).toPromise(); } this.setWorkflowStepRelatedMetadata(record, wfStep); return await RecordsService.create(brand, record, recType, user); } setWorkflowStepRelatedMetadata(currentRec, nextStep) { if (!_.isEmpty(nextStep)) { sails.log.verbose('setWorkflowStepRelatedMetadata - enter'); sails.log.verbose(nextStep); currentRec.previousWorkflow = currentRec.workflow; currentRec.workflow = nextStep.config.workflow; // TODO: validate data with form fields currentRec.metaMetadata.form = nextStep.config.form; // Check for JSON-LD config if (sails.config.jsonld.addJsonLdContext) { currentRec.metadata['@context'] = sails.config.jsonld.contexts[currentRec.metaMetadata.form]; } //TODO: if this was all typed we probably don't need these sorts of initialisations if (currentRec.authorization == undefined) { currentRec.authorization = { viewRoles: [], editRoles: [], edit: [], view: [] }; } // update authorizations based on workflow... currentRec.authorization.viewRoles = nextStep.config.authorization.viewRoles; currentRec.authorization.editRoles = nextStep.config.authorization.editRoles; } } } Controllers.RedcapController = RedcapController; })(Controllers || (exports.Controllers = Controllers = {})); module.exports = new Controllers.RedcapController().exports(); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUmVkY2FwQ29udHJvbGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3R5cGVzY3JpcHQvYXBpL2NvbnRyb2xsZXJzL1JlZGNhcENvbnRyb2xsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBS0EsaUNBQStCO0FBQy9CLDBFQUFnRztBQUdoRzs7R0FFRztBQUVILHNDQUFtQztBQUVuQyxJQUFjLFdBQVcsQ0FpTnhCO0FBak5ELFdBQWMsV0FBVztJQUN2Qjs7O09BR0c7SUFDSCxNQUFhLGdCQUFpQixTQUFRLCtCQUFXLENBQUMsSUFBSSxDQUFDLFVBQVU7UUFFckQsZ0JBQWdCLEdBQVE7WUFDaEMsU0FBUztZQUNULE1BQU07U0FDUCxDQUFDO1FBR1EsTUFBTSxDQUFTO1FBQ2YsU0FBUyxHQUFHLG9CQUFvQixDQUFDO1FBRTNDO1lBQ0UsS0FBSyxFQUFFLENBQUM7WUFDUixJQUFJLElBQUksR0FBRyxJQUFJLENBQUM7WUFDaEIsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFO2dCQUNyQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksZUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDcEQsQ0FBQyxDQUFDLENBQUM7UUFFTCxDQUFDO1FBRU0sS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRztZQUMzQixJQUFJLENBQUM7Z0JBQ0gsSUFBSSxRQUFRLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDbEMsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQztnQkFDN0IsS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ3ZCLEtBQUssQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFD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