@researchdatabox/sails-hook-redbox-redcap
Version:
Redbox hook for REDCap API
204 lines • 20.8 kB
JavaScript
;
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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