diff --git a/config/index.js b/config/index.js index 567b86dd..a2bb1ec4 100644 --- a/config/index.js +++ b/config/index.js @@ -59,7 +59,8 @@ config.thickDb = config.thickDb || { }; config.maxConcurrent = config.maxConcurrent || 5; config.disableStats = config.disableStats || false; -config.statsEpad = config.statsEpad || 'https://epad-public.stanford.edu'; +config.statsEpad = + config.statsEpad || process.env.STATSEPAD || 'https://epadlite-public.stanford.edu'; config.limitStudies = process.env.LIMIT_STUDIES || config.limitStudies; config.disableDICOMSend = process.env.DISABLE_DICOM_SEND === 'true' || config.disableDICOMSend; config.unassignedProjectID = config.unassignedProjectID || 'nonassigned'; @@ -82,6 +83,13 @@ if (process.env.CORS_ORIGIN) { } config.noResume = process.env.NO_RESUME === 'true' || config.noResume || false; config.secret = process.env.SECRET || config.secret || undefined; +// mail relay example. Required to register the app +// config.notificationEmail = { host: 'smtp.gmail.com' }; +// config.notificationEmail = { port: 465 }; // ssl: 465 or 587 +// config.notificationEmail.isTls = true; // use TLS +// config.notificationEmail.auth = {}; +// config.notificationEmail.auth.user: 'example@gmail.com' ; +// config.notificationEmail.auth.pass: 'examplepass' ; config.precomputeReports = process.env.PRECOMPUTE_REPORTS ? JSON.parse(process.env.PRECOMPUTE_REPORTS) : config.precomputeReports || []; diff --git a/plugins/EpadDB.js b/plugins/EpadDB.js index 23cad939..7491bcbb 100644 --- a/plugins/EpadDB.js +++ b/plugins/EpadDB.js @@ -2772,6 +2772,7 @@ async function epaddb(fastify, options, done) { }); const onlyNameValues = []; const foldersToBind = []; + let dockeroptions = {}; for (let i = 0; i < tempPluginParams.length; i += 1) { if ( tempPluginParams[i].format === 'InputFolder' || @@ -2794,10 +2795,66 @@ async function epaddb(fastify, options, done) { onlyNameValues.push(tempPluginParams[i].default_value); } } + + if (tempPluginParams[i].paramid === 'dockeroptions') { + let tmpArray = []; + switch (tempPluginParams[i].format) { + case 'sharedram': + dockeroptions.ShmSize = tempPluginParams[i].default_value; + break; + case 'driver': + if (!dockeroptions.DeviceRequests) { + dockeroptions = { + ...dockeroptions, + DeviceRequests: [{ Driver: tempPluginParams[i].default_value }], + }; + } else { + dockeroptions.DeviceRequests[0].Driver = tempPluginParams[i].default_value; + } + break; + case 'deviceids': + // device ids need to be passed to container as array. Expect coma separated strings and convert those to an array before sending + + if (tempPluginParams[i].default_value.split(',').length >= 1) { + tmpArray = tempPluginParams[i].default_value.split(','); + } else { + tmpArray.push(tempPluginParams[i].default_value); + } + + if (!dockeroptions.DeviceRequests) { + dockeroptions = { + ...dockeroptions, + DeviceRequests: [{ DeviceIDs: tmpArray }], + }; + } else { + dockeroptions.DeviceRequests[0].DeviceIDs = tmpArray; + } + break; + case 'capabilities': + // device ids need to be passed to container as array. Expect coma separated strings and convert those to an array before sending + + if (tempPluginParams[i].default_value.split(',').length >= 1) { + tmpArray = tempPluginParams[i].default_value.split(','); + } else { + tmpArray.push(tempPluginParams[i].default_value); + } + if (!dockeroptions.DeviceRequests) { + dockeroptions = { + ...dockeroptions, + DeviceRequests: [{ Capabilities: [tmpArray] }], + }; + } else { + dockeroptions.DeviceRequests[0].Capabilities = [tmpArray]; + } + break; + default: + } + } } const returnObj = { paramsDocker: onlyNameValues, dockerFoldersToBind: foldersToBind, + dockeroptions: { HostConfig: dockeroptions }, }; return resolve(returnObj); @@ -3373,15 +3430,16 @@ async function epaddb(fastify, options, done) { fastify.nodemailer.sendMail(mailOptions, (err, info) => { if (err) { fastify.log.error(`could not send email to ${paramTo}. Error: ${err.message}`); - reject(new InternalError('Error Happened while senfing an email', err)); + reject(new InternalError('Error Happened while sending an email', err)); } else { fastify.log.info(`Email accepted for ${JSON.stringify(info.accepted)}`); resolve(info); } }); + } else { + reject(new InternalError('Mail relay settings are not found', new Error('334'))); + // Error : 334 means –> Provide SMTP authentication credentials. } - reject(new InternalError('Mail relay settings are not found', new Error('334'))); - // Error : 334 means –> Provide SMTP authentication credentials. }) ); @@ -3449,12 +3507,13 @@ async function epaddb(fastify, options, done) { ) { tempEpadStatServer = config.statsEpad; } + // if (config.statsEpad) { if (!requestSenderServerName.includes(tempEpadStatServer)) { - const resultRemoteRegister = await Axios.post(`${config.statsEpad}/register`, { + const resultRemoteRegister = await Axios.post(`${config.statsEpad}/api/register`, { headers: { 'Content-Type': 'application/json', }, - tempBody, + ...tempBody, }); fastify.log.info( @@ -3464,7 +3523,6 @@ async function epaddb(fastify, options, done) { reply.code(resultRemoteRegister.code).send(resultRemoteRegister.data); return; } - const tempName = request.body.name; const tempEmail = request.body.email; const tempOrganization = request.body.organization; @@ -3498,7 +3556,7 @@ async function epaddb(fastify, options, done) { hostname: tempHostname, email: tempEmail, emailvalidationcode: tempGeneratedEmailValidationCode, - creator: request.epadAuth.username, + creator: 'registercall', createdtime: Date.now(), emailvalidationsent: Date.now(), }); @@ -3529,7 +3587,7 @@ async function epaddb(fastify, options, done) { emailvalidationcode: tempGeneratedEmailValidationCode, updatetime: Date.now(), emailvalidationsent: Date.now(), - updated_by: request.epadAuth.username, + updated_by: 'registercall', }, { where: { diff --git a/plugins/Ontology.js b/plugins/Ontology.js index 095a3976..f0eabb1d 100644 --- a/plugins/Ontology.js +++ b/plugins/Ontology.js @@ -260,7 +260,7 @@ async function Ontology(fastify, options, done) { fastify.decorate( 'insertOntologyItemInternal', async (lexiconObj) => - // this function need to call remote ontology server if no valid ontology apikey + // this function need to call remote ontology server if valid ontology apikey new Promise(async (resolve, reject) => { let returnObj = null; try { @@ -270,7 +270,7 @@ async function Ontology(fastify, options, done) { } if (returnObj.code === 200) { try { - const nextindex = (await fastify.generateCodeValueInternal()) + 1; + // const nextindex = (await fastify.generateCodeValueInternal()) + 1; const { codemeaning: CODE_MEANING, description, @@ -284,19 +284,30 @@ async function Ontology(fastify, options, done) { const retVal = await models.lexicon.create({ CODE_MEANING, - CODE_VALUE: `99EPAD_${nextindex}`, description, SCHEMA_DESIGNATOR, SCHEMA_VERSION, referenceuid, referencename, referencetype, - indexno: nextindex, creator, createdtime: Date.now(), updatetime: Date.now(), }); + await models.lexicon.update( + { + CODE_VALUE: `99EPAD_${retVal.ID}`, + indexno: retVal.indexno, + updatetime: Date.now(), + }, + { + where: { + ID: retVal.ID, + }, + } + ); + const resultInJson = { id: retVal.ID, codevalue: retVal.CODE_VALUE, @@ -422,7 +433,7 @@ async function Ontology(fastify, options, done) { referencename, referencetype, } = request.body; - models.lexicon.update( + await models.lexicon.update( { CODE_MEANING, CODE_VALUE, @@ -458,7 +469,7 @@ async function Ontology(fastify, options, done) { try { await fastify.validateApiKeyInternal(request); const { codevalue: CODE_VALUE } = request.params; - models.lexicon.destroy({ + await models.lexicon.destroy({ where: { CODE_VALUE, }, diff --git a/plugins/Other.js b/plugins/Other.js index 5a83b769..17142721 100644 --- a/plugins/Other.js +++ b/plugins/Other.js @@ -1406,6 +1406,7 @@ async function other(fastify) { users: 'user', worklists: 'worklist', ontology: 'ontology', + register: 'register', }; if (urlParts[urlParts.length - 1] === 'download') reqInfo.methodText = 'DOWNLOAD'; if (levels[urlParts[urlParts.length - 1]]) { @@ -1687,7 +1688,8 @@ async function other(fastify) { !req.raw.url.startsWith(`${fastify.getPrefixForRoute()}/epad/statistics`) && // disabling auth for put is dangerous !req.raw.url.startsWith(`${fastify.getPrefixForRoute()}/download`) && !req.raw.url.startsWith(`${fastify.getPrefixForRoute()}/ontology`) && - !req.raw.url.startsWith(`${fastify.getPrefixForRoute()}/decrypt?`) && + !req.raw.url.startsWith(`${fastify.getPrefixForRoute()}/register`) && + !req.raw.url.startsWith(`${fastify.getPrefixForRoute()}/decrypt?`) & req.method !== 'OPTIONS' ) { // if auth has been given in config, verify authentication @@ -1927,6 +1929,7 @@ async function other(fastify) { break; case 'POST': if ( + reqInfo.level !== 'register' && !fastify.hasCreatePermission(request, reqInfo.level) && !( reqInfo.level === 'worklist' && diff --git a/utils/Docker.js b/utils/Docker.js index a19cf86a..4cdd0499 100644 --- a/utils/Docker.js +++ b/utils/Docker.js @@ -130,6 +130,8 @@ class DockerService { StdinOnce: false, HostConfig: { Binds: dockerFoldersToBind, + DeviceRequests: [...params.dockeroptions.HostConfig.DeviceRequests], + ShmSize: parseInt(params.dockeroptions.HostConfig.ShmSize, 10) || 64000000, }, }) // eslint-disable-next-line prefer-arrow-callback