diff --git a/.gitignore b/.gitignore deleted file mode 100644 index fed401d5c039459aebbc72931ae9d84f5099a616..0000000000000000000000000000000000000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -package-lock.json -node_modules/ \ No newline at end of file diff --git a/src/.eslintrc.js b/src/.eslintrc.js new file mode 100644 index 0000000000000000000000000000000000000000..d85cd213a1350e272672436090dbe0b5ccd9b445 --- /dev/null +++ b/src/.eslintrc.js @@ -0,0 +1,15 @@ +module.exports = { + env: { + browser: true, + es2020: true + }, + extends: [ + 'standard' + ], + parserOptions: { + ecmaVersion: 11, + sourceType: 'module' + }, + rules: { + } +} diff --git a/src/.eslintrc.json b/src/.eslintrc.json new file mode 100644 index 0000000000000000000000000000000000000000..71ac1f718ef99b1af01f8e470a7fd13cfdaa5eb2 --- /dev/null +++ b/src/.eslintrc.json @@ -0,0 +1,9 @@ +{ + "extends": "strongloop", + "rules": { + "indent": [2, "tab"], + "max-len": [2, 120, 8], + "no-undef": "off" + }, + "ignorePatterns": [ "libs/**" ] +} diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c7895cda396d5bf325fac74f59cc99e1662563c1 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,3 @@ +package-lock.json +node_modules/ +libs/ \ No newline at end of file diff --git a/src/app.js b/src/app.js index e1d0324bf411e3e008f313430ae12546d2e01135..275426fa9bd715faeab3adfed19f025b1eb11c1e 100644 --- a/src/app.js +++ b/src/app.js @@ -1,38 +1,43 @@ -const createError = require('http-errors') - express = require('express') - path = require('path') - http = require('http') - indexRouter = require('./routes/index') - programsRouter = require('./routes/programRoutes') - cookieParser = require('cookie-parser'), - logger = require('morgan'), - bodyParser = require('body-parser'), - envVariables = require('./envVariables'), - port = envVariables.port; - const telemetryService = require('./service/telemetryService'); +const express = require('express') +const cookieParser = require('cookie-parser') +const logger = require('morgan') +const bodyParser = require('body-parser') +const envVariables = require('./envVariables') +const port = envVariables.port +const telemetryService = require('./service/telemetryService') +const helmet = require('helmet') - const createAppServer = () => { - const app = express(); +const createAppServer = () => { + const app = express() + app.use(helmet()) + app.use((req, res, next) => { + res.header('Access-Control-Allow-Origin', '*') + res.header( + 'Access-Control-Allow-Methods', + 'GET,PUT,POST,PATCH,DELETE,OPTIONS' + ) + res.header( + 'Access-Control-Allow-Headers', + 'Content-Type, Authorization,' + + 'cid, user-id, x-auth, Cache-Control, X-Requested-With, datatype, *' + ) + if (req.method === 'OPTIONS') res.sendStatus(200) + else next() + }) + app.use(bodyParser.json({ limit: '1mb' })) + app.use(logger('dev')) + app.use(express.json()) + app.use(bodyParser.urlencoded({ extended: false })) + require('./routes/programRoutes')(app) + app.use(cookieParser()) + module.exports = app + return app +} - app.use((req, res, next) => { - res.header('Access-Control-Allow-Origin', '*') - res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,PATCH,DELETE,OPTIONS') - res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization,' + 'cid, user-id, x-auth, Cache-Control, X-Requested-With, datatype, *') - if (req.method === 'OPTIONS') res.sendStatus(200) - else next() - }) - app.use(bodyParser.json({ limit: '1mb' })); - app.use(logger('dev')); - app.use(express.json()); - app.use(bodyParser.urlencoded({ extended: false })); - require('./routes/programRoutes')(app) - app.use(cookieParser()); - module.exports = app; - return app; - } - -const app = createAppServer(); +const app = createAppServer() app.listen(port, () => { - console.log(`program-service is running in test env on port ${port} with ${process.pid} pid`); - telemetryService.initializeTelemetryService(); -}); + console.log( + `program-service is running in test env on port ${port} with ${process.pid} pid` + ) + telemetryService.initializeTelemetryService() +}) diff --git a/src/envVariables.js b/src/envVariables.js index e29158d22f55a44d8ce31db4f96c4f8c5b74c3bc..cecf7a15c8910805c7d6b524acde52df6bc853b0 100644 --- a/src/envVariables.js +++ b/src/envVariables.js @@ -1,34 +1,32 @@ - const envVariables = { - baseURL: process.env.dock_base_url || 'https://dock.sunbirded.org', - SUNBIRD_URL: process.env.sunbird_base_url || 'https://dev.sunbirded.org', - SUNBIRD_PORTAL_API_AUTH_TOKEN: process.env.sunbird_api_auth_token, - DOCK_CHANNEL: process.env.dock_channel || 'sunbird', - port: process.env.sunbird_program_port || 6000, - CACHE_TTL: process.env.dock_cache_ttl || 900, - level: process.env.sunbird_service_log_level || 'info', - LEARNING_SERVICE_URL: process.env.learning_service_url, - OPENSABER_SERVICE_URL: process.env.opensaber_service_url, - SUNBIRD_KAFKA_HOST: process.env.sunbird_kafka_host, - DOCK_REDIS_HOST: process.env.dock_redis_host, - DOCK_REDIS_PORT: process.env.dock_redis_port || 6379, - SUNBIRD_AUTO_CREATION_TOPIC: process.env.sunbird_auto_creation_topic, - config: { - user: process.env.sunbird_program_db_user || "postgres", - host: process.env.sunbird_program_db_host || "localhost", - database: process.env.sunbird_program_db_name || 'sunbird_programs', - password: process.env.sunbird_program_db_password || 'password', - port: process.env.sunbird_program_db_port || 5432, - dialect: process.env.sunbird_program_db_dialect || "postgres", - pool: { - max: process.env.sunbird_program_db_pool || 100 - } - }, - telemetryConfig: { - host: process.env.telemetry_service_host, - endpoint: process.env.telemetry_service_endpoint, - method: 'POST' + baseURL: process.env.dock_base_url || 'https://dock.sunbirded.org', + SUNBIRD_URL: process.env.sunbird_base_url || 'https://dev.sunbirded.org', + SUNBIRD_PORTAL_API_AUTH_TOKEN: process.env.sunbird_api_auth_token, + DOCK_CHANNEL: process.env.dock_channel || 'sunbird', + port: process.env.sunbird_program_port || 6000, + CACHE_TTL: process.env.dock_cache_ttl || 900, + level: process.env.sunbird_service_log_level || 'info', + LEARNING_SERVICE_URL: process.env.learning_service_url, + OPENSABER_SERVICE_URL: process.env.opensaber_service_url, + SUNBIRD_KAFKA_HOST: process.env.sunbird_kafka_host, + DOCK_REDIS_HOST: process.env.dock_redis_host, + DOCK_REDIS_PORT: process.env.dock_redis_port || 6379, + SUNBIRD_AUTO_CREATION_TOPIC: process.env.sunbird_auto_creation_topic, + config: { + user: process.env.sunbird_program_db_user || 'postgres', + host: process.env.sunbird_program_db_host || 'localhost', + database: process.env.sunbird_program_db_name || 'sunbird_programs', + password: process.env.sunbird_program_db_password || 'password', + port: process.env.sunbird_program_db_port || 5432, + dialect: process.env.sunbird_program_db_dialect || 'postgres', + pool: { + max: process.env.sunbird_program_db_pool || 100 } + }, + telemetryConfig: { + host: process.env.telemetry_service_host, + endpoint: process.env.telemetry_service_endpoint, + method: 'POST' + } } -module.exports = envVariables; - +module.exports = envVariables diff --git a/src/helpers/helperService.js b/src/helpers/helperService.js index 0c76a2eb5134072ee9b578def3e1a8db851ab0ad..8e4c7dd4741cc4cd18bcbb4a01d2c09b4c462692 100644 --- a/src/helpers/helperService.js +++ b/src/helpers/helperService.js @@ -1,11 +1,18 @@ +const telemetryService = require('../service/telemetryService') -const telemetryService = require('../service/telemetryService'); +function manageModelHooks (db) { + db.program.addHook('beforeUpdate', (instance) => { + telemetryService.generateAuditEvent(instance, db.program, 'update') + }) + db.program.addHook('afterCreate', (instance) => { + telemetryService.generateAuditEvent(instance, db.program, 'create') + }) + db.nomination.addHook('beforeUpdate', (instance) => { + telemetryService.generateAuditEvent(instance, db.nomination, 'update') + }) + db.nomination.addHook('afterCreate', (instance) => { + telemetryService.generateAuditEvent(instance, db.nomination, 'create') + }) +} -function manageModelHooks(db) { - db.program.addHook('beforeUpdate', (instance) => {telemetryService.generateAuditEvent(instance, db.program, 'update')}); - db.program.addHook('afterCreate', (instance) => {telemetryService.generateAuditEvent(instance, db.program, 'create')}); - db.nomination.addHook('beforeUpdate', (instance) => {telemetryService.generateAuditEvent(instance, db.nomination, 'update')}); - db.nomination.addHook('afterCreate', (instance) => {telemetryService.generateAuditEvent(instance, db.nomination, 'create')}); - } - -module.exports.AttachModelHooks = manageModelHooks; \ No newline at end of file +module.exports.AttachModelHooks = manageModelHooks diff --git a/src/helpers/kafkaUtil.js b/src/helpers/kafkaUtil.js index 68d422bd4c55b41b1c71824a524f49eb4832f430..0116926bb8d99ef9e85aeaead62e17ca142dc8e4 100644 --- a/src/helpers/kafkaUtil.js +++ b/src/helpers/kafkaUtil.js @@ -1,7 +1,7 @@ const kafka = require('kafka-node') const _ = require('lodash') var logger = require('sb_logger_util_v2') -const envVariables = require("../envVariables"); +const envVariables = require('../envVariables') const client = new kafka.KafkaClient({ kafkaHost: envVariables.SUNBIRD_KAFKA_HOST, @@ -11,19 +11,22 @@ const client = new kafka.KafkaClient({ const producer = new kafka.HighLevelProducer(client) producer.on('ready', function () { console.log('Kafka Producer is connected and ready.') - logger.info({msg: 'Kafka Producer is connected and ready.'}) + logger.info({ msg: 'Kafka Producer is connected and ready.' }) }) // For this demo we just log producer errors to the console. producer.on('error', function (error) { - logger.error({msg: 'Error from Kafka producer', error}) + logger.error({ msg: 'Error from Kafka producer', error }) console.error(error) }) const KafkaService = { - sendRecord: (data, callback = () => { }) => { + sendRecord: (data, callback = () => {}) => { if (_.isEmpty(data)) { - logger.error({msg: 'Data must be provided to send Record', additionalInfo: {data}}) + logger.error({ + msg: 'Data must be provided to send Record', + additionalInfo: { data } + }) return callback(new Error('Event Data must be provided.')) } @@ -34,7 +37,7 @@ const KafkaService = { messages: JSON.stringify(data) } ] - logger.info({msg: 'Kafka record', additionalInfo: {record}}) + logger.info({ msg: 'Kafka record', additionalInfo: { record } }) // Send record to Kafka and log result/error producer.send(record, callback) } diff --git a/src/helpers/programHelper.js b/src/helpers/programHelper.js index a949382158ee0dc685a8b912f8c28074f131dba3..1a64e5a543ddc31366e18044021d639de6829789 100644 --- a/src/helpers/programHelper.js +++ b/src/helpers/programHelper.js @@ -1,13 +1,13 @@ -const { forkJoin } = require("rxjs"); -const _ = require("lodash"); -const envVariables = require("../envVariables"); -const axios = require("axios"); -const dateFormat = require('dateformat'); -const model = require('../models'); -const Sequelize = require('sequelize'); +const { forkJoin } = require('rxjs') +const _ = require('lodash') +const envVariables = require('../envVariables') +const axios = require('axios') +const dateFormat = require('dateformat') +const model = require('../models') +const Sequelize = require('sequelize') class ProgramServiceHelper { - searchContent(programId, sampleContentCheck, reqHeaders) { + searchContent (programId, sampleContentCheck, reqHeaders) { const url = `${envVariables.baseURL}/api/composite/v1/search` const option = { url, @@ -18,80 +18,91 @@ class ProgramServiceHelper { filters: { objectType: 'content', programId: programId, - mimeType: {'!=': 'application/vnd.ekstep.content-collection'}, - contentType: {'!=': 'Asset'}, + mimeType: { '!=': 'application/vnd.ekstep.content-collection' }, + contentType: { '!=': 'Asset' }, ...(sampleContentCheck && { - 'sampleContent': true, - 'status': ['Draft', 'Review'] + sampleContent: true, + status: ['Draft', 'Review'] }) }, fields: [ - 'name', - 'identifier', - 'programId', - 'mimeType', - 'status', - 'sampleContent', - 'createdBy', - 'organisationId', - 'collectionId', - 'prevStatus', - 'contentType' + 'name', + 'identifier', + 'programId', + 'mimeType', + 'status', + 'sampleContent', + 'createdBy', + 'organisationId', + 'collectionId', + 'prevStatus', + 'contentType' ], limit: 10000 } } - }; - return axios(option); + } + return axios(option) } - - setNominationSampleCounts(contentResult) { - let nominationSampleCounts = {}; - let orgSampleUploads = _.filter(contentResult, contribution => !_.isEmpty(contribution.organisationId) && contribution.sampleContent); - orgSampleUploads = _.groupBy(orgSampleUploads, 'organisationId'); + setNominationSampleCounts (contentResult) { + const nominationSampleCounts = {} + let orgSampleUploads = _.filter( + contentResult, + (contribution) => + !_.isEmpty(contribution.organisationId) && contribution.sampleContent + ) + orgSampleUploads = _.groupBy(orgSampleUploads, 'organisationId') _.forEach(orgSampleUploads, (temp, index) => { - nominationSampleCounts[index] = temp.length; - }); + nominationSampleCounts[index] = temp.length + }) // tslint:disable-next-line: max-line-length - let individualSampleUploads = _.filter(contentResult, contribution => _.isEmpty(contribution.organisationId) && contribution.sampleContent); - individualSampleUploads = _.groupBy(individualSampleUploads, 'createdBy'); + let individualSampleUploads = _.filter( + contentResult, + (contribution) => + _.isEmpty(contribution.organisationId) && contribution.sampleContent + ) + individualSampleUploads = _.groupBy(individualSampleUploads, 'createdBy') _.forEach(individualSampleUploads, (temp, index) => { - nominationSampleCounts[index] = temp.length; - }); + nominationSampleCounts[index] = temp.length + }) - return nominationSampleCounts; + return nominationSampleCounts } - assignSampleCounts(nominations, nominationSampleCounts, programName) { - const newNominations = _.map(nominations, n => { - n.programName = programName.trim(); - n.samples = this.getNominationSampleCounts(n, nominationSampleCounts); - return n; - }); - return newNominations; + assignSampleCounts (nominations, nominationSampleCounts, programName) { + const newNominations = _.map(nominations, (n) => { + n.programName = programName.trim() + n.samples = this.getNominationSampleCounts(n, nominationSampleCounts) + return n + }) + return newNominations } - - getNominationSampleCounts(nomination, nominationSampleCounts) { + getNominationSampleCounts (nomination, nominationSampleCounts) { // tslint:disable-next-line:max-line-length - return (nomination.organisation_id) ? nominationSampleCounts[nomination.organisation_id] || 0 : nominationSampleCounts[nomination.user_id] || 0; + return nomination.organisation_id + ? nominationSampleCounts[nomination.organisation_id] || 0 + : nominationSampleCounts[nomination.user_id] || 0 } - downloadNominationList(nominations) { + downloadNominationList (nominations) { const tableData = _.map(_.cloneDeep(nominations), (nomination) => { - const isOrg = !_.isEmpty(nomination.organisation_id); - let name = ''; + const isOrg = !_.isEmpty(nomination.organisation_id) + let name = '' if (isOrg && !_.isEmpty(nomination.orgData)) { - name = nomination.orgData.name; + name = nomination.orgData.name } else if (!_.isEmpty(nomination.userData)) { - name = `${nomination.userData.firstName} ${nomination.userData.lastName || ''}`; + name = `${nomination.userData.firstName} ${ + nomination.userData.lastName || '' + }` } - nomination.createdon = dateFormat(nomination.createdon, 'mmmm d, yyyy'); - nomination.name = name; - nomination.textbooks = nomination.collection_ids && nomination.collection_ids.length; - nomination.type = isOrg ? 'Organisation' : 'Individual'; + nomination.createdon = dateFormat(nomination.createdon, 'mmmm d, yyyy') + nomination.name = name + nomination.textbooks = + nomination.collection_ids && nomination.collection_ids.length + nomination.type = isOrg ? 'Organisation' : 'Individual' return { programName: nomination.programName, name: nomination.name, @@ -99,336 +110,517 @@ class ProgramServiceHelper { textbooks: nomination.textbooks, sample: nomination.samples, createdon: nomination.createdon, - status: nomination.status, - }; - }); + status: nomination.status + } + }) - return tableData; + return tableData } - searchWithProgramId(queryFilter, req) { + searchWithProgramId (queryFilter, req) { const headers = { - 'content-type': 'application/json', - }; + 'content-type': 'application/json' + } const option = { url: `${envVariables.baseURL}/api/composite/v1/search`, method: 'post', - headers: {...req.headers, ...headers}, + headers: { ...req.headers, ...headers }, data: { request: queryFilter } - }; - return axios(option); + } + return axios(option) } - getCollectionWithProgramId(program_id, req) { + getCollectionWithProgramId (programId, req) { const queryFilter = { - filters: { - programId: program_id, - objectType: 'content', - status: ['Draft'], - contentType: 'Textbook' - }, - fields: ['name', 'medium', 'gradeLevel', 'subject', 'chapterCount', 'acceptedContents', 'rejectedContents'], - limit: 1000 - }; - return this.searchWithProgramId(queryFilter, req); -} - -getSampleContentWithProgramId(program_id, req) { - const queryFilter = { - filters: { - programId: program_id, - objectType: 'content', - status: ['Review', 'Draft'], - sampleContent: true - }, - facets: [ - 'sampleContent', 'collectionId', 'status' + filters: { + programId: programId, + objectType: 'content', + status: ['Draft'], + contentType: 'Textbook' + }, + fields: [ + 'name', + 'medium', + 'gradeLevel', + 'subject', + 'chapterCount', + 'acceptedContents', + 'rejectedContents' ], + limit: 1000 + } + return this.searchWithProgramId(queryFilter, req) + } + + getSampleContentWithProgramId (programId, req) { + const queryFilter = { + filters: { + programId: programId, + objectType: 'content', + status: ['Review', 'Draft'], + sampleContent: true + }, + facets: ['sampleContent', 'collectionId', 'status'], limit: 0 - }; - return this.searchWithProgramId(queryFilter, req); -} + } + return this.searchWithProgramId(queryFilter, req) + } -getContributionWithProgramId(program_id, req) { - const queryFilter = { - filters: { - programId: program_id, - objectType: 'content', - status: ['Review', 'Draft', 'Live'], - contentType: { '!=': 'Asset' }, - mimeType: { '!=': 'application/vnd.ekstep.content-collection' } - }, - not_exists: ['sampleContent'], - aggregations: [ - { - "l1": "collectionId", - "l2": "status" - } + getContributionWithProgramId (programId, req) { + const queryFilter = { + filters: { + programId: programId, + objectType: 'content', + status: ['Review', 'Draft', 'Live'], + contentType: { '!=': 'Asset' }, + mimeType: { '!=': 'application/vnd.ekstep.content-collection' } + }, + not_exists: ['sampleContent'], + aggregations: [ + { + l1: 'collectionId', + l2: 'status' + } ], limit: 0 - }; - return this.searchWithProgramId(queryFilter, req); -} + } + return this.searchWithProgramId(queryFilter, req) + } - getNominationWithProgramId(programId) { - const facets = ['collection_ids', 'status']; + getNominationWithProgramId (programId) { + const facets = ['collection_ids', 'status'] const promise = model.nomination.findAll({ where: { program_id: programId }, - attributes: [...facets, [Sequelize.fn('count', Sequelize.col(facets[0])), 'count']], + attributes: [ + ...facets, + [Sequelize.fn('count', Sequelize.col(facets[0])), 'count'] + ], group: [...facets] }) - return promise; + return promise } - handleMultiProgramDetails(resGroup) { - const multiProgramDetails = _.map(resGroup, (resData) => { - try { - return this.prepareTableData(resData); - } catch(err) { - throw err - } - }); - return multiProgramDetails; + handleMultiProgramDetails (resGroup) { + const multiProgramDetails = _.map(resGroup, (resData) => { + // eslint-disable-next-line no-useless-catch + try { + return this.prepareTableData(resData) + } catch (err) { + throw err + } + }) + return multiProgramDetails } prepareTableData (resData) { try { - const collectionList = resData[0].data.result && resData[0].data.result.content || [], - sampleContentResponse = resData[1].data.result && resData[1].data.result.facets || [], - contributionResponse = resData[2].data.result && resData[2].data.result.aggregations || [], - nominationResponse = _.isArray(resData[3]) && resData[3].length? _.map(resData[3], obj => obj.dataValues) : []; - let tableData = []; - if (collectionList.length) { + // eslint-disable-next-line no-mixed-operators + const collectionList = + (resData[0].data.result && resData[0].data.result.content) || [] + // eslint-disable-next-line no-mixed-operators + const sampleContentResponse = + (resData[1].data.result && resData[1].data.result.facets) || [] + // eslint-disable-next-line no-mixed-operators + const contributionResponse = + (resData[2].data.result && resData[2].data.result.aggregations) || [] + const nominationResponse = + _.isArray(resData[3]) && resData[3].length + ? _.map(resData[3], (obj) => obj.dataValues) + : [] + let tableData = [] + if (collectionList.length) { tableData = _.map(collectionList, (collection) => { - const result = {}; - // sequence of columns in tableData - result['Textbook Name'] = collection.name; - result['Medium'] = collection.medium || '--'; - result['Class'] = collection.gradeLevel && collection.gradeLevel.length ? collection.gradeLevel.join(', ') : ''; - result['Subject'] = collection.subject || '--'; - result['Number of Chapters'] = collection.chapterCount || '--'; - result['Nominations Received'] = 0; - result['Samples Received'] = 0; - result['Nominations Accepted'] = 0; - result['Contributions Received'] = 0; - result['Contributions Accepted'] = collection.acceptedContents ? collection.acceptedContents.length : 0; - result['Contributions Rejected'] = collection.rejectedContents ? collection.rejectedContents.length : 0; - result['Contributions Pending'] = 0; + const result = {} + // sequence of columns in tableData + result['Textbook Name'] = collection.name + result.Medium = collection.medium || '--' + result.Class = + collection.gradeLevel && collection.gradeLevel.length + ? collection.gradeLevel.join(', ') + : '' + result.Subject = collection.subject || '--' + result['Number of Chapters'] = collection.chapterCount || '--' + result['Nominations Received'] = 0 + result['Samples Received'] = 0 + result['Nominations Accepted'] = 0 + result['Contributions Received'] = 0 + result['Contributions Accepted'] = collection.acceptedContents + ? collection.acceptedContents.length + : 0 + result['Contributions Rejected'] = collection.rejectedContents + ? collection.rejectedContents.length + : 0 + result['Contributions Pending'] = 0 - // count of sample contents - if (sampleContentResponse.length) { - const facetObj = _.find(sampleContentResponse, {name: 'collectionId'}); - if (facetObj && facetObj.values.length && - _.find(facetObj.values, {name: collection.identifier})) { - result['Samples Received'] = _.find(facetObj.values, {name: collection.identifier}).count; + // count of sample contents + if (sampleContentResponse.length) { + const facetObj = _.find(sampleContentResponse, { + name: 'collectionId' + }) + if ( + facetObj && + facetObj.values.length && + _.find(facetObj.values, { name: collection.identifier }) + ) { + result['Samples Received'] = _.find(facetObj.values, { + name: collection.identifier + }).count + } + } + // count of contribution + if ( + contributionResponse.length && + contributionResponse[0].name === 'collectionId' && + contributionResponse[0].values.length + ) { + const statusCount = _.find(contributionResponse[0].values, { + name: collection.identifier + }) + if ( + statusCount && + statusCount.aggregations && + statusCount.aggregations.length + ) { + _.forEach(statusCount.aggregations[0].values, (obj) => { + if (obj.name === 'live') { + result['Contributions Received'] = + result['Contributions Received'] + obj.count + // tslint:disable-next-line:max-line-length + result['Contributions Pending'] = + result['Contributions Received'] - + (result['Contributions Rejected'] + + result['Contributions Accepted']) + } + }) + } } - } - // count of contribution - if (contributionResponse.length && contributionResponse[0].name === 'collectionId' - && contributionResponse[0].values.length) { - const statusCount = _.find(contributionResponse[0].values, {name: collection.identifier}); - if (statusCount && statusCount.aggregations && statusCount.aggregations.length) { - _.forEach(statusCount.aggregations[0].values, (obj) => { - if (obj.name === 'live') { - result['Contributions Received'] = result['Contributions Received'] + obj.count; - // tslint:disable-next-line:max-line-length - result['Contributions Pending'] = result['Contributions Received'] - (result['Contributions Rejected'] + result['Contributions Accepted']); - } - }); - } - } - // count of nomination - if (nominationResponse.length) { - _.forEach(nominationResponse, (obj) => { - if (obj.collection_ids && _.includes(obj.collection_ids, collection.identifier) ) { - if (obj.status === 'Approved') { - result['Nominations Accepted'] = result['Nominations Accepted'] + Number(obj.count); - } else if (obj.status !== 'Initiated') { - result['Nominations Received'] = result['Nominations Received'] + Number(obj.count); + // count of nomination + if (nominationResponse.length) { + _.forEach(nominationResponse, (obj) => { + if ( + obj.collection_ids && + _.includes(obj.collection_ids, collection.identifier) + ) { + if (obj.status === 'Approved') { + result['Nominations Accepted'] = + result['Nominations Accepted'] + Number(obj.count) + } else if (obj.status !== 'Initiated') { + result['Nominations Received'] = + result['Nominations Received'] + Number(obj.count) + } } - } - }); - result['Nominations Received'] = result['Nominations Accepted'] + result['Nominations Received']; - } - return result; - }); + }) + result['Nominations Received'] = + result['Nominations Accepted'] + result['Nominations Received'] + } + return result + }) + } + return tableData + } catch (err) { + // eslint-disable-next-line no-throw-literal + throw 'error in preparing CSV data' } - return tableData; - } catch (err) { - throw 'error in preparing CSV data' - } } - getProgramDetails(program_id) { + getProgramDetails (programId) { return model.program.findOne({ where: { - program_id: program_id + program_id: programId } }) } - hierarchyRequest(req, collectionId) { + hierarchyRequest (req, collectionId) { const option = { url: `${envVariables.baseURL}/action/content/v3/hierarchy/${collectionId}?mode=edit`, method: 'get', - headers: {...req.headers} - }; - return axios(option); + headers: { ...req.headers } + } + return axios(option) } - getCollectionHierarchy(req, program_id) { + getCollectionHierarchy (req, programId) { return new Promise((resolve, reject) => { - this.getCollectionWithProgramId(program_id, req).then((res_collection) => { - const collectionArr = res_collection.data && res_collection.data.result && res_collection.data.result.content || []; - forkJoin(..._.map(collectionArr, collection => this.hierarchyRequest(req, collection.identifier))).subscribe(data => { - try { - const hierarchyArr = _.compact(_.map(data, obj => obj.data.result && obj.data.result.content)); - const contentCount = this.approvedContentCount(hierarchyArr, program_id); - resolve(contentCount); - } catch (err) { - reject('programServiceException: error in counting the approved contents'); - } - }, err => { - reject('programServiceException: error in fetching collections-hierarchy'); - }); - }).catch(err => { - reject('programServiceException: error in fetching collections against programID'); - }); - }); + this.getCollectionWithProgramId(programId, req) + .then((resCollection) => { + // eslint-disable-next-line no-mixed-operators + const collectionArr = + (resCollection.data && + resCollection.data.result && + resCollection.data.result.content) || + [] + forkJoin( + ..._.map(collectionArr, (collection) => + this.hierarchyRequest(req, collection.identifier) + ) + ).subscribe( + (data) => { + try { + const hierarchyArr = _.compact( + _.map( + data, + (obj) => obj.data.result && obj.data.result.content + ) + ) + const contentCount = this.approvedContentCount( + hierarchyArr, + programId + ) + resolve(contentCount) + } catch (err) { + // eslint-disable-next-line prefer-promise-reject-errors + reject( + 'programServiceException: error in counting the approved contents' + ) + } + // eslint-disable-next-line handle-callback-err + }, + // eslint-disable-next-line handle-callback-err + (err) => { + // eslint-disable-next-line prefer-promise-reject-errors + reject( + 'programServiceException: error in fetching collections-hierarchy' + ) + } + ) + // eslint-disable-next-line handle-callback-err + }) + // eslint-disable-next-line handle-callback-err + .catch((err) => { + // eslint-disable-next-line prefer-promise-reject-errors + reject( + 'programServiceException: error in fetching collections against programID' + ) + }) + }) } - approvedContentCount(collectionHierarchy, program_id) { - const collectionWithApprovedContent = _.map(collectionHierarchy, collection => { - this.acceptedContents = _.uniq(collection.acceptedContents) || []; - this.collectionData = {}; - this.collectionLevelCount(collection); - return this.collectionData - }); - return {program_id: program_id, collection: collectionWithApprovedContent}; + approvedContentCount (collectionHierarchy, programId) { + const collectionWithApprovedContent = _.map( + collectionHierarchy, + (collection) => { + this.acceptedContents = _.uniq(collection.acceptedContents) || [] + this.collectionData = {} + this.collectionLevelCount(collection) + return this.collectionData + } + ) + return { program_id: programId, collection: collectionWithApprovedContent } } - collectionLevelCount(data) { - const self = this; + collectionLevelCount (data) { + const self = this if (data.contentType === 'TextBook') { - this.collectionData['name'] = data.name; - this.collectionData['identifier'] = data.identifier; - this.collectionData['grade'] = _.isArray(data.gradeLevel) ? data.gradeLevel.join(", ") : data.gradeLevel || ''; - this.collectionData['medium'] = _.isArray(data.medium) ? data.medium.join(", ") : data.medium || ''; - this.collectionData['subject'] = _.isArray(data.subject) ? data.subject.join(", ") : data.subject || ''; - this.collectionData['count'] = this.acceptedContents.length; - this.collectionData['chapter'] = []; - this.recursive = true; + this.collectionData.name = data.name + this.collectionData.identifier = data.identifier + this.collectionData.grade = _.isArray(data.gradeLevel) + ? data.gradeLevel.join(', ') + : data.gradeLevel || '' + this.collectionData.medium = _.isArray(data.medium) + ? data.medium.join(', ') + : data.medium || '' + this.collectionData.subject = _.isArray(data.subject) + ? data.subject.join(', ') + : data.subject || '' + this.collectionData.count = this.acceptedContents.length + this.collectionData.chapter = [] + this.recursive = true } else if (data.contentType === 'TextBookUnit') { - if (data.parent === this.collectionData['identifier']) { + if (data.parent === this.collectionData.identifier) { const chapterObj = { name: data.name, identifier: data.identifier, count: 0 } - this.contentData = []; - this.chapterLevelCount(data); - chapterObj['contentTypes'] = _.map(_.groupBy(this.contentData, 'name'), (val, key) => { - chapterObj['count'] = chapterObj['count'] + val.length; - return {name: key, count: val.length} - }); - this.collectionData['chapter'].push(chapterObj); + this.contentData = [] + this.chapterLevelCount(data) + chapterObj.contentTypes = _.map( + _.groupBy(this.contentData, 'name'), + (val, key) => { + chapterObj.count = chapterObj.count + val.length + return { name: key, count: val.length } + } + ) + this.collectionData.chapter.push(chapterObj) } } if (data.children && this.recursive) { - this.recursive = false; - _.forEach(data.children, child => self.collectionLevelCount(child)); + this.recursive = false + _.forEach(data.children, (child) => self.collectionLevelCount(child)) } } - chapterLevelCount(object) { - const self = this; - if (object.contentType !== 'TextBook' && object.contentType !== 'TextBookUnit' && - _.includes(this.acceptedContents, object.identifier)) { - this.contentData.push({name: object.contentType}); + chapterLevelCount (object) { + const self = this + if ( + object.contentType !== 'TextBook' && + object.contentType !== 'TextBookUnit' && + _.includes(this.acceptedContents, object.identifier) + ) { + this.contentData.push({ name: object.contentType }) } if (object.children) { - _.forEach(object.children, child => self.chapterLevelCount(child)); + _.forEach(object.children, (child) => self.chapterLevelCount(child)) } } - textbookLevelContentMetrics(collectedData) { + textbookLevelContentMetrics (collectedData) { return new Promise((resolve, reject) => { - forkJoin(..._.map(collectedData, data => this.getProgramDetails(data.program_id))).subscribe(details => { - try { - const contentTypes = details.length ? _.uniq(_.compact(..._.map(details, model => model && model.dataValues.content_types))) : []; - const overalData = _.map(collectedData, data => { - if (data.collection && data.collection.length) { - const tableObj = _.map(data.collection, (collection) => { - const final = {}; - final['Medium'] = collection.medium; - final['Grade'] = collection.grade; - final['Subject'] = collection.subject; - final['Textbook Name'] = collection.name; - final['Total Number of Chapters'] = collection.chapter ? collection.chapter.length : 0; - final['Chapters with atleast one approved in each contentType'] = contentTypes.length ? _.filter(collection.chapter, unit => unit.contentTypes.length === contentTypes.length).length : 0; - final['Chapters with atleast one approved'] = _.filter(collection.chapter, unit => unit.contentTypes.length).length; - final['Total number of Approved Contents'] = collection.count || 0; - _.forEach(contentTypes, type => final[type] = 0); - const contentTypeObj = _.groupBy(_.flattenDeep(_.map(collection.chapter, obj => obj.contentTypes)), 'name'); - _.map(contentTypeObj, (val, key) => _.forEach(val, v => final[key] = (final[key] || 0) + v.count)); - return final; - }); - return tableObj; - } else { - return {} + forkJoin( + ..._.map(collectedData, (data) => + this.getProgramDetails(data.program_id) + ) + ).subscribe( + (details) => { + try { + const contentTypes = details.length + ? _.uniq( + _.compact( + ..._.map( + details, + (model) => model && model.dataValues.content_types + ) + ) + ) + : [] + const overalData = _.map(collectedData, (data) => { + if (data.collection && data.collection.length) { + const tableObj = _.map(data.collection, (collection) => { + const final = {} + final.Medium = collection.medium + final.Grade = collection.grade + final.Subject = collection.subject + final['Textbook Name'] = collection.name + final['Total Number of Chapters'] = collection.chapter + ? collection.chapter.length + : 0 + final[ + 'Chapters with atleast one approved in each contentType' + ] = contentTypes.length + ? _.filter( + collection.chapter, + (unit) => + unit.contentTypes.length === contentTypes.length + ).length + : 0 + final['Chapters with atleast one approved'] = _.filter( + collection.chapter, + (unit) => unit.contentTypes.length + ).length + final['Total number of Approved Contents'] = + collection.count || 0 + // eslint-disable-next-line no-return-assign + _.forEach(contentTypes, (type) => (final[type] = 0)) + const contentTypeObj = _.groupBy( + _.flattenDeep( + _.map(collection.chapter, (obj) => obj.contentTypes) + ), + 'name' + ) + // eslint-disable-next-line no-return-assign + _.map(contentTypeObj, (val, key) => + _.forEach( + val, + (v) => (final[key] = (final[key] || 0) + v.count) + ) + ) + return final + }) + return tableObj + } else { + return {} + } + }) + return resolve(overalData) + } catch (err) { + // eslint-disable-next-line prefer-promise-reject-errors + reject( + 'programServiceException: error in preparing textbookLevelContentMetrics' + ) } - }); - return resolve(overalData); - }catch (err) { - reject('programServiceException: error in preparing textbookLevelContentMetrics'); - } - }, err => { - reject('programServiceException: error in fetching contentTypes'); - }); - }); + // eslint-disable-next-line handle-callback-err + }, + // eslint-disable-next-line handle-callback-err + (err) => { + // eslint-disable-next-line prefer-promise-reject-errors + reject('programServiceException: error in fetching contentTypes') + } + ) + }) } - chapterLevelContentMetrics(collectedData) { + chapterLevelContentMetrics (collectedData) { return new Promise((resolve, reject) => { - forkJoin(..._.map(collectedData, data => this.getProgramDetails(data.program_id))).subscribe(details => { - try { - const contentTypes = details.length ? _.uniq(_.compact(..._.map(details, model => model && model.dataValues.content_types))) : []; - const overalData = _.map(collectedData, data => { - if (data.collection && data.collection.length) { - const tableObj = _.map(data.collection, (collection) => { - const unitDetails = _.map(collection.chapter, unit => { - const final = {}; - final['Medium'] = collection.medium; - final['Grade'] = collection.grade; - final['Subject'] = collection.subject; - final['Textbook Name'] = collection.name; - final['Chapter Name'] = unit.name; - final['Total number of Approved Contents'] = unit.count || 0; - _.forEach(contentTypes, type => final[type] = 0); - _.forEach(unit.contentTypes, type => final[type.name] = (final[type.name] || 0) + type.count); - return final; - }); - return unitDetails; - }); - return _.flattenDeep(tableObj); - } else { - return {} - } - }); - resolve(overalData); - }catch (err) { - reject('programServiceException: error in preparing chapterLevelContentMetrics'); + forkJoin( + ..._.map(collectedData, (data) => + this.getProgramDetails(data.program_id) + ) + ).subscribe( + (details) => { + try { + const contentTypes = details.length + ? _.uniq( + _.compact( + ..._.map( + details, + (model) => model && model.dataValues.content_types + ) + ) + ) + : [] + const overalData = _.map(collectedData, (data) => { + if (data.collection && data.collection.length) { + const tableObj = _.map(data.collection, (collection) => { + const unitDetails = _.map(collection.chapter, (unit) => { + const final = {} + final.Medium = collection.medium + final.Grade = collection.grade + final.Subject = collection.subject + final['Textbook Name'] = collection.name + final['Chapter Name'] = unit.name + final['Total number of Approved Contents'] = + unit.count || 0 + // eslint-disable-next-line no-return-assign + _.forEach(contentTypes, (type) => (final[type] = 0)) + // eslint-disable-next-line no-return-assign + _.forEach( + unit.contentTypes, + (type) => + (final[type.name] = + (final[type.name] || 0) + type.count) + ) + return final + }) + return unitDetails + }) + return _.flattenDeep(tableObj) + } else { + return {} + } + }) + resolve(overalData) + } catch (err) { + // eslint-disable-next-line prefer-promise-reject-errors + reject( + 'programServiceException: error in preparing chapterLevelContentMetrics' + ) + } + // eslint-disable-next-line handle-callback-err + }, + // eslint-disable-next-line handle-callback-err + (err) => { + // eslint-disable-next-line prefer-promise-reject-errors + reject('programServiceException: error in fetching contentTypes') } - }, err => { - reject('programServiceException: error in fetching contentTypes'); - }); - }); + ) + }) } } -module.exports = ProgramServiceHelper; +module.exports = ProgramServiceHelper diff --git a/src/helpers/publishHelper.js b/src/helpers/publishHelper.js index dd4948b4b1be848d855c89370fb6f9a1e20fcee8..4a3af3bcf40387cdb26a7bb4ff6beb420380c3ae 100644 --- a/src/helpers/publishHelper.js +++ b/src/helpers/publishHelper.js @@ -1,72 +1,75 @@ -const uuid = require("uuid/v1") -const _ = require("lodash"); -const envVariables = require("../envVariables"); -const axios = require("axios"); -const { from } = require("rxjs"); +const uuid = require('uuid/v1') +const _ = require('lodash') +const envVariables = require('../envVariables') +const axios = require('axios') +const { from } = require('rxjs') -function getContentMetaData(contentId, reqHeaders){ - const url = `${envVariables.baseURL}/action/content/v3/read/${contentId}`; +function getContentMetaData (contentId, reqHeaders) { + const url = `${envVariables.baseURL}/action/content/v3/read/${contentId}` const option = { url: url, - method: "get", + method: 'get', headers: reqHeaders - }; - return from(axios(option)); + } + return from(axios(option)) } -function getPublishContentEvent(metadata, textbookId, units) { - metadata.pkgVersion = `${metadata.pkgVersion}.0`; - if(metadata.subject){ - metadata.subject = _.isArray(metadata.subject) ? metadata.subject : [metadata.subject]; - } - if(metadata.medium){ - metadata.medium = _.isArray(metadata.medium) ? metadata.medium : [metadata.medium]; - } - metadata = _.omit(metadata, [ - "downloadUrl", - "variants", - "previewUrl", - "streamingUrl", - "unitIdentifiers", - "itemSets" - ]); - var ets = Date.now(); - var dataObj = { - 'eid': 'BE_JOB_REQUEST', - 'ets': ets, - 'mid': `LP.${ets}.${uuid()}`, - 'actor': { - 'id': 'Auto Creator', - 'type': 'System' - }, - 'context': { - 'pdata': { - 'ver': '1.0', - 'id': 'org.ekstep.platform' - }, - 'channel': metadata.channel, - 'env': envVariables.PUBLISH_ENV - }, - 'object': { - 'ver': '1.0', - 'id': metadata.identifier +function getPublishContentEvent (metadata, textbookId, units) { + metadata.pkgVersion = `${metadata.pkgVersion}.0` + if (metadata.subject) { + metadata.subject = _.isArray(metadata.subject) + ? metadata.subject + : [metadata.subject] + } + if (metadata.medium) { + metadata.medium = _.isArray(metadata.medium) + ? metadata.medium + : [metadata.medium] + } + metadata = _.omit(metadata, [ + 'downloadUrl', + 'variants', + 'previewUrl', + 'streamingUrl', + 'unitIdentifiers', + 'itemSets' + ]) + var ets = Date.now() + var dataObj = { + eid: 'BE_JOB_REQUEST', + ets: ets, + mid: `LP.${ets}.${uuid()}`, + actor: { + id: 'Auto Creator', + type: 'System' + }, + context: { + pdata: { + ver: '1.0', + id: 'org.ekstep.platform' }, - 'edata': { - 'action': 'auto-create', - 'iteration': 1, - 'objectType': 'Content', - 'repository': `${envVariables.baseURL}/api/content/v1/read/${metadata.identifier}`, - 'metadata': metadata, - 'textbookInfo': { - 'identifier': textbookId, - 'unitIdentifiers': units - } + channel: metadata.channel, + env: envVariables.PUBLISH_ENV + }, + object: { + ver: '1.0', + id: metadata.identifier + }, + edata: { + action: 'auto-create', + iteration: 1, + objectType: 'Content', + repository: `${envVariables.baseURL}/api/content/v1/read/${metadata.identifier}`, + metadata: metadata, + textbookInfo: { + identifier: textbookId, + unitIdentifiers: units } } - - return dataObj; } + return dataObj +} module.exports.getPublishContentEvent = getPublishContentEvent module.exports.getContentMetaData = getContentMetaData diff --git a/src/helpers/redisUtil.js b/src/helpers/redisUtil.js index 275ec1b5a111d8fe424202eb3cacb7097f9d981f..a78dc1ee682905357c73a9fb323c50b84cf6fb69 100644 --- a/src/helpers/redisUtil.js +++ b/src/helpers/redisUtil.js @@ -1,98 +1,104 @@ -const redis = require('redis'); -const logger = require('sb_logger_util_v2'); -const envVariables = require("../envVariables"); -var redisClient; +const redis = require('redis') +const logger = require('sb_logger_util_v2') +const envVariables = require('../envVariables') class RedisManager { - constructor() { - this.redisClient = redis.createClient({ - host: envVariables.DOCK_REDIS_HOST, - port: envVariables.DOCK_REDIS_PORT, - retry_strategy: (options) => { - return 5000; //in ms - } - }); - /** - * Redis Event listener for `ready` event - */ - this.redisClient.on('ready', function () { - logger.info({msg: `✅ Redis Server connected to [${envVariables.DOCK_REDIS_HOST}:${envVariables.DOCK_REDIS_PORT}]`}); - }); - } - - /** - * Redis Event listener for `connect` event - */ - isConnected(){ - this.msgredisClient.on('connect', function () { - logger.info({msg: `✅ Redis Server connecting to [${envVariables.DOCK_REDIS_HOST}:${envVariables.DOCK_REDIS_PORT}]`}); - }); - } - + constructor () { + this.redisClient = redis.createClient({ + host: envVariables.DOCK_REDIS_HOST, + port: envVariables.DOCK_REDIS_PORT, + retry_strategy: (options) => { + return 5000 // in ms + } + }) /** * Redis Event listener for `ready` event */ - isReady(){ - this.redisClient.on('ready', function () { - logger.info({msg: `✅ Redis Server connected to [${envVariables.DOCK_REDIS_HOST}:${envVariables.DOCK_REDIS_PORT}]`}); - }); - } + this.redisClient.on('ready', function () { + logger.info({ + msg: `✅ Redis Server connected to [${envVariables.DOCK_REDIS_HOST}:${envVariables.DOCK_REDIS_PORT}]` + }) + }) + } - /** - * Redis Event listener for `reconnecting` event - */ - isReconnecting(){ - this.redisClient.on('reconnecting', function () { - logger.info({msg: `⌠Redis Server reconnecting to [${envVariables.DOCK_REDIS_HOST}:${envVariables.DOCK_REDIS_PORT}]`}); - // throw new Error('Redis Client - Connection failure'); - }); - } + /** + * Redis Event listener for `connect` event + */ + isConnected () { + this.msgredisClient.on('connect', function () { + logger.info({ + msg: `✅ Redis Server connecting to [${envVariables.DOCK_REDIS_HOST}:${envVariables.DOCK_REDIS_PORT}]` + }) + }) + } - /** - * Redis Event listener for `error` event - */ - isError(){ - this.redisClient.on('error', function (error) { - logger.info({ - msg: `⌠Redis Server error while connecting to [${envVariables.DOCK_REDIS_HOST}:${envVariables.DOCK_REDIS_PORT}]`, - error: error - }); - // throw new Error(error); - }); - } - - /** - * set data - */ - setData(data, callback) { - if(typeof callback !== "function") { - return; - } - this.redisClient.set(data.key, data.value, function(err){ - if (err) { - return callback(err, null); - } else { - return callback(null, {success : true}); - } - }); - } - - /** - * get data - */ - getData(key, callback) { - if(typeof callback !== "function") { - return; - } - this.redisClient.get(key, function(err, cacheData){ - if (err) { - return callback(err, null); - } else { - return callback(null, cacheData); - } - }); + /** + * Redis Event listener for `ready` event + */ + isReady () { + this.redisClient.on('ready', function () { + logger.info({ + msg: `✅ Redis Server connected to [${envVariables.DOCK_REDIS_HOST}:${envVariables.DOCK_REDIS_PORT}]` + }) + }) + } + + /** + * Redis Event listener for `reconnecting` event + */ + isReconnecting () { + this.redisClient.on('reconnecting', function () { + logger.info({ + msg: `⌠Redis Server reconnecting to [${envVariables.DOCK_REDIS_HOST}:${envVariables.DOCK_REDIS_PORT}]` + }) + // throw new Error('Redis Client - Connection failure'); + }) + } + + /** + * Redis Event listener for `error` event + */ + isError () { + this.redisClient.on('error', function (error) { + logger.info({ + msg: `⌠Redis Server error while connecting to [${envVariables.DOCK_REDIS_HOST}:${envVariables.DOCK_REDIS_PORT}]`, + error: error + }) + // throw new Error(error); + }) + } + + /** + * set data + */ + setData (data, callback) { + if (typeof callback !== 'function') { + return } + this.redisClient.set(data.key, data.value, function (err) { + if (err) { + return callback(err, null) + } else { + return callback(null, { success: true }) + } + }) + } + /** + * get data + */ + getData (key, callback) { + if (typeof callback !== 'function') { + return + } + this.redisClient.get(key, function (err, cacheData) { + if (err) { + return callback(err, null) + } else { + return callback(null, cacheData) + } + }) + } } -module.exports = RedisManager; \ No newline at end of file +module.exports = RedisManager diff --git a/src/helpers/updateHierarchy.helper.js b/src/helpers/updateHierarchy.helper.js index 7b89d890c329d0c27dd84576bf412155d40d2020..016d35486997eb146d20413d6fd1850b739414e3 100644 --- a/src/helpers/updateHierarchy.helper.js +++ b/src/helpers/updateHierarchy.helper.js @@ -1,91 +1,91 @@ -const { forkJoin } = require("rxjs"); -const _ = require("lodash"); -const envVariables = require("../envVariables"); -const axios = require("axios"); +const { forkJoin } = require('rxjs') +const _ = require('lodash') +const envVariables = require('../envVariables') +const axios = require('axios') class HierarchyService { - filterExistingTextbooks(collectionIds, reqHeaders) { - const url = `${envVariables.baseURL}/api/composite/v1/search`; - const filterRequest = _.map(collectionIds, id => { + filterExistingTextbooks (collectionIds, reqHeaders) { + const url = `${envVariables.baseURL}/api/composite/v1/search` + const filterRequest = _.map(collectionIds, (id) => { const option = { url: url, - method: "post", + method: 'post', headers: reqHeaders, data: { request: { filters: { - objectType: "content", - status: ["Draft", "Live"], + objectType: 'content', + status: ['Draft', 'Live'], identifier: id, - contentType: "Textbook" + contentType: 'Textbook' } } } - }; - return axios(option); - }); + } + return axios(option) + }) - return forkJoin(...filterRequest); + return forkJoin(...filterRequest) } - bulkUpdateHierarchy(collections, reqHeaders) { - const url = `${envVariables.LEARNING_SERVICE_URL}/content/v3/hierarchy/update`; - const bulkRequest = _.map(collections, collection => { - const createdBy = this.getCreatedBy(collection); + bulkUpdateHierarchy (collections, reqHeaders) { + const url = `${envVariables.LEARNING_SERVICE_URL}/content/v3/hierarchy/update` + const bulkRequest = _.map(collections, (collection) => { + const createdBy = this.getCreatedBy(collection) const option = { url, - method: "patch", + method: 'patch', headers: _.merge({}, reqHeaders, { - "x-authenticated-userid": createdBy + 'x-authenticated-userid': createdBy }), data: { request: { data: collection } } - }; - return axios(option); - }); + } + return axios(option) + }) - return forkJoin(...bulkRequest); + return forkJoin(...bulkRequest) } - getCreatedBy(collection) { - const nodesModified = _.get(collection, "nodesModified"); - const rootNode = _.findKey(nodesModified, item => { - return item.root === true; - }); - return nodesModified[rootNode].metadata.createdBy || null; + getCreatedBy (collection) { + const nodesModified = _.get(collection, 'nodesModified') + const rootNode = _.findKey(nodesModified, (item) => { + return item.root === true + }) + return nodesModified[rootNode].metadata.createdBy || null } - createCollection(collections, reqHeaders) { - const url = `http://content-service:9000/content/v3/create`; + createCollection (collections, reqHeaders) { + const url = 'http://content-service:9000/content/v3/create' - const bulkRequest = _.map(collections, collection => { + const bulkRequest = _.map(collections, (collection) => { const option = { url, - method: "post", + method: 'post', headers: reqHeaders, data: { request: { content: { ..._.omit(collection.result.content, [ - "children", - "identifier", - "status", - "reservedDialcodes", - "dialcodes", - "license", - "sYS_INTERNAL_LAST_UPDATED_ON", - "contentCredits", - "consumerId", - "osId", - "qrCodeProcessId", - "idealScreenSize", - "contentDisposition", - "os", - "idealScreenDensity", - "depth" + 'children', + 'identifier', + 'status', + 'reservedDialcodes', + 'dialcodes', + 'license', + 'sYS_INTERNAL_LAST_UPDATED_ON', + 'contentCredits', + 'consumerId', + 'osId', + 'qrCodeProcessId', + 'idealScreenSize', + 'contentDisposition', + 'os', + 'idealScreenDensity', + 'depth' ]) } } @@ -93,67 +93,70 @@ class HierarchyService { params: { identifier: collection.result.content.identifier } - }; - return axios(option); - }); - return forkJoin(...bulkRequest); + } + return axios(option) + }) + return forkJoin(...bulkRequest) } - getHierarchy(collectionIds, reqHeaders) { - const collectiveRequest = _.map(collectionIds, id => { - const url = `${envVariables.SUNBIRD_URL}/action/content/v3/hierarchy/${id}?mode=edit`; + getHierarchy (collectionIds, reqHeaders) { + const collectiveRequest = _.map(collectionIds, (id) => { + const url = `${envVariables.SUNBIRD_URL}/action/content/v3/hierarchy/${id}?mode=edit` const option = { url: url, - method: "get", + method: 'get', headers: reqHeaders - }; - return axios(option); - }); - return forkJoin(...collectiveRequest); + } + return axios(option) + }) + return forkJoin(...collectiveRequest) } - getExistingCollection(collections) { + getExistingCollection (collections) { return _.map( - _.filter(collections, r => { - return r.result.count > 0; + _.filter(collections, (r) => { + return r.result.count > 0 }), - tb => tb.result.content[0].identifier - ); + (tb) => tb.result.content[0].identifier + ) } - getNonExistingCollection(collections) { + getNonExistingCollection (collections) { return _.map( - _.filter(collections, r => { - return r.result.count === 0; + _.filter(collections, (r) => { + return r.result.count === 0 }), - tb => JSON.parse(tb.config).request.filters.identifier - ); + (tb) => JSON.parse(tb.config).request.filters.identifier + ) } - existingHierarchyUpdateRequest(data, additionalMetaData) { - let instance = this; - this.hierarchy = {}; - this.nodeModified = {}; - const response = data.result; + existingHierarchyUpdateRequest (data, additionalMetaData) { + const instance = this + this.hierarchy = {} + this.nodeModified = {} + const response = data.result return { nodesModified: instance.getFlatNodesModified( response.content, additionalMetaData ), - hierarchy: instance.getFlatHierarchyObj(response.content, additionalMetaData) - }; + hierarchy: instance.getFlatHierarchyObj( + response.content, + additionalMetaData + ) + } } - newHierarchyUpdateRequest(collection, additionalMetaData) { - let instance = this; - this.hierarchy = {}; - this.nodeModified = {}; - const response = collection.originHierarchy; + newHierarchyUpdateRequest (collection, additionalMetaData) { + const instance = this + this.hierarchy = {} + this.nodeModified = {} + const response = collection.originHierarchy additionalMetaData = { ...collection.creationResult.result, ...additionalMetaData, isFirstTime: true - }; + } return { nodesModified: instance.getFlatNodesModified( response.content, @@ -163,100 +166,100 @@ class HierarchyService { response.content, additionalMetaData ) - }; + } } - getFlatHierarchyObj(data, additionalMetaData) { - let instance = this; + getFlatHierarchyObj (data, additionalMetaData) { + const instance = this if (data) { - if (additionalMetaData.isFirstTime && data.contentType === "TextBook") { - data.identifier = additionalMetaData.identifier; + if (additionalMetaData.isFirstTime && data.contentType === 'TextBook') { + data.identifier = additionalMetaData.identifier } instance.hierarchy[data.identifier] = { name: data.name, contentType: data.contentType, children: _.compact( - _.map(data.children, function(child) { + _.map(data.children, function (child) { if ( - child.mimeType === "application/vnd.ekstep.content-collection" && - (child.contentType === "TextBook" || - child.contentType === "TextBookUnit") + child.mimeType === 'application/vnd.ekstep.content-collection' && + (child.contentType === 'TextBook' || + child.contentType === 'TextBookUnit') ) { - console.log(child.mimeType, child.identifier); - return child.identifier; + console.log(child.mimeType, child.identifier) + return child.identifier } }) ), - root: data.contentType === "TextBook" ? true : false - }; + root: data.contentType === 'TextBook' + } } - _.forEach(data.children, child => { + _.forEach(data.children, (child) => { if ( - child.contentType === "TextBookUnit" || - child.contentType === "TextBook" + child.contentType === 'TextBookUnit' || + child.contentType === 'TextBook' ) { - instance.getFlatHierarchyObj(child, additionalMetaData); + instance.getFlatHierarchyObj(child, additionalMetaData) } - }); - return instance.hierarchy; + }) + return instance.hierarchy } - getFlatNodesModified(data, additionalMetaData) { - let instance = this; - let nodeId; + getFlatNodesModified (data, additionalMetaData) { + const instance = this + let nodeId if (data) { - if (additionalMetaData.isFirstTime && data.contentType === "TextBook") { - nodeId = additionalMetaData.identifier; + if (additionalMetaData.isFirstTime && data.contentType === 'TextBook') { + nodeId = additionalMetaData.identifier } else { - nodeId = data.identifier; + nodeId = data.identifier } instance.nodeModified[nodeId] = { isNew: true, - root: data.contentType === "TextBook" ? true : false, + root: data.contentType === 'TextBook', metadata: { ..._.omit(data, [ - "children", - "identifier", - "status", - "reservedDialcodes", - "dialcodes", - "license", - "sYS_INTERNAL_LAST_UPDATED_ON", - "contentCredits", - "consumerId", - "osId", - "qrCodeProcessId", - "idealScreenSize", - "contentDisposition", - "os", - "idealScreenDensity", - "depth" + 'children', + 'identifier', + 'status', + 'reservedDialcodes', + 'dialcodes', + 'license', + 'sYS_INTERNAL_LAST_UPDATED_ON', + 'contentCredits', + 'consumerId', + 'osId', + 'qrCodeProcessId', + 'idealScreenSize', + 'contentDisposition', + 'os', + 'idealScreenDensity', + 'depth' ]), - ...(data.contentType === "TextBook" && { - chapterCount : data.children ? data.children.length : 0 + ...(data.contentType === 'TextBook' && { + chapterCount: data.children ? data.children.length : 0 }), programId: additionalMetaData.programId, allowedContentTypes: additionalMetaData.allowedContentTypes, openForContribution: true, - channel: envVariables.DOCK_CHANNEL || "sunbird", + channel: envVariables.DOCK_CHANNEL || 'sunbird', origin: data.origin || data.identifier, originData: { channel: data.originData ? data.originData.channel : data.channel } } - }; + } } - _.forEach(data.children, child => { + _.forEach(data.children, (child) => { if ( - child.contentType === "TextBookUnit" || - child.contentType === "TextBook" + child.contentType === 'TextBookUnit' || + child.contentType === 'TextBook' ) { - instance.getFlatNodesModified(child, additionalMetaData); + instance.getFlatNodesModified(child, additionalMetaData) } - }); - return instance.nodeModified; + }) + return instance.nodeModified } } -module.exports = HierarchyService; +module.exports = HierarchyService diff --git a/src/middlewares/request.middleware.js b/src/middlewares/request.middleware.js index b391bab931b9b3a91ab125c9b5a7a53a7e6087ed..cefd54edb6706a74a666571357b48985e385dd5b 100644 --- a/src/middlewares/request.middleware.js +++ b/src/middlewares/request.middleware.js @@ -1,7 +1,7 @@ var async = require('async') var uuidV1 = require('uuid/v1') var respUtil = require('response_util') // done -var messageUtil = require('../service/messageUtil') //done +var messageUtil = require('../service/messageUtil') // done var logger = require('sb_logger_util_v2') // done var utilsService = require('../service/utilsService') // var contentProvider = require('sb_content_provider_util') // done @@ -16,14 +16,24 @@ var configUtil = require('sb-config-util') // done var compression = require('compression') // done var keyCloakConfig = { - 'authServerUrl': process.env.sunbird_keycloak_auth_server_url ? process.env.sunbird_keycloak_auth_server_url : 'https://staging.open-sunbird.org/auth', - 'realm': process.env.sunbird_keycloak_realm ? process.env.sunbird_keycloak_realm : 'sunbird', - 'clientId': process.env.sunbird_keycloak_client_id ? process.env.sunbird_keycloak_client_id : 'portal', - 'public': process.env.sunbird_keycloak_public ? process.env.sunbird_keycloak_public : true + authServerUrl: process.env.sunbird_keycloak_auth_server_url + ? process.env.sunbird_keycloak_auth_server_url + : 'https://staging.open-sunbird.org/auth', + realm: process.env.sunbird_keycloak_realm + ? process.env.sunbird_keycloak_realm + : 'sunbird', + clientId: process.env.sunbird_keycloak_client_id + ? process.env.sunbird_keycloak_client_id + : 'portal', + public: process.env.sunbird_keycloak_public + ? process.env.sunbird_keycloak_public + : true } var cacheConfig = { - store: process.env.sunbird_cache_store ? process.env.sunbird_cache_store : 'memory', + store: process.env.sunbird_cache_store + ? process.env.sunbird_cache_store + : 'memory', ttl: process.env.sunbird_cache_ttl ? process.env.sunbird_cache_ttl : 1800 } @@ -43,7 +53,8 @@ function createAndValidateRequestBody (req, res, next) { req.body.url = req.url req.body.path = req.route.path req.body.params = req.body.params ? req.body.params : {} - req.body.params.msgid = req.get('x-msgid') || req.body.params.msgid || uuidV1() + req.body.params.msgid = + req.get('x-msgid') || req.body.params.msgid || uuidV1() req.id = req.body.params.msgid var rspObj = { apiId: utilsService.getAppIDForRESP(req.body.path), @@ -63,8 +74,21 @@ function createAndValidateRequestBody (req, res, next) { } req.headers.telemetryData = rspObj.telemetryData - var removedHeaders = ['host', 'origin', 'accept', 'referer', 'content-length', 'user-agent', - 'accept-language', 'accept-charset', 'cookie', 'dnt', 'postman-token', 'cache-control', 'connection'] + var removedHeaders = [ + 'host', + 'origin', + 'accept', + 'referer', + 'content-length', + 'user-agent', + 'accept-language', + 'accept-charset', + 'cookie', + 'dnt', + 'postman-token', + 'cache-control', + 'connection' + ] removedHeaders.forEach(function (e) { delete req.headers[e] @@ -74,7 +98,10 @@ function createAndValidateRequestBody (req, res, next) { body: req.body, params: req.params, query: req.query, - headers: lodash.omit(req.headers, ['Authorization', 'x-authenticated-user-token']) + headers: lodash.omit(req.headers, [ + 'Authorization', + 'x-authenticated-user-token' + ]) } logger.debug({ msg: 'new request', requestData: requestedData }, req) @@ -98,14 +125,17 @@ function validateToken (req, res, next) { rspObj.errMsg = reqMsg.TOKEN.MISSING_MESSAGE rspObj.responseCode = responseCode.UNAUTHORIZED_ACCESS - logger.error({ - msg: 'API failed due to missing token', - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode - } - }, req) + logger.error( + { + msg: 'API failed due to missing token', + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + } + }, + req + ) return res.status(401).send(respUtil.errorResponse(rspObj)) } @@ -115,23 +145,28 @@ function validateToken (req, res, next) { rspObj.errCode = reqMsg.TOKEN.INVALID_CODE rspObj.errMsg = reqMsg.TOKEN.INVALID_MESSAGE rspObj.responseCode = responseCode.UNAUTHORIZED_ACCESS - logger.error({ - msg: 'Invalid token', - err: { - err, - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode - } - }, req) + logger.error( + { + msg: 'Invalid token', + err: { + err, + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + } + }, + req + ) return res.status(401).send(respUtil.errorResponse(rspObj)) } else { var payload = jwt.decode(tokenData.token) delete req.headers['x-authenticated-userid'] var url = req.path - if (!url.includes('/content/v3/review') && + if ( + !url.includes('/content/v3/review') && !url.includes('/v1/content/review') && - !url.includes('/v1/course/review')) { + !url.includes('/v1/course/review') + ) { delete req.headers['x-authenticated-user-token'] } req.rspObj.userId = tokenData.userId @@ -170,14 +205,17 @@ function validateUserToken (req, res, next) { rspObj.errCode = reqMsg.TOKEN.MISSING_CODE rspObj.errMsg = reqMsg.TOKEN.MISSING_MESSAGE rspObj.responseCode = responseCode.UNAUTHORIZED_ACCESS - logger.error({ - msg: 'x-authenticated-user-token not present', - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode - } - }, req) + logger.error( + { + msg: 'x-authenticated-user-token not present', + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + } + }, + req + ) return res.status(401).send(respUtil.errorResponse(rspObj)) } @@ -186,16 +224,19 @@ function validateUserToken (req, res, next) { rspObj.errCode = reqMsg.TOKEN.INVALID_CODE rspObj.errMsg = reqMsg.TOKEN.INVALID_MESSAGE rspObj.responseCode = responseCode.UNAUTHORIZED_ACCESS - logger.error({ - msg: 'Invalid token', - err: { - err, - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode + logger.error( + { + msg: 'Invalid token', + err: { + err, + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + }, + additionalInfo: { token } }, - additionalInfo: { token } - }, req) + req + ) return res.status(401).send(respUtil.errorResponse(rspObj)) } else { delete req.headers['x-authenticated-user-token'] @@ -223,46 +264,75 @@ function apiAccessForCreatorUser (req, response, next) { data.contentId = req.params.contentId async.waterfall([ - function (CBW) { - contentProvider.getContentUsingQuery(data.contentId, qs, req.headers, + contentProvider.getContentUsingQuery( + data.contentId, + qs, + req.headers, function (err, res) { if (err || res.responseCode !== responseCode.SUCCESS) { - rspObj.errCode = res && res.params ? res.params.err : contentMessage.GET.FAILED_CODE - rspObj.errMsg = res && res.params ? res.params.errmsg : contentMessage.GET.FAILED_MESSAGE - rspObj.responseCode = res && res.responseCode ? res.responseCode : responseCode.SERVER_ERROR - logger.error({ - msg: 'Getting error from content provider', - err: { - err, - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode + rspObj.errCode = + res && res.params + ? res.params.err + : contentMessage.GET.FAILED_CODE + rspObj.errMsg = + res && res.params + ? res.params.errmsg + : contentMessage.GET.FAILED_MESSAGE + rspObj.responseCode = + res && res.responseCode + ? res.responseCode + : responseCode.SERVER_ERROR + logger.error( + { + msg: 'Getting error from content provider', + err: { + err, + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + }, + res }, - res - }, req) - var httpStatus = res && res.statusCode >= 100 && res.statusCode < 600 ? res.statusCode : 500 - return response.status(httpStatus).send(respUtil.errorResponse(rspObj)) + req + ) + var httpStatus = + res && res.statusCode >= 100 && res.statusCode < 600 + ? res.statusCode + : 500 + return response + .status(httpStatus) + .send(respUtil.errorResponse(rspObj)) } else { CBW(null, res) } - }) + } + ) }, function (res) { - let createdBy = res.result.content.createdBy.split(':') - if (createdBy[createdBy.length - 1] !== userId && !lodash.includes(res.result.content.collaborators, userId)) { + const createdBy = res.result.content.createdBy.split(':') + if ( + createdBy[createdBy.length - 1] !== userId && + !lodash.includes(res.result.content.collaborators, userId) + ) { rspObj.errCode = reqMsg.TOKEN.INVALID_CODE rspObj.errMsg = reqMsg.TOKEN.INVALID_MESSAGE rspObj.responseCode = responseCode.UNAUTHORIZED_ACCESS - logger.error({ - msg: 'Content createdBy and userId not matched', - additionalInfo: { createdBy: res.result.content.createdBy, userId: userId }, - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode - } - }, req) + logger.error( + { + msg: 'Content createdBy and userId not matched', + additionalInfo: { + createdBy: res.result.content.createdBy, + userId: userId + }, + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + } + }, + req + ) return response.status(401).send(respUtil.errorResponse(rspObj)) } else { next() @@ -290,44 +360,70 @@ function apiAccessForReviewerUser (req, response, next) { data.contentId = req.params.contentId async.waterfall([ - function (CBW) { - contentProvider.getContentUsingQuery(data.contentId, qs, req.headers, + contentProvider.getContentUsingQuery( + data.contentId, + qs, + req.headers, function (err, res) { if (err || res.responseCode !== responseCode.SUCCESS) { - rspObj.errCode = res && res.params ? res.params.err : contentMessage.GET.FAILED_CODE - rspObj.errMsg = res && res.params ? res.params.errmsg : contentMessage.GET.FAILED_MESSAGE - rspObj.responseCode = res && res.responseCode ? res.responseCode : responseCode.SERVER_ERROR - logger.error({ - msg: 'getting error from content provider', - err: { - err, - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode + rspObj.errCode = + res && res.params + ? res.params.err + : contentMessage.GET.FAILED_CODE + rspObj.errMsg = + res && res.params + ? res.params.errmsg + : contentMessage.GET.FAILED_MESSAGE + rspObj.responseCode = + res && res.responseCode + ? res.responseCode + : responseCode.SERVER_ERROR + logger.error( + { + msg: 'getting error from content provider', + err: { + err, + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + }, + additionalInfo: { qs } }, - additionalInfo: { qs } - }, req) - var httpStatus = res && res.statusCode >= 100 && res.statusCode < 600 ? res.statusCode : 500 - return response.status(httpStatus).send(respUtil.errorResponse(rspObj)) + req + ) + var httpStatus = + res && res.statusCode >= 100 && res.statusCode < 600 + ? res.statusCode + : 500 + return response + .status(httpStatus) + .send(respUtil.errorResponse(rspObj)) } else { CBW(null, res) } - }) + } + ) }, function (res) { - if (res.result.content.createdBy === userId || lodash.includes(res.result.content.collaborators, userId)) { + if ( + res.result.content.createdBy === userId || + lodash.includes(res.result.content.collaborators, userId) + ) { rspObj.errCode = reqMsg.TOKEN.INVALID_CODE rspObj.errMsg = reqMsg.TOKEN.INVALID_MESSAGE rspObj.responseCode = responseCode.UNAUTHORIZED_ACCESS - logger.error({ - msg: 'Unauthorized access', - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode - } - }, req) + logger.error( + { + msg: 'Unauthorized access', + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + } + }, + req + ) return response.status(401).send(respUtil.errorResponse(rspObj)) } else { next() @@ -356,63 +452,98 @@ function hierarchyUpdateApiAccess (req, response, next) { rspObj.errCode = contentMessage.HIERARCHY_UPDATE.MISSING_CODE rspObj.errMsg = contentMessage.HIERARCHY_UPDATE.MISSING_MESSAGE rspObj.responseCode = responseCode.CLIENT_ERROR - logger.error({ - msg: 'Error due to required params are missing', - additionalInfo: data.request, - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode - } - }, req) + logger.error( + { + msg: 'Error due to required params are missing', + additionalInfo: data.request, + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + } + }, + req + ) return response.status(400).send(respUtil.errorResponse(rspObj)) } var hierarchy = !_.isEmpty(data.request.data.hierarchy) - ? data.request.data.hierarchy : data.request.data.nodesModified + ? data.request.data.hierarchy + : data.request.data.nodesModified data.contentId = _.findKey(hierarchy, function (item) { if (item.root === true) return item }) async.waterfall([ function (CBW) { - contentProvider.getContentUsingQuery(data.contentId, qs, req.headers, function (err, res) { - if (err || res.responseCode !== responseCode.SUCCESS) { - rspObj.errCode = res && res.params ? res.params.err : contentMessage.GET.FAILED_CODE - rspObj.errMsg = res && res.params ? res.params.errmsg : contentMessage.GET.FAILED_MESSAGE - rspObj.responseCode = res && res.responseCode ? res.responseCode : responseCode.SERVER_ERROR - logger.error({ - msg: 'Getting error from content provider', - err: { - err, - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode - }, - additionalInfo: { qs } - }, req) - - var httpStatus = res && res.statusCode >= 100 && res.statusCode < 600 ? res.statusCode : 500 - return response.status(httpStatus).send(respUtil.errorResponse(rspObj)) - } else { - CBW(null, res) + contentProvider.getContentUsingQuery( + data.contentId, + qs, + req.headers, + function (err, res) { + if (err || res.responseCode !== responseCode.SUCCESS) { + rspObj.errCode = + res && res.params + ? res.params.err + : contentMessage.GET.FAILED_CODE + rspObj.errMsg = + res && res.params + ? res.params.errmsg + : contentMessage.GET.FAILED_MESSAGE + rspObj.responseCode = + res && res.responseCode + ? res.responseCode + : responseCode.SERVER_ERROR + logger.error( + { + msg: 'Getting error from content provider', + err: { + err, + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + }, + additionalInfo: { qs } + }, + req + ) + + var httpStatus = + res && res.statusCode >= 100 && res.statusCode < 600 + ? res.statusCode + : 500 + return response + .status(httpStatus) + .send(respUtil.errorResponse(rspObj)) + } else { + CBW(null, res) + } } - }) + ) }, function (res) { - if (res.result.content.createdBy !== userId && !lodash.includes(res.result.content.collaborators, userId)) { + if ( + res.result.content.createdBy !== userId && + !lodash.includes(res.result.content.collaborators, userId) + ) { rspObj.errCode = reqMsg.TOKEN.INVALID_CODE rspObj.errMsg = reqMsg.TOKEN.INVALID_MESSAGE rspObj.responseCode = responseCode.UNAUTHORIZED_ACCESS - logger.error({ - msg: 'Content createdBy and userId not matched', - additionalInfo: { createBy: res.result.content.createdBy, userId: userId }, - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode - } - }, req) + logger.error( + { + msg: 'Content createdBy and userId not matched', + additionalInfo: { + createBy: res.result.content.createdBy, + userId: userId + }, + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + } + }, + req + ) return response.status(401).send(respUtil.errorResponse(rspObj)) } else { next() @@ -435,14 +566,17 @@ function checkChannelID (req, res, next) { rspObj.errCode = reqMsg.PARAMS.MISSING_CHANNELID_CODE rspObj.errMsg = reqMsg.PARAMS.MISSING_CHANNELID_MESSAGE rspObj.responseCode = responseCode.CLIENT_ERROR - logger.error({ - msg: 'API failed due to missing channelID', - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode - } - }, req) + logger.error( + { + msg: 'API failed due to missing channelID', + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + } + }, + req + ) return res.status(400).send(respUtil.errorResponse(rspObj)) } logger.debug({ msg: `channel id = ${channelID}` }) diff --git a/src/models/configuration.js b/src/models/configuration.js index db63e72ae1812d1bbb72519d5b1d2d54a0fc455a..dd864aab60da7da1ae77de316368d2a9881a8b4b 100644 --- a/src/models/configuration.js +++ b/src/models/configuration.js @@ -1,38 +1,42 @@ -module.exports = function(sequelize, DataTypes) { - const configuration = sequelize.define("configuration", { - id: { - type: DataTypes.INTEGER, - autoIncrement: true, - allowNull: false, - primaryKey: true +module.exports = function (sequelize, DataTypes) { + const configuration = sequelize.define( + 'configuration', + { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + allowNull: false, + primaryKey: true + }, + key: { + type: DataTypes.STRING, + allowNull: false + }, + value: { + type: DataTypes.STRING, + allowNull: false + }, + status: { + type: DataTypes.ENUM('active', 'inactive'), + allowNull: false + }, + createdby: { + type: DataTypes.STRING + }, + updatedby: { + type: DataTypes.STRING + }, + createdon: { + type: DataTypes.DATE + }, + updatedon: { + type: DataTypes.DATE + } }, - key: { - type: DataTypes.STRING, - allowNull: false - }, - value: { - type: DataTypes.STRING, - allowNull: false - }, - status: { - type: DataTypes.ENUM("active", "inactive"), - allowNull: false - }, - createdby: { - type: DataTypes.STRING - }, - updatedby: { - type: DataTypes.STRING - }, - createdon: { - type: DataTypes.DATE - }, - updatedon: { - type: DataTypes.DATE + { + timestamps: false, + freezeTableName: true } - }, { - timestamps: false, - freezeTableName: true - }); - return configuration; -}; + ) + return configuration +} diff --git a/src/models/contenttypes.js b/src/models/contenttypes.js index 03b32fba5d8d6f4db1d09b3c71e6531a4ee28881..e20e53e07c519c13f8a1c7235f8d0b4f6e526b01 100644 --- a/src/models/contenttypes.js +++ b/src/models/contenttypes.js @@ -1,22 +1,38 @@ -module.exports = function(sequelize, DataTypes) { - const content = sequelize.define("contenttypes", { - id: { - type: DataTypes.INTEGER, - autoIncrement: true, - allowNull: false, - primaryKey: true +module.exports = function (sequelize, DataTypes) { + const content = sequelize.define( + 'contenttypes', + { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + allowNull: false, + primaryKey: true + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + value: { + type: DataTypes.ENUM( + 'TeachingMethod', + 'PedagogyFlow', + 'FocusSpot', + 'LearningOutcomeDefinition', + 'PracticeQuestionSet', + 'CuriosityQuestionSet', + 'MarkingSchemeRubric', + 'ExplanationResource', + 'ExperientialResource', + 'ConceptMap', + 'SelfAssess' + ), + allowNull: false + } }, - name: { - type: DataTypes.STRING, - allowNull: false - }, - value: { - type: DataTypes.ENUM("TeachingMethod", "PedagogyFlow", "FocusSpot", "LearningOutcomeDefinition", "PracticeQuestionSet", "CuriosityQuestionSet", "MarkingSchemeRubric", "ExplanationResource", "ExperientialResource", "ConceptMap", "SelfAssess"), - allowNull: false + { + timestamps: false, + freezeTableName: true } - }, { - timestamps: false, - freezeTableName: true - }); - return content; -}; + ) + return content +} diff --git a/src/models/index.js b/src/models/index.js index 3d83cf8fc90e62fa486c2f7fd82d19ebc673fc1d..f735991cc3e0eea11ca69c774725eac8e2149951 100644 --- a/src/models/index.js +++ b/src/models/index.js @@ -1,29 +1,36 @@ const Sequelize = require('sequelize') - envVariables = require('../envVariables') - path = require('path') - fs = require('fs'); - basename = path.basename(module.filename); +const envVariables = require('../envVariables') +const path = require('path') +const fs = require('fs') +const basename = path.basename(module.filename) -const HelperService = require('../helpers/helperService'); +const HelperService = require('../helpers/helperService') -var db = {}; -var sequelize = new Sequelize(envVariables.config.database, envVariables.config.user, envVariables.config.password, envVariables.config); +var db = {} +var sequelize = new Sequelize( + envVariables.config.database, + envVariables.config.user, + envVariables.config.password, + envVariables.config +) fs.readdirSync(__dirname) - .filter(function(file) { - return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); + .filter(function (file) { + return ( + file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js' + ) + }) + .forEach(function (file) { + var model = sequelize.import(path.join(__dirname, file)) + db[model.name] = model }) - .forEach(function(file) { - var model = sequelize['import'](path.join(__dirname, file)); - db[model.name] = model; - }); -db.sequelize = sequelize; -db.Sequelize = Sequelize; +db.sequelize = sequelize +db.Sequelize = Sequelize -db.program.hasMany(db.nomination, {foreignKey: 'program_id'}); -db.nomination.belongsTo(db.program, {foreignKey: 'program_id'}); +db.program.hasMany(db.nomination, { foreignKey: 'program_id' }) +db.nomination.belongsTo(db.program, { foreignKey: 'program_id' }) -HelperService.AttachModelHooks(db); +HelperService.AttachModelHooks(db) -module.exports = db; +module.exports = db diff --git a/src/models/nomination.js b/src/models/nomination.js index 361cad673b5a911b1ae0c1074820fb6c5b5f7fd4..c4607cfd473164d7cd1377961a6dc7c8746aeb3d 100644 --- a/src/models/nomination.js +++ b/src/models/nomination.js @@ -1,5 +1,7 @@ -module.exports = function(sequelize, DataTypes) { - const nomination = sequelize.define("nomination", { +module.exports = function (sequelize, DataTypes) { + const nomination = sequelize.define( + 'nomination', + { id: { type: DataTypes.INTEGER, allowNull: false, @@ -18,7 +20,7 @@ module.exports = function(sequelize, DataTypes) { type: DataTypes.STRING }, status: { - type: DataTypes.ENUM("Pending", "Approved", "Rejected"), + type: DataTypes.ENUM('Pending', 'Approved', 'Rejected'), allowNull: false }, content_types: { @@ -45,9 +47,11 @@ module.exports = function(sequelize, DataTypes) { updatedon: { type: DataTypes.DATE } - }, { - timestamps: false, - freezeTableName: true - }); - return nomination; - }; \ No newline at end of file + }, + { + timestamps: false, + freezeTableName: true + } + ) + return nomination +} diff --git a/src/models/program.js b/src/models/program.js index d56013b6023f82b74256f27a51364c20e3d3aafe..8e016efe0b4b767b782f164498785b25b5e68a4a 100644 --- a/src/models/program.js +++ b/src/models/program.js @@ -1,90 +1,94 @@ -module.exports = function(sequelize, DataTypes) { - const program = sequelize.define("program", { - program_id: { - type: DataTypes.UUID, - allowNull: false, - primaryKey: true - }, - name: { - type: DataTypes.STRING, - allowNull: false - }, - description: { - type: DataTypes.TEXT - }, - type: { - type: DataTypes.ENUM("public", "private"), - allowNull: false - }, - collection_ids: { - type: DataTypes.ARRAY(DataTypes.TEXT) - }, - content_types: { - type: DataTypes.ARRAY(DataTypes.TEXT) - }, - startdate: { - type: DataTypes.DATE - }, - enddate: { - type: DataTypes.DATE - }, - nomination_enddate: { - type: DataTypes.DATE - }, - shortlisting_enddate: { - type: DataTypes.DATE - }, - content_submission_enddate: { - type: DataTypes.DATE - }, - image: { - type: DataTypes.STRING - }, - status: { - type: DataTypes.ENUM("Draft", "Live"), - allowNull: false - }, - slug: { - type: DataTypes.STRING - }, - config: { - type: DataTypes.TEXT, - allowNull: false - }, - rolemapping: { - type: DataTypes.JSON - }, - createdby: { - type: DataTypes.STRING - }, - updatedby: { - type: DataTypes.STRING - }, - createdon: { - type: DataTypes.DATE - }, - updatedon: { - type: DataTypes.DATE - }, - rootorg_id: { - type: DataTypes.STRING - }, - sourcing_org_name: { - type: DataTypes.STRING - }, - channel: { - type: DataTypes.TEXT, - defaultValue: 'DIKSHA' - }, - template_id: { - type: DataTypes.TEXT - }, - guidelines_url: { - type: DataTypes.TEXT - } - }, { +module.exports = function (sequelize, DataTypes) { + const program = sequelize.define( + 'program', + { + program_id: { + type: DataTypes.UUID, + allowNull: false, + primaryKey: true + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + description: { + type: DataTypes.TEXT + }, + type: { + type: DataTypes.ENUM('public', 'private'), + allowNull: false + }, + collection_ids: { + type: DataTypes.ARRAY(DataTypes.TEXT) + }, + content_types: { + type: DataTypes.ARRAY(DataTypes.TEXT) + }, + startdate: { + type: DataTypes.DATE + }, + enddate: { + type: DataTypes.DATE + }, + nomination_enddate: { + type: DataTypes.DATE + }, + shortlisting_enddate: { + type: DataTypes.DATE + }, + content_submission_enddate: { + type: DataTypes.DATE + }, + image: { + type: DataTypes.STRING + }, + status: { + type: DataTypes.ENUM('Draft', 'Live'), + allowNull: false + }, + slug: { + type: DataTypes.STRING + }, + config: { + type: DataTypes.TEXT, + allowNull: false + }, + rolemapping: { + type: DataTypes.JSON + }, + createdby: { + type: DataTypes.STRING + }, + updatedby: { + type: DataTypes.STRING + }, + createdon: { + type: DataTypes.DATE + }, + updatedon: { + type: DataTypes.DATE + }, + rootorg_id: { + type: DataTypes.STRING + }, + sourcing_org_name: { + type: DataTypes.STRING + }, + channel: { + type: DataTypes.TEXT, + defaultValue: 'DIKSHA' + }, + template_id: { + type: DataTypes.TEXT + }, + guidelines_url: { + type: DataTypes.TEXT + } + }, + { timestamps: false, freezeTableName: true - }); - return program; -}; + } + ) + return program +} diff --git a/src/models/user_preference.js b/src/models/user_preference.js index 9745e97bdc31187a2420cc3534a08cb0dcc6a6c3..d1ce3d2d31f481e7a72d9457efdf0cd75dc5d1b3 100644 --- a/src/models/user_preference.js +++ b/src/models/user_preference.js @@ -1,5 +1,7 @@ -module.exports = function(sequelize, DataTypes) { - const preference = sequelize.define("user_program_preference", { +module.exports = function (sequelize, DataTypes) { + const preference = sequelize.define( + 'user_program_preference', + { user_id: { type: DataTypes.STRING, allowNull: false @@ -26,9 +28,11 @@ module.exports = function(sequelize, DataTypes) { updatedon: { type: DataTypes.DATE } - }, { - timestamps: false, - freezeTableName: true - }); - return preference; - }; \ No newline at end of file + }, + { + timestamps: false, + freezeTableName: true + } + ) + return preference +} diff --git a/src/package-lock.json b/src/package-lock.json index a705a5fda82e10f204e2885d745c432805152cf7..a6bbe8ee152811c345f9f6cb2440946071eddc14 100644 --- a/src/package-lock.json +++ b/src/package-lock.json @@ -4,6 +4,45 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.10.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.3.tgz", + "integrity": "sha512-fDx9eNW0qz0WkUeqL6tXEXzVlPh6Y5aCDEZesl0xBGA8ndRukX91Uk44ZqnkECp01NAZUdCAl+aiQNGi0k88Eg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.3" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.3", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz", + "integrity": "sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.10.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.3.tgz", + "integrity": "sha512-Ih9B/u7AtgEnySE2L2F0Xm0GaM729XqqLfHkalTsbjXGyqmf/6M0Cu0WpvqueUlW+xk88BHw9Nkpj49naU+vWw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.3", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, "@project-sunbird/telemetry-sdk": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/@project-sunbird/telemetry-sdk/-/telemetry-sdk-0.0.9.tgz", @@ -13,6 +52,18 @@ "karma": "^3.0.0" } }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, "@types/long": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", @@ -54,6 +105,12 @@ "acorn": "^2.1.0" } }, + "acorn-jsx": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", + "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", + "dev": true + }, "adm-zip": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.14.tgz", @@ -100,6 +157,27 @@ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -124,6 +202,15 @@ } } }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -144,6 +231,17 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, + "array-includes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + } + }, "array-slice": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", @@ -154,6 +252,16 @@ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, "arraybuffer.slice": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", @@ -197,6 +305,12 @@ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", @@ -398,6 +512,11 @@ "type-is": "~1.6.16" } }, + "bowser": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.9.0.tgz", + "integrity": "sha512-2ld76tuLBNFekRgmJfT2+3j5MIrP6bFict8WAIT3beq+srz1gcKNAdNKMqHqauQt63NmAa88HfP1/Ypa9Er3HA==" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -504,11 +623,22 @@ "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, "camelcase": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" }, + "camelize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", + "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -547,6 +677,58 @@ "type-detect": "^4.0.5" } }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "character-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-1.2.1.tgz", @@ -669,6 +851,21 @@ "object-visit": "^1.0.0" } }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -772,11 +969,22 @@ "acorn": "^2.1.0" } }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" }, + "content-security-policy-builder": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-2.1.0.tgz", + "integrity": "sha512-/MtLWhJVvJNkA9dVLAp6fg9LxD2gfI6R2Fi1hPmfjYXSahJJzcfvoeDOxSyp4NvxMuwWv3WMssE9o31DoULHrQ==" + }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", @@ -816,6 +1024,17 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "css": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/css/-/css-1.0.8.tgz", @@ -848,6 +1067,11 @@ "assert-plus": "^1.0.0" } }, + "dasherize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz", + "integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg=" + }, "date-format": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", @@ -891,6 +1115,21 @@ "type-detect": "^4.0.0" } }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", @@ -948,6 +1187,20 @@ "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=" }, + "dns-prefetch-control": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.2.0.tgz", + "integrity": "sha512-hvSnros73+qyZXhHFjx2CMLwoj3Fe7eR9EJsFsqmcI1bB2OBWL/+0YzaEaKssCHnj/6crawNnUyw74Gm2EKe+Q==" + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "dom-serialize": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", @@ -959,6 +1212,11 @@ "void-elements": "^2.0.0" } }, + "dont-sniff-mimetype": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.1.0.tgz", + "integrity": "sha512-ZjI4zqTaxveH2/tTlzS1wFp+7ncxNZaIEWYg3lzZRHkKf5zPT/MnEG6WL0BhHMJUabkh8GeU5NL5j+rEUCb7Ug==" + }, "dottie": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", @@ -1000,6 +1258,12 @@ "minimalistic-crypto-utils": "^1.0.0" } }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -1083,16 +1347,343 @@ "has-binary2": "~1.0.2" } }, + "enquirer": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.5.tgz", + "integrity": "sha512-BNT1C08P9XD0vNg3J475yIUG+mVdp9T6towYFHUv897X0KoHBjB1shyrNmhmtHWKP17iSWgo7Gqh7BBuzLZMSA==", + "dev": true, + "requires": { + "ansi-colors": "^3.2.1" + } + }, "ent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=" }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.3.0.tgz", + "integrity": "sha512-dJMVXwfU5PT1cj2Nv2VPPrKahKTGdX+5Dh0Q3YuKt+Y2UhdL2YbzsVaBMyG9HC0tBismlv/r1+eZqs6SMIV38Q==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.0", + "eslint-utils": "^2.0.0", + "eslint-visitor-keys": "^1.2.0", + "espree": "^7.1.0", + "esquery": "^1.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } + } + }, + "eslint-config-standard": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz", + "integrity": "sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg==", + "dev": true + }, + "eslint-config-strongloop": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-strongloop/-/eslint-config-strongloop-2.1.0.tgz", + "integrity": "sha1-dj3Rmt/OiNewBR5uJV8a43eDtMY=", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + } + }, + "eslint-module-utils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + } + }, + "eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + } + }, + "eslint-plugin-import": { + "version": "2.21.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.21.2.tgz", + "integrity": "sha512-FEmxeGI6yaz+SnEB6YgNHlQK1Bs2DKLM+YF+vuTk5H8J9CLbJLtlPvRFgZZ2+sXiKAlN5dpdlrWOjK8ZoZJpQA==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.3", + "eslint-module-utils": "^2.6.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.1", + "read-pkg-up": "^2.0.0", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + } + } + }, + "eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, + "requires": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", + "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", + "dev": true + }, + "eslint-plugin-standard": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz", + "integrity": "sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ==", + "dev": true + }, + "eslint-scope": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", + "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.1.0.tgz", + "integrity": "sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==", + "dev": true, + "requires": { + "acorn": "^7.2.0", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.2.0" + }, + "dependencies": { + "acorn": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz", + "integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", + "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -1194,6 +1785,11 @@ } } }, + "expect-ct": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/expect-ct/-/expect-ct-0.2.0.tgz", + "integrity": "sha512-6SK3MG/Bbhm8MsgyJAylg+ucIOU71/FzyFalcfu5nY19dH8y/z0tBJU0wrNBXD4B27EoQtqPF/9wqH0iYAd04g==" + }, "express": { "version": "4.16.4", "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", @@ -1380,6 +1976,26 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "feature-policy": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/feature-policy/-/feature-policy-0.3.0.tgz", + "integrity": "sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ==" + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -1428,6 +2044,37 @@ } } }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "flatted": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", @@ -1484,6 +2131,11 @@ "map-cache": "^0.2.2" } }, + "frameguard": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.1.0.tgz", + "integrity": "sha512-TxgSKM+7LTA6sidjOiSZK9wxY0ffMPY3Wta//MqwmX0nZuEHc8QrkV8Fh3ZhMJeiH+Uyh/tcaarImRy8u77O7g==" + }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -1994,6 +2646,18 @@ } } }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", @@ -2044,6 +2708,15 @@ } } }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, "graceful-fs": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", @@ -2083,6 +2756,15 @@ "har-schema": "^2.0.0" } }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, "has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", @@ -2103,6 +2785,18 @@ "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -2141,6 +2835,55 @@ "minimalistic-assert": "^1.0.1" } }, + "helmet": { + "version": "3.23.1", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.23.1.tgz", + "integrity": "sha512-e034HHfRK4065BFjYbffn5jXaTWWrhTNgmLIppsGEOjpdDB1MBQkWlAFW/auULXAu6uKk2X76n7a7gvz5sSjkg==", + "requires": { + "depd": "2.0.0", + "dns-prefetch-control": "0.2.0", + "dont-sniff-mimetype": "1.1.0", + "expect-ct": "0.2.0", + "feature-policy": "0.3.0", + "frameguard": "3.1.0", + "helmet-crossdomain": "0.4.0", + "helmet-csp": "2.10.0", + "hide-powered-by": "1.1.0", + "hpkp": "2.0.0", + "hsts": "2.2.0", + "nocache": "2.1.0", + "referrer-policy": "1.2.0", + "x-xss-protection": "1.3.0" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + } + } + }, + "helmet-crossdomain": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/helmet-crossdomain/-/helmet-crossdomain-0.4.0.tgz", + "integrity": "sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA==" + }, + "helmet-csp": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.10.0.tgz", + "integrity": "sha512-Rz953ZNEFk8sT2XvewXkYN0Ho4GEZdjAZy4stjiEQV3eN7GDxg1QKmYggH7otDyIA7uGA6XnUMVSgeJwbR5X+w==", + "requires": { + "bowser": "2.9.0", + "camelize": "1.0.0", + "content-security-policy-builder": "2.1.0", + "dasherize": "2.0.0" + } + }, + "hide-powered-by": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.1.0.tgz", + "integrity": "sha512-Io1zA2yOA1YJslkr+AJlWSf2yWFkKjvkcL9Ni1XSUqnGLr/qRQe2UI3Cn/J9MsJht7yEVCe0SscY1HgVMujbgg==" + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -2151,6 +2894,32 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "hpkp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz", + "integrity": "sha1-EOFCJk52IVpdMMROxD3mTe5tFnI=" + }, + "hsts": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.2.0.tgz", + "integrity": "sha512-ToaTnQ2TbJkochoVcdXYm4HOCliNozlviNsg+X2XQLQvZNI/kCHR9rZxVYpJB3UPcHz80PgxRyWQ7PdU1r+VBQ==", + "requires": { + "depd": "2.0.0" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + } + } + }, "http-errors": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", @@ -2197,6 +2966,28 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", @@ -2244,6 +3035,12 @@ } } }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", @@ -2262,6 +3059,12 @@ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", + "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", + "dev": true + }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -2280,6 +3083,12 @@ } } }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", @@ -2307,6 +3116,12 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -2346,6 +3161,30 @@ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", + "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -2369,6 +3208,12 @@ "buffer-alloc": "^1.2.0" } }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", @@ -2396,6 +3241,22 @@ "with": "~4.0.0" } }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -2411,11 +3272,34 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } + } + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -2610,6 +3494,38 @@ "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", @@ -2866,11 +3782,34 @@ "to-regex": "^3.0.1" } }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, + "nocache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz", + "integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q==" + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -2919,6 +3858,18 @@ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.1.4.tgz", "integrity": "sha1-E28H8aSK9fa5BoEkUa5OQ5eMlKo=" }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", @@ -2927,6 +3878,18 @@ "isobject": "^3.0.0" } }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -2935,6 +3898,18 @@ "isobject": "^3.0.1" } }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -2964,16 +3939,72 @@ "wordwrap": "~0.0.2" } }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, "packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", @@ -3005,16 +4036,43 @@ "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, "pathval": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", @@ -3087,6 +4145,21 @@ "split": "^1.0.0" } }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -3115,11 +4188,23 @@ "xtend": "^4.0.0" } }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, "promise": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz", @@ -3178,6 +4263,27 @@ "unpipe": "1.0.0" } }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -3207,6 +4313,11 @@ "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==" }, + "referrer-policy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.2.0.tgz", + "integrity": "sha512-LgQJIuS6nAy1Jd88DCQRemyE3mS+ispwlqMk3b0yjZ257fI1v9c+/p6SD5gP5FGyXUIgrNOAfmyioHwZtYv2VA==" + }, "regenerator-runtime": { "version": "0.10.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", @@ -3221,6 +4332,12 @@ "safe-regex": "^1.1.0" } }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -3275,6 +4392,21 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -3575,11 +4707,37 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "shimmer": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -3821,6 +4979,38 @@ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, "split": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", @@ -3837,6 +5027,12 @@ "extend-shallow": "^3.0.0" } }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, "sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", @@ -3907,6 +5103,54 @@ } } }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -3915,6 +5159,54 @@ "safe-buffer": "~5.1.0" } }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", + "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -4027,6 +5319,26 @@ } } }, + "tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } + } + }, "tslib": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", @@ -4045,11 +5357,26 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -4200,6 +5527,22 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" }, + "v8-compile-cache": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "validator": { "version": "10.11.0", "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", @@ -4225,6 +5568,15 @@ "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", @@ -4254,6 +5606,12 @@ "@types/node": "*" } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", @@ -4264,6 +5622,15 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", @@ -4274,6 +5641,11 @@ "ultron": "~1.1.0" } }, + "x-xss-protection": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.3.0.tgz", + "integrity": "sha512-kpyBI9TlVipZO4diReZMAHWtS0MMa/7Kgx8hwG/EuZLiA6sg4Ah/4TRdASHhRRN3boobzcYgFRUFSgHRge6Qhg==" + }, "xmlhttprequest-ssl": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", diff --git a/src/package.json b/src/package.json index 7b7b14e193471f1b6189f99bf05df92721baff15..f943bcdd5df07a01dfcbe97d7e2026acedfc1831 100644 --- a/src/package.json +++ b/src/package.json @@ -16,6 +16,7 @@ "express": "~4.16.1", "express-cassandra": "^2.3.2", "express-cluster": "0.0.5", + "helmet": "^3.23.1", "http-errors": "^1.6.3", "jade": "~1.11.0", "jsonwebtoken": "^8.5.1", @@ -38,5 +39,14 @@ "sequelize": "^5.21.5", "underscore": "^1.9.2", "uuid": "^3.2.1" + }, + "devDependencies": { + "eslint": "^7.3.0", + "eslint-config-standard": "^14.1.1", + "eslint-config-strongloop": "^2.1.0", + "eslint-plugin-import": "^2.21.2", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-standard": "^4.0.1" } } diff --git a/src/routes/index.js b/src/routes/index.js deleted file mode 100644 index ecca96a56b309a315ddf6399155fd2f953031d3b..0000000000000000000000000000000000000000 --- a/src/routes/index.js +++ /dev/null @@ -1,9 +0,0 @@ -var express = require('express'); -var router = express.Router(); - -/* GET home page. */ -router.get('/', function(req, res, next) { - res.render('index', { title: 'Express' }); -}); - -module.exports = router; diff --git a/src/routes/programRoutes.js b/src/routes/programRoutes.js index f857a2480c706c1ab8d2e4254170ada8a9061fe3..417b8eee3de72e679ce5c273e7c633bd3014f8cd 100644 --- a/src/routes/programRoutes.js +++ b/src/routes/programRoutes.js @@ -1,107 +1,207 @@ -const programService = require('../service/programService'); -const userProgramPreference = require('../service/userProgramPreference'); +const programService = require('../service/programService') +const userProgramPreference = require('../service/userProgramPreference') const requestMiddleware = require('../middlewares/request.middleware') const BASE_URL = '/program/v1' module.exports = function (app) { - app.route(BASE_URL + '/read/:program_id') - .get(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.getProgramAPI) - - app.route(BASE_URL + '/create') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.createProgramAPI) - - app.route(BASE_URL + '/update') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.updateProgramAPI) - - app.route(BASE_URL + '/delete') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.deleteProgramAPI) - - app.route(BASE_URL + '/list') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.programListAPI) - - app.route(BASE_URL + '/list/download') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.downloadProgramDetailsAPI) - - app.route(BASE_URL + '/report') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.generateApprovedContentReportAPI) - - app.route(BASE_URL + '/search') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.programSearchAPI) - - app.route(BASE_URL + '/nomination/add') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.addNominationAPI) - - app.route(BASE_URL + '/nomination/update') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.updateNominationAPI) - - app.route(BASE_URL + '/nomination/remove') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.removeNominationAPI) - - app.route(BASE_URL + '/nomination/list') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.nominationsListAPI) - - app.route(BASE_URL + '/nomination/list/download') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.downloadNominationListAPI) - - app.route(BASE_URL + '/collection/link') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.programUpdateCollectionAPI) - - app.route(BASE_URL + '/contenttypes/list') - .get(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.programGetContentTypesAPI) - - app.route(BASE_URL + '/health') - .get(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.healthAPI) - - app.route(BASE_URL + '/users/:user_id') - .get(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.getUserDetailsAPI) - - app.route(BASE_URL + '/collection/copy') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.programCopyCollectionAPI) - - app.route(BASE_URL + '/configuration/list') - .get(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.getAllConfigurationsAPI) - - app.route(BASE_URL + '/configuration/search') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.getConfigurationByKeyAPI) - - app.route(BASE_URL + '/content/publish') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.publishContentAPI) - - app.route(BASE_URL + '/tenant/list') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - programService.programCountsByOrgAPI) - - app.route(BASE_URL + '/preference/create') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - userProgramPreference.setUserPreferences) - - app.route(BASE_URL + '/preference/update') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - userProgramPreference.setUserPreferences) - - app.route(BASE_URL + '/preference/read') - .post(requestMiddleware.gzipCompression(), requestMiddleware.createAndValidateRequestBody, - userProgramPreference.getUserPreferences) + app + .route(BASE_URL + '/read/:program_id') + .get( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.getProgramAPI + ) + + app + .route(BASE_URL + '/create') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.createProgramAPI + ) + + app + .route(BASE_URL + '/update') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.updateProgramAPI + ) + + app + .route(BASE_URL + '/delete') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.deleteProgramAPI + ) + + app + .route(BASE_URL + '/list') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.programListAPI + ) + + app + .route(BASE_URL + '/list/download') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.downloadProgramDetailsAPI + ) + + app + .route(BASE_URL + '/report') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.generateApprovedContentReportAPI + ) + + app + .route(BASE_URL + '/search') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.programSearchAPI + ) + + app + .route(BASE_URL + '/nomination/add') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.addNominationAPI + ) + + app + .route(BASE_URL + '/nomination/update') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.updateNominationAPI + ) + + app + .route(BASE_URL + '/nomination/remove') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.removeNominationAPI + ) + + app + .route(BASE_URL + '/nomination/list') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.nominationsListAPI + ) + + app + .route(BASE_URL + '/nomination/list/download') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.downloadNominationListAPI + ) + + app + .route(BASE_URL + '/collection/link') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.programUpdateCollectionAPI + ) + + app + .route(BASE_URL + '/contenttypes/list') + .get( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.programGetContentTypesAPI + ) + + app + .route(BASE_URL + '/health') + .get( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.healthAPI + ) + + app + .route(BASE_URL + '/users/:user_id') + .get( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.getUserDetailsAPI + ) + + app + .route(BASE_URL + '/collection/copy') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.programCopyCollectionAPI + ) + + app + .route(BASE_URL + '/configuration/list') + .get( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.getAllConfigurationsAPI + ) + + app + .route(BASE_URL + '/configuration/search') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.getConfigurationByKeyAPI + ) + + app + .route(BASE_URL + '/content/publish') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.publishContentAPI + ) + + app + .route(BASE_URL + '/tenant/list') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + programService.programCountsByOrgAPI + ) + + app + .route(BASE_URL + '/preference/create') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + userProgramPreference.setUserPreferences + ) + + app + .route(BASE_URL + '/preference/update') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + userProgramPreference.setUserPreferences + ) + + app + .route(BASE_URL + '/preference/read') + .post( + requestMiddleware.gzipCompression(), + requestMiddleware.createAndValidateRequestBody, + userProgramPreference.getUserPreferences + ) } diff --git a/src/routes/users.js b/src/routes/users.js deleted file mode 100644 index 623e4302bee32ccc080d1c83ee2e55a426c9bac8..0000000000000000000000000000000000000000 --- a/src/routes/users.js +++ /dev/null @@ -1,9 +0,0 @@ -var express = require('express'); -var router = express.Router(); - -/* GET users listing. */ -router.get('/', function(req, res, next) { - res.send('respond with a resource'); -}); - -module.exports = router; diff --git a/src/service/messageUtil.js b/src/service/messageUtil.js index c60ccf97ab57f7128454b769e056841a945faf54..1a88ef7c2cfeb4295e966ea06d2e5eabb911f291 100644 --- a/src/service/messageUtil.js +++ b/src/service/messageUtil.js @@ -1,12 +1,8 @@ exports.COMPOSITE = { - - CONTENT_TYPE: [ - 'Collection', 'LessonPlan', 'Resource', 'TextBook' - ] + CONTENT_TYPE: ['Collection', 'LessonPlan', 'Resource', 'TextBook'] } exports.COURSE = { - SEARCH: { MISSING_CODE: 'ERR_COURSE_SEARCH_FIELDS_MISSING', MISSING_MESSAGE: 'Required fields for search course are missing', @@ -72,7 +68,6 @@ exports.COURSE = { } exports.CONTENT = { - SEARCH: { MISSING_CODE: 'ERR_CONTENT_SEARCH_FIELDS_MISSING', MISSING_MESSAGE: 'Required fields for search content are missing', @@ -181,12 +176,7 @@ exports.CONTENT = { FAILED_MESSAGE: 'Unlisted publish content failed' }, - CONTENT_TYPE: [ - 'Story', - 'Worksheet', - 'TextBook', - 'Collection' - ], + CONTENT_TYPE: ['Story', 'Worksheet', 'TextBook', 'Collection'], MIME_TYPE: [ 'application/vnd.ekstep.ecml-archive', @@ -264,7 +254,8 @@ exports.CONTENT = { FAILED_MESSAGE: 'Creating lock failed', ALREADY_LOCKED: 'The resource is already locked by {{Name}}', DEVICE_ID_MISSING: 'X-device-Id is missing in headers', - SAME_USER_ERR_MSG: 'The resource is already locked by you in a different window/device', + SAME_USER_ERR_MSG: + 'The resource is already locked by you in a different window/device', UNAUTHORIZED: 'You are not authorized to lock this resource', SELF_LOCKED_CODE: 'RESOURCE_SELF_LOCKED', LOCKED_CODE: 'RESOURCE_LOCKED' @@ -299,7 +290,6 @@ exports.CONTENT = { } exports.REQUEST = { - PARAMS: { MISSING_CID_CODE: 'ERR_REQUEST_FIELDS_CID_MISSING', MISSING_CID_MESSAGE: 'Required field consumer id is missing', @@ -347,7 +337,6 @@ exports.UTILS = { } exports.DOMAIN = { - GET_DOMAINS: { FAILED_CODE: 'ERR_GET_DOMAINS_FAILED', FAILED_MESSAGE: 'Get domains failed' @@ -414,81 +403,94 @@ exports.EMAIL = { CREATE_FLAG: { FAILED_CODE: 'ERR_SEND_CREATE_FLAG_EMAIL', FAILED_MESSAGE: 'Sending email failed for create flag', - SUBJECT: 'Flag raised for your content: Content Type: {{Content type}}, Title: {{Content title}} ', - BODY: 'Your content is flagged by another user. <br><br>' + - '<b>Content Type: </b>{{Content type}}<br>' + - '<b>Title: </b>{{Content title}}<br>' + - '<b>Flag(s) Raised: </b>{{Flag reason}}<br>' + - '<b>Content Status: </b>{{Content status}}<br>', + SUBJECT: + 'Flag raised for your content: Content Type: {{Content type}}, Title: {{Content title}} ', + BODY: + 'Your content is flagged by another user. <br><br>' + + '<b>Content Type: </b>{{Content type}}<br>' + + '<b>Title: </b>{{Content title}}<br>' + + '<b>Flag(s) Raised: </b>{{Flag reason}}<br>' + + '<b>Content Status: </b>{{Content status}}<br>', TEMPLATE: 'contentFlagged' }, ACCEPT_FLAG: { FAILED_CODE: 'ERR_SEND_ACCEPT_FLAG_EMAIL', FAILED_MESSAGE: 'Sending email failed for accept flag', - SUBJECT: 'Reviewer has accepted the flag for your content: {{Content type}} ', - BODY: 'Your content has been flagged by the reviewer. <br><br>' + - '<b>Content Type: </b>{{Content type}}<br>' + - '<b>Title: </b>{{Content title}}<br>' + - '<b>Flag(s) Raised: </b>{{Flag reason}}<br>', + SUBJECT: + 'Reviewer has accepted the flag for your content: {{Content type}} ', + BODY: + 'Your content has been flagged by the reviewer. <br><br>' + + '<b>Content Type: </b>{{Content type}}<br>' + + '<b>Title: </b>{{Content title}}<br>' + + '<b>Flag(s) Raised: </b>{{Flag reason}}<br>', TEMPLATE: 'acceptFlag' }, REJECT_FLAG: { FAILED_CODE: 'ERR_SEND_REJECT_FLAG_EMAIL', FAILED_MESSAGE: 'Sending email failed for reject flag', - SUBJECT: 'Congratulations, your content is live! Content Type: {{Content type}}, Title: {{Content title}}', - BODY: 'Congratulations! The content that you had submitted has been accepted for publication.' + - ' It is now available for usage. <br><br>' + - '<b>Content Type: </b>{{Content type}}<br>' + - '<b>Title: </b>{{Content title}}<br>' + - '<b>Status: </b>{{Content status}}<br>', + SUBJECT: + 'Congratulations, your content is live! Content Type: {{Content type}}, Title: {{Content title}}', + BODY: + 'Congratulations! The content that you had submitted has been accepted for publication.' + + ' It is now available for usage. <br><br>' + + '<b>Content Type: </b>{{Content type}}<br>' + + '<b>Title: </b>{{Content title}}<br>' + + '<b>Status: </b>{{Content status}}<br>', TEMPLATE: 'rejectFlag' }, PUBLISHED_CONTENT: { FAILED_CODE: 'ERR_SEND_PUBLISHED_CONTENT_EMAIL', FAILED_MESSAGE: 'Sending email failed for published content', - SUBJECT: 'Congratulations, your content is live! Content Type: {{Content type}}, Title: {{Content title}}', - BODY: 'Congratulations! The content that you had submitted has been accepted for publication. ' + - 'It will be available for usage shortly. <br><br>' + - '<b>Content Type: </b>{{Content type}}<br> ' + - '<b>Title: </b>{{Content title}}<br>', + SUBJECT: + 'Congratulations, your content is live! Content Type: {{Content type}}, Title: {{Content title}}', + BODY: + 'Congratulations! The content that you had submitted has been accepted for publication. ' + + 'It will be available for usage shortly. <br><br>' + + '<b>Content Type: </b>{{Content type}}<br> ' + + '<b>Title: </b>{{Content title}}<br>', TEMPLATE: 'publishContent' }, REJECT_CONTENT: { FAILED_CODE: 'ERR_SEND_REJECT_CONTENT_EMAIL', FAILED_MESSAGE: 'Sending email failed for reject content', - SUBJECT: 'Our sincere apologies! Content Type: {{Content type}}, Title: {{Content title}}', - BODY: 'We acknowledge your contribution and effort in creating content for us.' + - ' However, we are unable to accept the content that you submitted.<br>' + - 'We look forward to a more meaningful relationship with you, the next time around. <br><br>' + - '<b>Content Type: </b>{{Content type}}<br>' + - '<b>Title: </b>{{Content title}}<br>' + - '<b>Status: </b>{{Content status}}<br>', + SUBJECT: + 'Our sincere apologies! Content Type: {{Content type}}, Title: {{Content title}}', + BODY: + 'We acknowledge your contribution and effort in creating content for us.' + + ' However, we are unable to accept the content that you submitted.<br>' + + 'We look forward to a more meaningful relationship with you, the next time around. <br><br>' + + '<b>Content Type: </b>{{Content type}}<br>' + + '<b>Title: </b>{{Content title}}<br>' + + '<b>Status: </b>{{Content status}}<br>', TEMPLATE: 'rejectContent' }, UNLISTED_PUBLISH_CONTENT: { FAILED_CODE: 'ERR_SEND_UNLISTED_PUBLISH_CONTENT_EMAIL', FAILED_MESSAGE: 'Sending email failed for unlist publish content', SUBJECT: 'Congratulations, your content {{Content title}} is live!', - BODY: 'Congratulations! The content is now ready for limited sharing. ' + - 'You can share it using <a href=\'{{Share url}}\'>{{Share url}}</a>. <br><br>' + - '<b>Content Type: </b>{{Content type}}<br> ' + - '<b>Title: </b>{{Content title}}<br>', + BODY: + 'Congratulations! The content is now ready for limited sharing. ' + + "You can share it using <a href='{{Share url}}'>{{Share url}}</a>. <br><br>" + + '<b>Content Type: </b>{{Content type}}<br> ' + + '<b>Title: </b>{{Content title}}<br>', TEMPLATE: 'unlistedPublishContent' }, ADD_COLLABORATORS: { FAILED_CODE: 'ERR_SEND_ADD_COLLABORATORS_EMAIL', FAILED_MESSAGE: 'Sending email failed for adding collaborators', SUBJECT: 'Congratulations! You are now a Collaborator', - BODY: '{{User}} has added you as a collaborator for the ' + - '{{Content type}}: {{Content title}}. View this in {{Content link}}', + BODY: + '{{User}} has added you as a collaborator for the ' + + '{{Content type}}: {{Content title}}. View this in {{Content link}}', TEMPLATE: 'default' }, REMOVE_COLLABORATORS: { FAILED_CODE: 'ERR_SEND_REMOVE_COLLABORATORS_EMAIL', FAILED_MESSAGE: 'Sending email failed for removing collaborators', SUBJECT: 'Removed as Collaborator', - BODY: '{{User}} has removed you as a collaborator for the ' + - '{{Content type}}: {{Content title}}', + BODY: + '{{User}} has removed you as a collaborator for the ' + + '{{Content type}}: {{Content title}}', TEMPLATE: 'default' } } @@ -519,7 +521,6 @@ exports.DIALCODE = { FAILED_MESSAGE: 'Generate dialcode failed', MISSING_COUNT: 'ERR_DIALCODE_GENERATE_COUNT_ERROR', MISSING_COUNT_MESSAGE: 'Required fields count is missing or invalid' - }, LIST: { @@ -668,7 +669,8 @@ exports.PROGRAM = { }, LINK: { MISSING_CODE: 'ERR_LINKING_PROGRAM_TEXTBOOK', - MISSING_MESSAGE: 'Required fields while linking textbook to program are missing', + MISSING_MESSAGE: + 'Required fields while linking textbook to program are missing', FAILED_CODE: 'ERR_LINKING_TEXBOOK_FAILED', FAILED_MESSAGE: 'Unable to link textbook to program' }, @@ -686,38 +688,44 @@ exports.PROGRAM = { }, CONTENT_PUBLISH: { MISSING_CODE: 'ERR_CONTENT_PUBLISH', - MISSING_MESSAGE: 'Required fields like content_id or textbook_id or units missing', + MISSING_MESSAGE: + 'Required fields like content_id or textbook_id or units missing', FAILED_CODE: 'ERR_CONTENT_PUBLISH_FAILED', FAILED_MESSAGE: 'Unable to publish contnet' }, NOMINATION: { READ: { MISSING_CODE: 'ERR_GET_NOMINATION_DATA', - MISSING_MESSAGE: 'Required fields like program_id to get nomination are missing', + MISSING_MESSAGE: + 'Required fields like program_id to get nomination are missing', FAILED_CODE: 'ERR_GET_NOMINATION_DATA_FAILED', FAILED_MESSAGE: 'Unable to get the nomination data' }, CREATE: { MISSING_CODE: 'ERR_CREATE_NOMINATION_DATA', - MISSING_MESSAGE: 'Required fields like program_id, user_id, status for creating nomination data are missing', + MISSING_MESSAGE: + 'Required fields like program_id, user_id, status for creating nomination data are missing', FAILED_CODE: 'ERR_CREATE_NOMINATION_DATA_FAILED', FAILED_MESSAGE: 'Unable to create the nomination data' }, UPDATE: { MISSING_CODE: 'ERR_UPDATE_NOMINATION_DATA', - MISSING_MESSAGE: 'Required fields like program_id, user_id or organisation_id while updating nomination data are missing', + MISSING_MESSAGE: + 'Required fields like program_id, user_id or organisation_id while updating nomination data are missing', FAILED_CODE: 'ERR_UPDATE_NOMINATION_DATA_FAILED', FAILED_MESSAGE: 'Unable to update the nomination data' }, LIST: { MISSING_CODE: 'ERR_GET_NOMINATION_LIST', - MISSING_MESSAGE: 'Required fields like program_id/user_id to get nomination are missing', + MISSING_MESSAGE: + 'Required fields like program_id/user_id to get nomination are missing', FAILED_CODE: 'ERR_GET_NOMINATION_LIST_FAILED', FAILED_MESSAGE: 'Unable to get the nomination list' }, DOWNLOAD_LIST: { MISSING_CODE: 'ERR_DOWNLOADING_NOMINATION_DATA', - MISSING_MESSAGE: 'Required fields like program_id, program_name, status while getting nomination data are missing', + MISSING_MESSAGE: + 'Required fields like program_id, program_name, status while getting nomination data are missing', FAILED_CODE: 'ERR_DOWNLOADING_NOMINATION_DATA_FAILED', FAILED_MESSAGE: 'Unable to download the nomination data', QUERY_FAILED_MESSAGE: 'Unable to fetch query from DB', @@ -727,19 +735,22 @@ exports.PROGRAM = { PREFERENCES: { CREATE: { MISSING_CODE: 'ERR_CREATE_USER_PREFERENCE', - MISSING_MESSAGE: 'Required fields like user_id, program_id for adding user preferences are missing', + MISSING_MESSAGE: + 'Required fields like user_id, program_id for adding user preferences are missing', FAILED_CODE: 'ERR_CREATE_USER_PREFERENCE_FAILED', FAILED_MESSAGE: 'Unable to add user preferences' }, READ: { MISSING_CODE: 'ERR_GET_USER_PREFERENCE', - MISSING_MESSAGE: 'Required fields like user_id to get preference are missing', + MISSING_MESSAGE: + 'Required fields like user_id to get preference are missing', FAILED_CODE: 'ERR_GET_USER_PREFERENCE_FAILED', FAILED_MESSAGE: 'Unable to get the user preferences' }, UPDATE: { MISSING_CODE: 'ERR_GET_USER_PREFERENCE', - MISSING_MESSAGE: 'Required fields like user_id to get preference are missing', + MISSING_MESSAGE: + 'Required fields like user_id to get preference are missing', FAILED_CODE: 'ERR_UPDATE_USER_PREFERENCE_FAILED', FAILED_MESSAGE: 'Unable to update the user preferences' } @@ -747,7 +758,8 @@ exports.PROGRAM = { COPY_COLLECTION: { COPY: { MISSING_CODE: 'ERR_COPYING_COLLECTIONS', - MISSING_MESSAGE: 'Required fields like program_id, collections, allow_content_types, channel to copy textbook are missing', + MISSING_MESSAGE: + 'Required fields like program_id, collections, allow_content_types, channel to copy textbook are missing', FAILED_CODE: 'ERR_COPY_COLLECTIONS_FAILED', FAILED_MESSAGE: 'Unable to copy the collection' }, @@ -771,7 +783,8 @@ exports.PROGRAM = { PROGRAMCOUNTS_BYORG: { PROGRAMCOUNTS_FETCH: { MISSING_CODE: 'ERR_GETTING_COUNTS', - MISSING_MESSAGE: 'Error due to missing request or request.facets or request.facets.rootorg_id', + MISSING_MESSAGE: + 'Error due to missing request or request.facets or request.facets.rootorg_id', FAILED_CODE: 'ERR_GET_PROGRAMCOUNTS_FAILED', FAILED_MESSAGE: 'Error while fetching program count group by facets' }, @@ -792,7 +805,8 @@ exports.CONTENT_TYPE = { exports.CONFIGURATION = { SEARCH: { MISSING_CODE: 'ERR_SEARCHING_CONFIGURATION', - MISSING_MESSAGE: 'Required fields like key, status to search for configuration are missing', + MISSING_MESSAGE: + 'Required fields like key, status to search for configuration are missing' }, FETCH: { FAILED_CODE: 'ERR_GETTING_CONFIGURATION_FAILED', diff --git a/src/service/programService.js b/src/service/programService.js index 33780db7d2e93bb67350d749615664dacb3ac56e..0f8601dd85521d897c9261f8341aa3244b69a470 100644 --- a/src/service/programService.js +++ b/src/service/programService.js @@ -1,133 +1,147 @@ -const _ = require("lodash"); -const uuid = require("uuid/v1"); -const logger = require('sb_logger_util_v2'); -const SbCacheManager = require('sb_cache_manager'); -const messageUtils = require('./messageUtil'); -const respUtil = require('response_util'); -const Sequelize = require('sequelize'); -const responseCode = messageUtils.RESPONSE_CODE; -const programMessages = messageUtils.PROGRAM; -const contentTypeMessages = messageUtils.CONTENT_TYPE; -const configurationMessages = messageUtils.CONFIGURATION; -const model = require('../models'); -const { - forkJoin -} = require('rxjs'); -const { catchError , map } = require('rxjs/operators'); -const axios = require('axios'); -const envVariables = require('../envVariables'); +const _ = require('lodash') +const uuid = require('uuid/v1') +const logger = require('sb_logger_util_v2') +const SbCacheManager = require('sb_cache_manager') +const messageUtils = require('./messageUtil') +const Sequelize = require('sequelize') +const responseCode = messageUtils.RESPONSE_CODE +const programMessages = messageUtils.PROGRAM +const contentTypeMessages = messageUtils.CONTENT_TYPE +const configurationMessages = messageUtils.CONFIGURATION +const model = require('../models') +const { forkJoin } = require('rxjs') +const { catchError, map } = require('rxjs/operators') +const axios = require('axios') +const envVariables = require('../envVariables') const RegistryService = require('./registryService') -const ProgramServiceHelper = require('../helpers/programHelper'); -const RedisManager = require('../helpers/redisUtil') +const ProgramServiceHelper = require('../helpers/programHelper') const KafkaService = require('../helpers/kafkaUtil') const publishHelper = require('../helpers/publishHelper') var async = require('async') +const queryResMax = 1000 +const queryResMin = 300 +const HierarchyService = require('../helpers/updateHierarchy.helper') -const queryRes_Max = 1000; -const queryRes_Min = 300; -const HierarchyService = require('../helpers/updateHierarchy.helper'); - -const programServiceHelper = new ProgramServiceHelper(); -const cacheManager = new SbCacheManager({ttl: envVariables.CACHE_TTL}); -const cacheManager_programReport = new SbCacheManager({ttl: 86400}); +const programServiceHelper = new ProgramServiceHelper() +const cacheManager = new SbCacheManager({ ttl: envVariables.CACHE_TTL }) +const cacheManagerProgramReport = new SbCacheManager({ ttl: 86400 }) const registryService = new RegistryService() const hierarchyService = new HierarchyService() -function getProgram(req, response) { - model.program.findOne({ +function getProgram (req, response) { + model.program + .findOne({ where: { program_id: req.params.program_id } }) .then(function (res) { - return response.status(200).send(successResponse({ - apiId: 'api.program.read', - ver: '1.0', - msgid: uuid(), - responseCode: 'OK', - result: res - })) + return response.status(200).send( + successResponse({ + apiId: 'api.program.read', + ver: '1.0', + msgid: uuid(), + responseCode: 'OK', + result: res + }) + ) }) .catch(function (err) { - return response.status(400).send(errorResponse({ - apiId: 'api.program.read', - ver: '1.0', - msgid: uuid(), - responseCode: 'ERR_READ_PROGRAM', - result: err - })); - }); + return response.status(400).send( + errorResponse({ + apiId: 'api.program.read', + ver: '1.0', + msgid: uuid(), + responseCode: 'ERR_READ_PROGRAM', + result: err + }) + ) + }) } -async function createProgram(req, response) { +async function createProgram (req, response) { var data = req.body var rspObj = req.rspObj if (!data.request || !data.request.config || !data.request.type) { rspObj.errCode = programMessages.CREATE.MISSING_CODE rspObj.errMsg = programMessages.CREATE.MISSING_MESSAGE rspObj.responseCode = responseCode.CLIENT_ERROR - logger.error({ - msg: 'Error due to missing request or request config or request rootOrgId or request type', - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode + logger.error( + { + msg: + 'Error due to missing request or request config or request rootOrgId or request type', + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + }, + additionalInfo: { + data + } }, - additionalInfo: { - data - } - }, req) + req + ) return response.status(400).send(errorResponse(rspObj)) } - const insertObj = req.body.request; - insertObj.program_id = uuid(); - insertObj.config = insertObj.config ? JSON.stringify(insertObj.config) : ""; + const insertObj = req.body.request + insertObj.program_id = uuid() + insertObj.config = insertObj.config ? JSON.stringify(insertObj.config) : '' if (req.body.request.enddate) { insertObj.enddate = req.body.request.enddate } - model.program.create(insertObj).then(sc => { - console.log("Program successfully written to DB", sc); - return response.status(200).send(successResponse({ - apiId: 'api.program.create', - ver: '1.0', - msgid: uuid(), - responseCode: 'OK', - result: { - 'program_id': insertObj.program_id - } - })); - }).catch(err => { - console.log("Error adding Program to db", err); - return response.status(400).send(errorResponse({ - apiId: 'api.program.create', - ver: '1.0', - msgid: uuid(), - responseCode: 'ERR_CREATE_PROGRAM', - result: err - })); - }); + model.program + .create(insertObj) + .then((sc) => { + console.log('Program successfully written to DB', sc) + return response.status(200).send( + successResponse({ + apiId: 'api.program.create', + ver: '1.0', + msgid: uuid(), + responseCode: 'OK', + result: { + program_id: insertObj.program_id + } + }) + ) + }) + .catch((err) => { + console.log('Error adding Program to db', err) + return response.status(400).send( + errorResponse({ + apiId: 'api.program.create', + ver: '1.0', + msgid: uuid(), + responseCode: 'ERR_CREATE_PROGRAM', + result: err + }) + ) + }) } -function updateProgram(req, response) { +function updateProgram (req, response) { var data = req.body var rspObj = req.rspObj if (!data.request || !data.request.program_id) { rspObj.errCode = programMessages.UPDATE.MISSING_CODE rspObj.errMsg = programMessages.UPDATE.MISSING_MESSAGE rspObj.responseCode = responseCode.CLIENT_ERROR - logger.error({ - msg: 'Error due to missing request or request program_id', - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode + logger.error( + { + msg: 'Error due to missing request or request program_id', + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + }, + additionalInfo: { + data + } }, - additionalInfo: { - data - } - }, req) + req + ) return response.status(400).send(errorResponse(rspObj)) } const updateQuery = { @@ -136,146 +150,194 @@ function updateProgram(req, response) { }, returning: true, individualHooks: true - }; - const updateValue = _.cloneDeep(req.body.request); + } + const updateValue = _.cloneDeep(req.body.request) if (!updateValue.updatedon) { - updateValue.updatedon = new Date(); + updateValue.updatedon = new Date() } if (updateValue.config) { - updateValue.config = JSON.stringify(updateValue.config); + updateValue.config = JSON.stringify(updateValue.config) } - model.program.update(updateValue, updateQuery).then(resData => { - if (_.isArray(resData) && !resData[0]) { - return response.status(400).send(errorResponse({ - apiId: 'api.program.update', - ver: '1.0', - msgid: uuid(), - responseCode: 'ERR_UPDATE_PROGRAM', - result: 'Program_id Not Found' - })); - } - return response.status(200).send(successResponse({ - apiId: 'api.program.update', - ver: '1.0', - msgid: uuid(), - responseCode: 'OK', - result: { - 'program_id': updateQuery.where.program_id + model.program + .update(updateValue, updateQuery) + .then((resData) => { + if (_.isArray(resData) && !resData[0]) { + return response.status(400).send( + errorResponse({ + apiId: 'api.program.update', + ver: '1.0', + msgid: uuid(), + responseCode: 'ERR_UPDATE_PROGRAM', + result: 'Program_id Not Found' + }) + ) } - })); - }).catch(error => { - return response.status(400).send(errorResponse({ - apiId: 'api.program.update', - ver: '1.0', - msgid: uuid(), - responseCode: 'ERR_UPDATE_PROGRAM', - result: error - })); - }); + return response.status(200).send( + successResponse({ + apiId: 'api.program.update', + ver: '1.0', + msgid: uuid(), + responseCode: 'OK', + result: { + program_id: updateQuery.where.program_id + } + }) + ) + }) + .catch((error) => { + return response.status(400).send( + errorResponse({ + apiId: 'api.program.update', + ver: '1.0', + msgid: uuid(), + responseCode: 'ERR_UPDATE_PROGRAM', + result: error + }) + ) + }) } -async function deleteProgram(req, response) { +async function deleteProgram (req, response) { var data = req.body var rspObj = req.rspObj if (!data.request || !data.request.program_id) { rspObj.errCode = programMessages.READ.MISSING_CODE rspObj.errMsg = programMessages.READ.MISSING_MESSAGE rspObj.responseCode = responseCode.CLIENT_ERROR - logger.error({ - msg: 'Error due to missing request or request config or request rootOrgId or request type', - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode + logger.error( + { + msg: + 'Error due to missing request or request config or request rootOrgId or request type', + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + }, + additionalInfo: { + data + } }, - additionalInfo: { - data - } - }, req) + req + ) return response.status(400).send(errorResponse(rspObj)) } const deleteQuery = { program_id: req.body.request.program_id - }; - programDBModel.instance.program.deleteAsync(deleteQuery).then(resData => { - return response.status(200).send(successResponse({ - apiId: 'api.program.delete', - ver: '1.0', - msgid: uuid(), - responseCode: 'OK', - result: { - 'program_id': deleteQuery.program_id - } - })); - }).catch(error => { - console.log('ERRor in deleteAsync ', error); - return response.status(400).send(errorResponse({ - apiId: 'api.program.delete', - ver: '1.0', - msgid: uuid(), - responseCode: 'ERR_DELETE_PROGRAM', - result: error - })); - }); + } + // eslint-disable-next-line no-undef + model.program + .deleteAsync(deleteQuery) + .then((resData) => { + return response.status(200).send( + successResponse({ + apiId: 'api.program.delete', + ver: '1.0', + msgid: uuid(), + responseCode: 'OK', + result: { + program_id: deleteQuery.program_id + } + }) + ) + }) + .catch((error) => { + console.log('ERRor in deleteAsync ', error) + return response.status(400).send( + errorResponse({ + apiId: 'api.program.delete', + ver: '1.0', + msgid: uuid(), + responseCode: 'ERR_DELETE_PROGRAM', + result: error + }) + ) + }) } -function getProgramCountsByOrg(req, response) { +function getProgramCountsByOrg (req, response) { var data = req.body var rspObj = req.rspObj - rspObj.errCode = programMessages.PROGRAMCOUNTS_BYORG.PROGRAMCOUNTS_FETCH.FAILED_CODE - rspObj.errMsg = programMessages.PROGRAMCOUNTS_BYORG.PROGRAMCOUNTS_FETCH.FAILED_MESSAGE - rspObj.responseCode = ''; - - const findQuery = (data.request && data.request.filters) ? data.request.filters : {} - const facets = ["rootorg_id"]; - model.program.findAll({ - where: { - ...findQuery - }, - attributes: [...facets, [Sequelize.fn('count', Sequelize.col(facets[0])), 'count']], - group: [...facets] - }).then((result) => { - const apiRes = _.keyBy(_.map(result, 'dataValues'), 'rootorg_id'); + rspObj.errCode = + programMessages.PROGRAMCOUNTS_BYORG.PROGRAMCOUNTS_FETCH.FAILED_CODE + rspObj.errMsg = + programMessages.PROGRAMCOUNTS_BYORG.PROGRAMCOUNTS_FETCH.FAILED_MESSAGE + rspObj.responseCode = '' + + const findQuery = + data.request && data.request.filters ? data.request.filters : {} + const facets = ['rootorg_id'] + model.program + .findAll({ + where: { + ...findQuery + }, + attributes: [ + ...facets, + [Sequelize.fn('count', Sequelize.col(facets[0])), 'count'] + ], + group: [...facets] + }) + .then((result) => { + const apiRes = _.keyBy(_.map(result, 'dataValues'), 'rootorg_id') - const orgIds = _.map(apiRes, 'rootorg_id'); + const orgIds = _.map(apiRes, 'rootorg_id') if (_.isEmpty(result) || _.isEmpty(orgIds)) { - return response.status(200).send(successResponse(rspObj)); + return response.status(200).send(successResponse(rspObj)) } - getOrganisationDetails(req, orgIds).then((orgData) => { - _.forEach(orgData.data.result.response.content, function(el, index){ - el.program_count = apiRes[el.id].count; - }); - rspObj.result = orgData.data.result.response; - return response.status(200).send(successResponse(rspObj)); - }, (error) => { - rspObj.responseCode = responseCode.SERVER_ERROR - rspObj.errCode = programMessages.PROGRAMCOUNTS_BYORG.ORGSEARCH.FAILED_CODE - rspObj.errMsg = programMessages.PROGRAMCOUNTS_BYORG.ORGSEARCH.FAILED_MESSAGE - loggerError(rspObj.errMsg, rspObj.errCode, rspObj.errMsg, error.response.data.responseCode, data, req) - rspObj.result = err; - return response.status(400).send(errorResponse(rspObj)); - }) - }).catch((err) => { - rspObj.responseCode = responseCode.SERVER_ERROR - loggerError('Error fetching program count group by facets', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, err, req); - return response.status(400).send(errorResponse(rspObj)); - }); + getOrganisationDetails(req, orgIds).then( + (orgData) => { + _.forEach(orgData.data.result.response.content, function (el, index) { + el.program_count = apiRes[el.id].count + }) + rspObj.result = orgData.data.result.response + return response.status(200).send(successResponse(rspObj)) + }, + (error) => { + rspObj.responseCode = responseCode.SERVER_ERROR + rspObj.errCode = + programMessages.PROGRAMCOUNTS_BYORG.ORGSEARCH.FAILED_CODE + rspObj.errMsg = + programMessages.PROGRAMCOUNTS_BYORG.ORGSEARCH.FAILED_MESSAGE + loggerError( + rspObj.errMsg, + rspObj.errCode, + rspObj.errMsg, + error.response.data.responseCode, + data, + req + ) + rspObj.result = error + return response.status(400).send(errorResponse(rspObj)) + } + ) + }) + .catch((err) => { + rspObj.responseCode = responseCode.SERVER_ERROR + loggerError( + 'Error fetching program count group by facets', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + err, + req + ) + return response.status(400).send(errorResponse(rspObj)) + }) } - /* Get the org details by filters*/ - function getOrganisationDetails(req, orgList) { - const url = `${envVariables.baseURL}/api/org/v1/search`; +/* Get the org details by filters */ +function getOrganisationDetails (req, orgList) { + const url = `${envVariables.baseURL}/api/org/v1/search` const reqData = { - "request": { - "filters": { - "id": orgList, - "status": 1, - "isRootOrg": true + request: { + filters: { + id: orgList, + status: 1, + isRootOrg: true }, - "fields": ["id", "slug", "orgName", "orgCode", "imgUrl"] + fields: ['id', 'slug', 'orgName', 'orgCode', 'imgUrl'] } } return axios({ @@ -283,230 +345,277 @@ function getProgramCountsByOrg(req, response) { url: url, headers: req.headers, data: reqData - }); + }) } -function programList(req, response) { +function programList (req, response) { var data = req.body var rspObj = req.rspObj - var res_limit = queryRes_Min; - var res_offset = data.request.offset || 0; + var resLimit = queryResMin + var resOffset = data.request.offset || 0 if (!data.request || !data.request.filters) { rspObj.errCode = programMessages.READ.MISSING_CODE rspObj.errMsg = programMessages.READ.MISSING_MESSAGE rspObj.responseCode = responseCode.CLIENT_ERROR - logger.error({ - msg: 'Error due to missing request or request.filters', - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode + logger.error( + { + msg: 'Error due to missing request or request.filters', + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + }, + additionalInfo: { + data + } }, - additionalInfo: { - data - } - }, req) + req + ) return response.status(400).send(errorResponse(rspObj)) } if (data.request.limit) { - res_limit = (data.request.limit < queryRes_Max) ? data.request.limit : (queryRes_Max); + resLimit = + data.request.limit < queryResMax ? data.request.limit : queryResMax } - + if (data.request.filters && data.request.filters.enrolled_id) { if (!data.request.filters.enrolled_id.user_id) { rspObj.errCode = programMessages.READ.MISSING_CODE rspObj.errMsg = programMessages.READ.MISSING_MESSAGE rspObj.responseCode = responseCode.CLIENT_ERROR - logger.error({ - msg: 'Error due to missing request.filters.enrolled_id.user_id', - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode + logger.error( + { + msg: 'Error due to missing request.filters.enrolled_id.user_id', + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + }, + additionalInfo: { + data + } }, - additionalInfo: { - data - } - }, req) + req + ) return response.status(400).send(errorResponse(rspObj)) } - model.nomination.findAndCountAll({ + model.nomination + .findAndCountAll({ where: { user_id: data.request.filters.enrolled_id.user_id }, - offset: res_offset, - limit: res_limit, - include: [{ - model: model.program - }], - order: [ - ['updatedon', 'DESC'] - ] - }) - .then((prg_list) => { - return response.status(200).send(successResponse({ - apiId: 'api.program.list', - ver: '1.0', - msgid: uuid(), - responseCode: 'OK', - result: { - count: prg_list.count, - programs: prg_list.rows + offset: resOffset, + limit: resLimit, + include: [ + { + model: model.program } - })) + ], + order: [['updatedon', 'DESC']] + }) + .then((prgList) => { + return response.status(200).send( + successResponse({ + apiId: 'api.program.list', + ver: '1.0', + msgid: uuid(), + responseCode: 'OK', + result: { + count: prgList.count, + programs: prgList.rows + } + }) + ) }) .catch(function (err) { - return response.status(400).send(errorResponse({ - apiId: 'api.program.list', - ver: '1.0', - msgid: uuid(), - responseCode: 'ERR_LIST_PROGRAM', - result: err - })); - }); - } else if (data.request.filters && data.request.filters.role && data.request.filters.user_id) { - const promises = []; + return response.status(400).send( + errorResponse({ + apiId: 'api.program.list', + ver: '1.0', + msgid: uuid(), + responseCode: 'ERR_LIST_PROGRAM', + result: err + }) + ) + }) + } else if ( + data.request.filters && + data.request.filters.role && + data.request.filters.user_id + ) { + const promises = [] _.forEach(data.request.filters.role, (role) => { - promises.push( + promises.push( model.program.findAndCountAll({ - where:{ - $contains: Sequelize.literal(`cast(rolemapping->>'${role}' as text) like ('%${data.request.filters.user_id}%')`) - }, - offset: res_offset, - limit: res_limit, - order: [ - ['updatedon', 'DESC'] - ] - }) + where: { + $contains: Sequelize.literal( + `cast(rolemapping->>'${role}' as text) like ('%${data.request.filters.user_id}%')` + ) + }, + offset: resOffset, + limit: resLimit, + order: [['updatedon', 'DESC']] + }) ) }) Promise.all(promises) - .then(function (res) { - let aggregatedRes = []; - _.forEach(res, (response) => { - _.forEach(response.rows, row => aggregatedRes.push(row)); + .then(function (res) { + let aggregatedRes = [] + _.forEach(res, (response) => { + _.forEach(response.rows, (row) => aggregatedRes.push(row)) + }) + aggregatedRes = _.uniqBy(aggregatedRes, 'dataValues.program_id') + return response.status(200).send( + successResponse({ + apiId: 'api.program.list', + ver: '1.0', + msgid: uuid(), + responseCode: 'OK', + result: { + count: aggregatedRes.length, + programs: aggregatedRes + } + }) + ) + }) + .catch(function (err) { + return response.status(400).send( + errorResponse({ + apiId: 'api.program.list', + ver: '1.0', + msgid: uuid(), + responseCode: 'ERR_LIST_PROGRAM', + result: err + }) + ) }) - aggregatedRes = _.uniqBy(aggregatedRes, 'dataValues.program_id'); - return response.status(200).send(successResponse({ - apiId: 'api.program.list', - ver: '1.0', - msgid: uuid(), - responseCode: 'OK', - result: { - count: aggregatedRes.length, - programs: aggregatedRes - } - })) - }) - .catch(function (err) { - return response.status(400).send(errorResponse({ - apiId: 'api.program.list', - ver: '1.0', - msgid: uuid(), - responseCode: 'ERR_LIST_PROGRAM', - result: err - })); - }); } else { - model.program.findAndCountAll({ + model.program + .findAndCountAll({ where: { ...data.request.filters }, - offset: res_offset, - limit: res_limit, - order: [ - ['updatedon', 'DESC'] - ] + offset: resOffset, + limit: resLimit, + order: [['updatedon', 'DESC']] }) .then(function (res) { - return response.status(200).send(successResponse({ - apiId: 'api.program.list', - ver: '1.0', - msgid: uuid(), - responseCode: 'OK', - result: { - count: res.count, - programs: res.rows - } - })) + return response.status(200).send( + successResponse({ + apiId: 'api.program.list', + ver: '1.0', + msgid: uuid(), + responseCode: 'OK', + result: { + count: res.count, + programs: res.rows + } + }) + ) }) .catch(function (err) { - return response.status(400).send(errorResponse({ - apiId: 'api.program.list', - ver: '1.0', - msgid: uuid(), - responseCode: 'ERR_LIST_PROGRAM', - result: err - })); - }); + return response.status(400).send( + errorResponse({ + apiId: 'api.program.list', + ver: '1.0', + msgid: uuid(), + responseCode: 'ERR_LIST_PROGRAM', + result: err + }) + ) + }) } } -function addNomination(req, response) { +function addNomination (req, response) { var data = req.body var rspObj = req.rspObj - if (!data.request || !data.request.program_id || !data.request.user_id || !data.request.status) { + if ( + !data.request || + !data.request.program_id || + !data.request.user_id || + !data.request.status + ) { rspObj.errCode = programMessages.NOMINATION.CREATE.MISSING_CODE rspObj.errMsg = programMessages.NOMINATION.CREATE.MISSING_MESSAGE rspObj.responseCode = responseCode.CLIENT_ERROR - logger.error({ - msg: 'Error due to missing request or request program_id or request user_id or request status', - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode + logger.error( + { + msg: + 'Error due to missing request or request program_id or request user_id or request status', + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + }, + additionalInfo: { + data + } }, - additionalInfo: { - data - } - }, req) + req + ) return response.status(400).send(errorResponse(rspObj)) } - const insertObj = req.body.request; - - model.nomination.create(insertObj).then(res => { - console.log("nomination successfully written to DB", res); - return response.status(200).send(successResponse({ - apiId: 'api.nomination.add', - ver: '1.0', - msgid: uuid(), - responseCode: 'OK', - result: { - 'program_id': insertObj.program_id, - 'user_id': insertObj.user_id, - 'id': res.dataValues.id - } - })); - }).catch(err => { - console.log("Error adding nomination to db", err); - return response.status(400).send(errorResponse({ - apiId: 'api.nomination.add', - ver: '1.0', - msgid: uuid(), - responseCode: 'ERR_CREATE_PROGRAM', - result: err - })); - }); + const insertObj = req.body.request + + model.nomination + .create(insertObj) + .then((res) => { + console.log('nomination successfully written to DB', res) + return response.status(200).send( + successResponse({ + apiId: 'api.nomination.add', + ver: '1.0', + msgid: uuid(), + responseCode: 'OK', + result: { + program_id: insertObj.program_id, + user_id: insertObj.user_id, + id: res.dataValues.id + } + }) + ) + }) + .catch((err) => { + console.log('Error adding nomination to db', err) + return response.status(400).send( + errorResponse({ + apiId: 'api.nomination.add', + ver: '1.0', + msgid: uuid(), + responseCode: 'ERR_CREATE_PROGRAM', + result: err + }) + ) + }) } -function updateNomination(req, response) { +function updateNomination (req, response) { var data = req.body var rspObj = req.rspObj - if (!data.request || !data.request.program_id || !(data.request.user_id || data.request.organisation_id)) { + if ( + !data.request || + !data.request.program_id || + !(data.request.user_id || data.request.organisation_id) + ) { rspObj.errCode = programMessages.NOMINATION.UPDATE.MISSING_CODE rspObj.errMsg = programMessages.NOMINATION.UPDATE.MISSING_MESSAGE rspObj.responseCode = responseCode.CLIENT_ERROR - logger.error({ - msg: 'Error due to missing request and request program_id and request user_id or organisation_id', - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode + logger.error( + { + msg: + 'Error due to missing request and request program_id and request user_id or organisation_id', + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + }, + additionalInfo: { + data + } }, - additionalInfo: { - data - } - }, req) + req + ) return response.status(400).send(errorResponse(rspObj)) } const updateQuery = { @@ -515,388 +624,585 @@ function updateNomination(req, response) { }, returning: true, individualHooks: true - }; - if(data.request.user_id){ + } + if (data.request.user_id) { updateQuery.where.user_id = data.request.user_id } - if(data.request.organisation_id){ + if (data.request.organisation_id) { updateQuery.where.organisation_id = data.request.organisation_id } - if(data.request.id){ - updateQuery.where.id = data.request.id + if (data.request.id) { + updateQuery.where.id = data.request.id } - var updateValue = req.body.request; + var updateValue = req.body.request updateValue = _.omit(updateValue, [ - "id", - "program_id", - "user_id", - "organisation_id" - ]); - updateValue.updatedon = new Date(); - model.nomination.update(updateValue, updateQuery).then(res => { - if (_.isArray(res) && !res[0]) { - return response.status(400).send(errorResponse({ - apiId: 'api.nomination.update', - ver: '1.0', - msgid: uuid(), - responseCode: 'ERR_UPDATE_NOMINATION', - result: 'Nomination Not Found' - })); - } - const successRes = { - program_id: updateQuery.where.program_id, - }; - if(updateQuery.where.user_id){ - successRes.user_id = updateQuery.where.user_id - } - if(updateQuery.where.organisation_id){ - successRes.organisation_id = updateQuery.where.organisation_id - } + 'id', + 'program_id', + 'user_id', + 'organisation_id' + ]) + updateValue.updatedon = new Date() + model.nomination + .update(updateValue, updateQuery) + .then((res) => { + if (_.isArray(res) && !res[0]) { + return response.status(400).send( + errorResponse({ + apiId: 'api.nomination.update', + ver: '1.0', + msgid: uuid(), + responseCode: 'ERR_UPDATE_NOMINATION', + result: 'Nomination Not Found' + }) + ) + } + const successRes = { + program_id: updateQuery.where.program_id + } + if (updateQuery.where.user_id) { + successRes.user_id = updateQuery.where.user_id + } + if (updateQuery.where.organisation_id) { + successRes.organisation_id = updateQuery.where.organisation_id + } - return response.status(200).send(successResponse({ - apiId: 'api.nomination.update', - ver: '1.0', - msgid: uuid(), - responseCode: 'OK', - result: successRes - })); - }).catch(err => { - console.log("Error updating nomination to db", err); - return response.status(400).send(errorResponse({ - apiId: 'api.nomination.update', - ver: '1.0', - msgid: uuid(), - responseCode: 'ERR_UPDATE_NOMINATION', - result: err - })); - }); + return response.status(200).send( + successResponse({ + apiId: 'api.nomination.update', + ver: '1.0', + msgid: uuid(), + responseCode: 'OK', + result: successRes + }) + ) + }) + .catch((err) => { + console.log('Error updating nomination to db', err) + return response.status(400).send( + errorResponse({ + apiId: 'api.nomination.update', + ver: '1.0', + msgid: uuid(), + responseCode: 'ERR_UPDATE_NOMINATION', + result: err + }) + ) + }) } -function removeNomination(req, response) { +function removeNomination (req, response) { console.log(req) } -function getNominationsList(req, response) { - var data = req.body; - var rspObj = req.rspObj; - var res_limit = queryRes_Min; - var res_offset = data.request.offset || 0; +function getNominationsList (req, response) { + var data = req.body + var rspObj = req.rspObj + var resLimit = queryResMin + var resOffset = data.request.offset || 0 rspObj.errCode = programMessages.NOMINATION.LIST.FAILED_CODE rspObj.errMsg = programMessages.NOMINATION.LIST.FAILED_MESSAGE rspObj.responseCode = responseCode.SERVER_ERROR if (data.request.limit) { - res_limit = (data.request.limit < queryRes_Max) ? data.request.limit : (queryRes_Max); + resLimit = + data.request.limit < queryResMax ? data.request.limit : queryResMax } const findQuery = data.request.filters ? data.request.filters : {} if (data.request.facets) { - const facets = data.request.facets; - model.nomination.findAll({ - where: { - ...findQuery - }, - attributes: [...facets, [Sequelize.fn('count', Sequelize.col(facets[0])), 'count']], - group: [...facets] - }).then((result) => { - return response.status(200).send(successResponse({ - apiId: 'api.nomination.list', - ver: '1.0', - msgid: uuid(), - responseCode: 'OK', - result: result - })) - }).catch((err) => { - loggerError('Error fetching nomination count group by facets', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, err, req); - return response.status(400).send(errorResponse(rspObj)); - }) - }else if (data.request.limit === 0) { - model.nomination.findAll({ - where: { - ...findQuery - }, - attributes: [...data.request.fields || []] - }).then(async (result) => { - let aggregatedRes = await aggregatedNominationCount(data, result); - - return response.status(200).send(successResponse({ - apiId: 'api.nomination.list', - ver: '1.0', - msgid: uuid(), - responseCode: 'OK', - result: aggregatedRes - })) - }).catch((err) => { - loggerError('Error fetching nomination count when limit = 0', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, err, req); - return response.status(400).send(errorResponse(rspObj)); - }) - } else { - model.nomination.findAll({ - where: { - ...findQuery - }, - offset: res_offset, - limit: res_limit, - order: [ - ['updatedon', 'DESC'] - ] - }).then(async function (result) { - try { - var userList = []; - var orgList = []; - _.forEach(result, function (data) { - userList.push(data.user_id); - - if (data.organisation_id) { - orgList.push(data.organisation_id); - } - }) - if (_.isEmpty(userList)) { - return response.status(200).send(successResponse({ + const facets = data.request.facets + model.nomination + .findAll({ + where: { + ...findQuery + }, + attributes: [ + ...facets, + [Sequelize.fn('count', Sequelize.col(facets[0])), 'count'] + ], + group: [...facets] + }) + .then((result) => { + return response.status(200).send( + successResponse({ apiId: 'api.nomination.list', ver: '1.0', msgid: uuid(), responseCode: 'OK', result: result - })) - } - - forkJoin(getUsersDetails(req, userList), getOrgDetails(req, orgList)).subscribe((resData) => { - _.forEach(resData, function (data) { - if (data.data.result && !_.isEmpty(_.get(data, 'data.result.User'))) { - _.forEach(data.data.result.User, (userData) => { - const index = _.indexOf(_.map(result, 'user_id'), userData.userId) - if (index !== -1) { - result[index].dataValues.userData = userData; - } - }) - } - if (data.data.result && !_.isEmpty(_.get(data, 'data.result.Org'))) { - _.forEach(data.data.result.Org, (orgData) => { - const index = _.indexOf(_.map(result, 'organisation_id'), orgData.osid) - if (index !== -1) { - result[index].dataValues.orgData = orgData; - } - }) - } - }); + }) + ) + }) + .catch((err) => { + loggerError( + 'Error fetching nomination count group by facets', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + err, + req + ) + return response.status(400).send(errorResponse(rspObj)) + }) + } else if (data.request.limit === 0) { + model.nomination + .findAll({ + where: { + ...findQuery + }, + attributes: [...(data.request.fields || [])] + }) + .then(async (result) => { + const aggregatedRes = await aggregatedNominationCount(data, result) - return response.status(200).send(successResponse({ + return response.status(200).send( + successResponse({ apiId: 'api.nomination.list', ver: '1.0', msgid: uuid(), responseCode: 'OK', - result: result - })) - }, (error) => { - loggerError('Error in fetching user/org details', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, error, req); - return response.status(400).send(errorResponse(rspObj)); - }); - } catch (err) { - loggerError('Error fetching nomination with limit and offset', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, err, req); - return response.status(400).send(errorResponse(rspObj)); - } - }).catch(function (err) { - loggerError('Error fetching nomination with limit and offset', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, err, req); - return response.status(400).send(errorResponse(rspObj)); - }); + result: aggregatedRes + }) + ) + }) + .catch((err) => { + loggerError( + 'Error fetching nomination count when limit = 0', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + err, + req + ) + return response.status(400).send(errorResponse(rspObj)) + }) + } else { + model.nomination + .findAll({ + where: { + ...findQuery + }, + offset: resOffset, + limit: resLimit, + order: [['updatedon', 'DESC']] + }) + .then(async function (result) { + try { + var userList = [] + var orgList = [] + _.forEach(result, function (data) { + userList.push(data.user_id) + + if (data.organisation_id) { + orgList.push(data.organisation_id) + } + }) + if (_.isEmpty(userList)) { + return response.status(200).send( + successResponse({ + apiId: 'api.nomination.list', + ver: '1.0', + msgid: uuid(), + responseCode: 'OK', + result: result + }) + ) + } + + forkJoin( + getUsersDetails(req, userList), + getOrgDetails(req, orgList) + ).subscribe( + (resData) => { + _.forEach(resData, function (data) { + if ( + data.data.result && + !_.isEmpty(_.get(data, 'data.result.User')) + ) { + _.forEach(data.data.result.User, (userData) => { + const index = _.indexOf( + _.map(result, 'user_id'), + userData.userId + ) + if (index !== -1) { + result[index].dataValues.userData = userData + } + }) + } + if ( + data.data.result && + !_.isEmpty(_.get(data, 'data.result.Org')) + ) { + _.forEach(data.data.result.Org, (orgData) => { + const index = _.indexOf( + _.map(result, 'organisation_id'), + orgData.osid + ) + if (index !== -1) { + result[index].dataValues.orgData = orgData + } + }) + } + }) + + return response.status(200).send( + successResponse({ + apiId: 'api.nomination.list', + ver: '1.0', + msgid: uuid(), + responseCode: 'OK', + result: result + }) + ) + }, + (error) => { + loggerError( + 'Error in fetching user/org details', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + error, + req + ) + return response.status(400).send(errorResponse(rspObj)) + } + ) + } catch (err) { + loggerError( + 'Error fetching nomination with limit and offset', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + err, + req + ) + return response.status(400).send(errorResponse(rspObj)) + } + }) + .catch(function (err) { + loggerError( + 'Error fetching nomination with limit and offset', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + err, + req + ) + return response.status(400).send(errorResponse(rspObj)) + }) } } -async function downloadProgramDetails(req, res) { +async function downloadProgramDetails (req, res) { const data = req.body const rspObj = req.rspObj - let programArr = [], promiseRequests = [], cacheData = [], filteredPrograms = []; + let programArr = [] + let promiseRequests = [] + const cacheData = [] + const filteredPrograms = [] rspObj.errCode = programMessages.GENERATE_DETAILS.FAILED_CODE rspObj.errMsg = programMessages.GENERATE_DETAILS.FAILED_MESSAGE rspObj.responseCode = responseCode.SERVER_ERROR - if (!data.request || !data.request.filters || !data.request.filters.program_id) { + if ( + !data.request || + !data.request.filters || + !data.request.filters.program_id + ) { rspObj.errCode = programMessages.GENERATE_DETAILS.MISSING_CODE rspObj.errMsg = programMessages.GENERATE_DETAILS.MISSING_MESSAGE rspObj.responseCode = responseCode.CLIENT_ERROR - loggerError('Error due to missing request or request.filters or request.filters.program_id', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, null, req) - return res.status(400).send(errorResponse(rspObj)); + loggerError( + 'Error due to missing request or request.filters or request.filters.program_id', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + null, + req + ) + return res.status(400).send(errorResponse(rspObj)) } - programArr = _.isArray(data.request.filters.program_id) ? data.request.filters.program_id : []; + programArr = _.isArray(data.request.filters.program_id) + ? data.request.filters.program_id + : [] await _.forEach(programArr, (program) => { cacheManager.get(`program_details_${program}`, (err, cache) => { if (err || !cache) { - filteredPrograms.push(program); + filteredPrograms.push(program) } else { - cacheData.push(cache); + cacheData.push(cache) } - }); - }); - + }) + }) + if (filteredPrograms.length) { - promiseRequests = _.map(filteredPrograms, (program) => { - return [programServiceHelper.getCollectionWithProgramId(program, req), programServiceHelper.getSampleContentWithProgramId(program, req), - programServiceHelper.getContributionWithProgramId(program, req), programServiceHelper.getNominationWithProgramId(program)]; - }); - - forkJoin(..._.flatMapDeep(promiseRequests)).subscribe((responseData) => { - try{ - const combainedRes = _.chunk(responseData, 4); - const programDetailsArray = programServiceHelper.handleMultiProgramDetails(combainedRes); - const tableData = _.reduce(programDetailsArray, (final, data, index) => { - final.push({program_id: filteredPrograms[index], values: data}); - return final; - }, []); - _.forEach(tableData, (obj) => { - cacheManager.set({ key: `program_details_${obj.program_id}`, value: obj }, - function (err, cacheCSVData) { - if (err) { - logger.error({msg: 'Error - caching', err, additionalInfo: {programDetails: obj}}, req) - } else { - logger.debug({msg: 'Caching nomination list - done', additionalInfo: {nominationData: obj}}, req) + promiseRequests = _.map(filteredPrograms, (program) => { + return [ + programServiceHelper.getCollectionWithProgramId(program, req), + programServiceHelper.getSampleContentWithProgramId(program, req), + programServiceHelper.getContributionWithProgramId(program, req), + programServiceHelper.getNominationWithProgramId(program) + ] + }) + + forkJoin(..._.flatMapDeep(promiseRequests)).subscribe( + (responseData) => { + try { + const combainedRes = _.chunk(responseData, 4) + const programDetailsArray = programServiceHelper.handleMultiProgramDetails( + combainedRes + ) + const tableData = _.reduce( + programDetailsArray, + (final, data, index) => { + final.push({ program_id: filteredPrograms[index], values: data }) + return final + }, + [] + ) + _.forEach(tableData, (obj) => { + cacheManager.set( + { key: `program_details_${obj.program_id}`, value: obj }, + function (err, cacheCSVData) { + if (err) { + logger.error( + { + msg: 'Error - caching', + err, + additionalInfo: { programDetails: obj } + }, + req + ) + } else { + logger.debug( + { + msg: 'Caching nomination list - done', + additionalInfo: { nominationData: obj } + }, + req + ) + } + } + ) + }) + rspObj.result = { + tableData: [...tableData, ...cacheData] + } + rspObj.responseCode = 'OK' + return res.status(200).send(successResponse(rspObj)) + } catch (err) { + loggerError( + 'Error due to unhandled exception', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + err, + req + ) + return res.status(400).send(errorResponse(rspObj)) } - }); - }); - rspObj.result = { - tableData: [...tableData, ...cacheData] - } - rspObj.responseCode = 'OK' - return res.status(200).send(successResponse(rspObj)); - } catch (err) { - loggerError('Error due to unhandled exception', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, err, req) - return res.status(400).send(errorResponse(rspObj)); - } - }, (err) => { - loggerError('Error http requests or nomination table query promise failure', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, err, req) - return res.status(400).send(errorResponse(rspObj)); - }); - }else { + }, + (err) => { + loggerError( + 'Error http requests or nomination table query promise failure', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + err, + req + ) + return res.status(400).send(errorResponse(rspObj)) + } + ) + } else { rspObj.result = { tableData: [...cacheData] } rspObj.responseCode = 'OK' - return res.status(200).send(successResponse(rspObj)); + return res.status(200).send(successResponse(rspObj)) } } -function aggregatedNominationCount(data, result) { +function aggregatedNominationCount (data, result) { return new Promise((resolve, reject) => { try { - let aggregatedRes = {} - aggregatedRes['nomination'] = { count: result.length } - const groupData = _.reduce(result, (final, instance) => { - _.forEach(data.request.fields, (field) => { - field !== 'status' ? - final[field] = _.compact(_.uniq(_.flattenDeep([...final[field] || [], instance[field]]))) : - final[field] = [...final[field] || [], instance[field]]; - }); - return final; - }, {}); - aggregatedRes.nomination['fields'] = _.map(data.request.fields, (field) => { - const obj = {name: field}; - if (field === 'status') { - obj['fields'] = {} - const temp = _.groupBy(groupData[field]); - _.mapKeys(temp, (val, key) => { - obj.fields[key] = val.length - }) - }else { - obj['count'] = groupData[field].length; - } - return obj; - }) - resolve(aggregatedRes); - } catch(err) { - reject(err); - } - }) - } - - function downloadNominationList(req, response) { - var data = req.body; - var rspObj = req.rspObj; - rspObj.errCode = programMessages.NOMINATION.DOWNLOAD_LIST.MISSING_CODE; - rspObj.errMsg = programMessages.NOMINATION.DOWNLOAD_LIST.MISSING_MESSAGE; - rspObj.responseCode = responseCode.CLIENT_ERROR; - if(!data || !data.request || !data.request.filters || !data.request.filters.program_id || !data.request.filters.program_name || !data.request.filters.status) { - loggerError('Error due to missing request or program_id, status or program_name', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, null, req) - return response.status(400).send(errorResponse(rspObj)) - } - const reqHeaders = req.headers; - const findQuery = data.request.filters ? data.request.filters : {}; - cacheManager.get(findQuery.program_id, (err, cacheData) => { - if(err || !cacheData) { - model.nomination.findAll({ - where: { - ..._.omit(findQuery, ["program_name"]) + const aggregatedRes = {} + aggregatedRes.nomination = { count: result.length } + const groupData = _.reduce( + result, + (final, instance) => { + _.forEach(data.request.fields, (field) => { + field !== 'status' + ? (final[field] = _.compact( + _.uniq( + _.flattenDeep([...(final[field] || []), instance[field]]) + ) + )) + : (final[field] = [...(final[field] || []), instance[field]]) + }) + return final }, - offset: 0, - limit: 1000, - order: [ - ['updatedon', 'DESC'] - ] - }).then((result) => { - try { - let userList = []; - let orgList = []; - let relatedContents = []; - let nominationSampleCounts = {}; - _.forEach(result, r => { - userList.push(r.user_id); - if(r.organisation_id) { - orgList.push(r.organisation_id); - } + {} + ) + aggregatedRes.nomination.fields = _.map(data.request.fields, (field) => { + const obj = { name: field } + if (field === 'status') { + obj.fields = {} + const temp = _.groupBy(groupData[field]) + _.mapKeys(temp, (val, key) => { + obj.fields[key] = val.length }) - if(_.isEmpty(userList)) { - rspObj.result = { - stats: [] + } else { + obj.count = groupData[field].length + } + return obj + }) + resolve(aggregatedRes) + } catch (err) { + reject(err) + } + }) +} + +function downloadNominationList (req, response) { + var data = req.body + var rspObj = req.rspObj + rspObj.errCode = programMessages.NOMINATION.DOWNLOAD_LIST.MISSING_CODE + rspObj.errMsg = programMessages.NOMINATION.DOWNLOAD_LIST.MISSING_MESSAGE + rspObj.responseCode = responseCode.CLIENT_ERROR + if ( + !data || + !data.request || + !data.request.filters || + !data.request.filters.program_id || + !data.request.filters.program_name || + !data.request.filters.status + ) { + loggerError( + 'Error due to missing request or program_id, status or program_name', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + null, + req + ) + return response.status(400).send(errorResponse(rspObj)) + } + const reqHeaders = req.headers + const findQuery = data.request.filters ? data.request.filters : {} + cacheManager.get(findQuery.program_id, (err, cacheData) => { + if (err || !cacheData) { + model.nomination + .findAll({ + where: { + ..._.omit(findQuery, ['program_name']) + }, + offset: 0, + limit: 1000, + order: [['updatedon', 'DESC']] + }) + .then((result) => { + try { + const userList = [] + const orgList = [] + let relatedContents = [] + let nominationSampleCounts = {} + _.forEach(result, (r) => { + userList.push(r.user_id) + if (r.organisation_id) { + orgList.push(r.organisation_id) + } + }) + if (_.isEmpty(userList)) { + rspObj.result = { + stats: [] + } + rspObj.responseCode = 'OK' + return response.status(200).send(successResponse(rspObj)) } - rspObj.responseCode = 'OK' - return response.status(200).send(successResponse(rspObj)) - } - forkJoin(programServiceHelper.searchContent(findQuery.program_id, true, reqHeaders), - getUsersDetails(req, userList), getOrgDetails(req, orgList)) - .subscribe( + forkJoin( + programServiceHelper.searchContent( + findQuery.program_id, + true, + reqHeaders + ), + getUsersDetails(req, userList), + getOrgDetails(req, orgList) + ).subscribe( (promiseData) => { - const contentResult = _.first(promiseData); - if (contentResult && contentResult.data && contentResult.data.result && contentResult.data.result.content) { - const contents = _.get(contentResult, 'data.result.content'); - relatedContents = contents; + const contentResult = _.first(promiseData) + if ( + contentResult && + contentResult.data && + contentResult.data.result && + contentResult.data.result.content + ) { + const contents = _.get(contentResult, 'data.result.content') + relatedContents = contents } - nominationSampleCounts = programServiceHelper.setNominationSampleCounts(relatedContents); - const userAndOrgResult = _.tail(promiseData, 2); - debugger + nominationSampleCounts = programServiceHelper.setNominationSampleCounts( + relatedContents + ) + const userAndOrgResult = _.tail(promiseData, 2) _.forEach(userAndOrgResult, function (data) { - if (data.data.result && !_.isEmpty(_.get(data, 'data.result.User'))) { + if ( + data.data.result && + !_.isEmpty(_.get(data, 'data.result.User')) + ) { _.forEach(data.data.result.User, (userData) => { - const index = _.indexOf(_.map(result, 'user_id'), userData.userId) + const index = _.indexOf( + _.map(result, 'user_id'), + userData.userId + ) if (index !== -1) { - result[index].dataValues.userData = userData; + result[index].dataValues.userData = userData } }) } - if (data.data.result && !_.isEmpty(_.get(data, 'data.result.Org'))) { + if ( + data.data.result && + !_.isEmpty(_.get(data, 'data.result.Org')) + ) { _.forEach(data.data.result.Org, (orgData) => { - const index = _.indexOf(_.map(result, 'organisation_id'), orgData.osid) + const index = _.indexOf( + _.map(result, 'organisation_id'), + orgData.osid + ) if (index !== -1) { - result[index].dataValues.orgData = orgData; + result[index].dataValues.orgData = orgData } }) } - }); + }) const dataValues = _.map(result, 'dataValues') - const nominationsWithSamples = programServiceHelper.assignSampleCounts(dataValues, nominationSampleCounts, findQuery.program_name); - const tableData = programServiceHelper.downloadNominationList(nominationsWithSamples) - cacheManager.set({ key: findQuery.program_id, value: tableData }, + const nominationsWithSamples = programServiceHelper.assignSampleCounts( + dataValues, + nominationSampleCounts, + findQuery.program_name + ) + const tableData = programServiceHelper.downloadNominationList( + nominationsWithSamples + ) + cacheManager.set( + { key: findQuery.program_id, value: tableData }, function (err, cacheCSVData) { if (err) { - logger.error({msg: 'Error - caching', err, additionalInfo: {stats: tableData}}, req) + logger.error( + { + msg: 'Error - caching', + err, + additionalInfo: { stats: tableData } + }, + req + ) } else { - logger.debug({msg: 'Caching nomination list - done', additionalInfo: {stats: cacheCSVData}}, req) + logger.debug( + { + msg: 'Caching nomination list - done', + additionalInfo: { stats: cacheCSVData } + }, + req + ) } - }) + } + ) rspObj.result = { stats: tableData } @@ -904,32 +1210,52 @@ function aggregatedNominationCount(data, result) { return response.status(200).send(successResponse(rspObj)) }, (error) => { - rspObj.errCode = _.get(error, 'response.statusText'); - rspObj.errMsg = _.get(error, 'response.data.message'); - rspObj.responseCode = responseCode.UNAUTHORIZED_ACCESS; - loggerError('Error fetching user or org details while downloading nomination list', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, error, null) + rspObj.errCode = _.get(error, 'response.statusText') + rspObj.errMsg = _.get(error, 'response.data.message') + rspObj.responseCode = responseCode.UNAUTHORIZED_ACCESS + loggerError( + 'Error fetching user or org details while downloading nomination list', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + error, + null + ) return response.status(400).send(errorResponse(rspObj)) } ) - } catch(error) { - rspObj.errCode = _.get(error, 'name'); - rspObj.errMsg = _.get(error, 'message'); - rspObj.responseCode = responseCode.SERVER_ERROR; - loggerError('Error fetching nomination list', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, error, req) + } catch (error) { + rspObj.errCode = _.get(error, 'name') + rspObj.errMsg = _.get(error, 'message') + rspObj.responseCode = responseCode.SERVER_ERROR + loggerError( + 'Error fetching nomination list', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + error, + req + ) + return response.status(400).send(errorResponse(rspObj)) + } + }) + .catch((error) => { + rspObj.errCode = + programMessages.NOMINATION.DOWNLOAD_LIST.QUERY_FAILED_CODE + rspObj.errMsg = + programMessages.NOMINATION.DOWNLOAD_LIST.QUERY_FAILED_MESSAGE + rspObj.responseCode = responseCode.SERVER_ERROR + loggerError( + 'Error fetching nomination list', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + error, + req + ) return response.status(400).send(errorResponse(rspObj)) - } - }).catch(error => { - rspObj.errCode = programMessages.NOMINATION.DOWNLOAD_LIST.QUERY_FAILED_CODE; - rspObj.errMsg = programMessages.NOMINATION.DOWNLOAD_LIST.QUERY_FAILED_MESSAGE; - rspObj.responseCode = responseCode.SERVER_ERROR; - loggerError('Error fetching nomination list', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, error, req) - return response.status(400).send(errorResponse(rspObj)) - }) - } - else { + }) + } else { rspObj.result = { stats: cacheData } @@ -939,22 +1265,22 @@ function aggregatedNominationCount(data, result) { }) } -function getUsersDetails(req, userList) { - const url = `${envVariables.OPENSABER_SERVICE_URL}/search`; +function getUsersDetails (req, userList) { + const url = `${envVariables.OPENSABER_SERVICE_URL}/search` const reqData = { - "id": "open-saber.registry.search", - "ver": "1.0", - "ets": "11234", - "params": { - "did": "", - "key": "", - "msgid": "" + id: 'open-saber.registry.search', + ver: '1.0', + ets: '11234', + params: { + did: '', + key: '', + msgid: '' }, - "request": { - "entityType": ["User"], - "filters": { - "userId": { - "or": userList + request: { + entityType: ['User'], + filters: { + userId: { + or: userList } } } @@ -964,26 +1290,25 @@ function getUsersDetails(req, userList) { url: url, headers: req.headers, data: reqData - }); + }) } - -function getOrgDetails(req, orgList) { - const url = `${envVariables.OPENSABER_SERVICE_URL}/search`; +function getOrgDetails (req, orgList) { + const url = `${envVariables.OPENSABER_SERVICE_URL}/search` const reqData = { - "id": "open-saber.registry.search", - "ver": "1.0", - "ets": "11234", - "params": { - "did": "", - "key": "", - "msgid": "" + id: 'open-saber.registry.search', + ver: '1.0', + ets: '11234', + params: { + did: '', + key: '', + msgid: '' }, - "request": { - "entityType": ["Org"], - "filters": { - "osid": { - "or": orgList + request: { + entityType: ['Org'], + filters: { + osid: { + or: orgList } } } @@ -993,471 +1318,599 @@ function getOrgDetails(req, orgList) { url: url, headers: req.headers, data: reqData - }); + }) } -function getUsersDetailsById(req, response) { - +function getUsersDetailsById (req, response) { const dikshaUserId = req.params.user_id - async.waterfall([ - function (callback1) { - getUserDetailsFromRegistry(dikshaUserId, callback1) - }, - function (user, callback2) { - getUserOrgMappingDetailFromRegistry(user, callback2); - }, - function (user, userOrgMapDetails, callback3) { - getOrgDetailsFromRegistry(user, userOrgMapDetails, callback3) - }, - function (user, userOrgMapDetails, orgInfoLists, callback4) { - createUserRecords(user, userOrgMapDetails, orgInfoLists, callback4) - } - ], function (err, res) { - if (err) { - return response.status(400).send(errorResponse({ - apiId: 'api.user.read', - ver: '1.0', - msgid: uuid(), - responseCode: 'ERR_READ_USER', - result: err.message || err - })) - - } else { - return response.status(200).send(successResponse({ - apiId: 'api.user.read', - ver: '1.0', - msgid: uuid(), - responseCode: 'OK', - result: res - })) + async.waterfall( + [ + function (callback1) { + getUserDetailsFromRegistry(dikshaUserId, callback1) + }, + function (user, callback2) { + getUserOrgMappingDetailFromRegistry(user, callback2) + }, + function (user, userOrgMapDetails, callback3) { + getOrgDetailsFromRegistry(user, userOrgMapDetails, callback3) + }, + function (user, userOrgMapDetails, orgInfoLists, callback4) { + createUserRecords(user, userOrgMapDetails, orgInfoLists, callback4) + } + ], + function (err, res) { + if (err) { + return response.status(400).send( + errorResponse({ + apiId: 'api.user.read', + ver: '1.0', + msgid: uuid(), + responseCode: 'ERR_READ_USER', + result: err.message || err + }) + ) + } else { + return response.status(200).send( + successResponse({ + apiId: 'api.user.read', + ver: '1.0', + msgid: uuid(), + responseCode: 'OK', + result: res + }) + ) + } } - }); + ) } -function getUserDetailsFromRegistry(value, callback) { - let userDetailReq = { +function getUserDetailsFromRegistry (value, callback) { + const userDetailReq = { body: { - id: "open-saber.registry.search", + id: 'open-saber.registry.search', request: { - entityType: ["User"], + entityType: ['User'], filters: { userId: { eq: value } } - } } } + // eslint-disable-next-line handle-callback-err registryService.searchRecord(userDetailReq, (err, res) => { if (res) { - if (res.status == 200) { + if (res.status === 200) { if (res.data.result.User.length > 0) { - var userDetails = res.data.result.User[0]; + var userDetails = res.data.result.User[0] callback(null, userDetails) } else { - callback("user does not exist") + // eslint-disable-next-line standard/no-callback-literal + callback('user does not exist') } } else { - logger.error("Encountered some error while searching data") - callback("Encountered some error while searching data") + logger.error('Encountered some error while searching data') + // eslint-disable-next-line standard/no-callback-literal + callback('Encountered some error while searching data') } } else { - logger.error("Encountered some error while searching data") - callback("Encountered some error while searching data") + logger.error('Encountered some error while searching data') + // eslint-disable-next-line standard/no-callback-literal + callback('Encountered some error while searching data') } - }); - + }) } - -function getUserOrgMappingDetailFromRegistry(user, callback) { - - let userOrgMappingReq = { +function getUserOrgMappingDetailFromRegistry (user, callback) { + const userOrgMappingReq = { body: { - id: "open-saber.registry.search", + id: 'open-saber.registry.search', request: { - entityType: ["User_Org"], + entityType: ['User_Org'], filters: { userId: { eq: user.osid } } - } } } - + // eslint-disable-next-line handle-callback-err registryService.searchRecord(userOrgMappingReq, (err, res) => { if (res) { - if (res.status == 200) { + if (res.status === 200) { if (res.data.result.User_Org.length > 0) { + // eslint-disable-next-line no-undef userOrgMapList = res.data.result.User_Org + // eslint-disable-next-line standard/no-callback-literal + // eslint-disable-next-line no-undef callback(null, user, userOrgMapList) } else { - callback("Org not mapped to the user: " + user.userId) + // eslint-disable-next-line standard/no-callback-literal + callback('Org not mapped to the user: ' + user.userId) } } else { - logger.error("Encountered some error while searching data") - callback("Encountered some error while searching data") + logger.error('Encountered some error while searching data') + // eslint-disable-next-line standard/no-callback-literal + callback('Encountered some error while searching data') } } else { - logger.error("Encountered some error while searching data") - callback("Encountered some error while searching data") + logger.error('Encountered some error while searching data') + // eslint-disable-next-line standard/no-callback-literal + callback('Encountered some error while searching data') } - }); - + }) } -function getOrgDetailsFromRegistry(user, userOrgMapDetails, callback) { - +function getOrgDetailsFromRegistry (user, userOrgMapDetails, callback) { const orgList = userOrgMapDetails.map((value) => value.orgId.slice(2)) - let orgDetailsReq = { + const orgDetailsReq = { body: { - id: "open-saber.registry.search", + id: 'open-saber.registry.search', request: { - entityType: ["Org"], + entityType: ['Org'], filters: { osid: { or: orgList } } - } } } + // eslint-disable-next-line handle-callback-err registryService.searchRecord(orgDetailsReq, (err, res) => { if (res) { - if (res.status == 200) { + if (res.status === 200) { if (res.data.result.Org.length > 0) { + // eslint-disable-next-line no-undef orgInfoList = res.data.result.Org + // eslint-disable-next-line no-undef callback(null, user, userOrgMapList, orgInfoList) } else { - callback("Org Details Not available with org Ids: " + orgList.toString()) + // eslint-disable-next-line standard/no-callback-literal + callback( + 'Org Details Not available with org Ids: ' + orgList.toString() + ) } } else { - logger.error("Encountered some error while searching data") - callback("Encountered some error while searching data") + logger.error('Encountered some error while searching data') + // eslint-disable-next-line standard/no-callback-literal + callback('Encountered some error while searching data') } } else { - logger.error("Encountered some error while searching data") - callback("Encountered some error while searching data") + logger.error('Encountered some error while searching data') + // eslint-disable-next-line standard/no-callback-literal + callback('Encountered some error while searching data') } - }); - + }) } -function createUserRecords(user, userOrgMapDetails, orgInfoList, callback) { - +function createUserRecords (user, userOrgMapDetails, orgInfoList, callback) { try { orgInfoList.map((org) => { var roles = null userOrgMapDetails.forEach(function (element, index, array) { if (org.osid === element.orgId) { - roles = element.roles; + roles = element.roles } - }); - - org['roles'] = roles + }) - }); + org.roles = roles + }) - user['orgs'] = orgInfoList + user.orgs = orgInfoList callback(null, user) - } catch (e) { - logger.error("Error while parsing for user lists") - callback("Some Internal processing error while parsing user details", null) + logger.error('Error while parsing for user lists') + // eslint-disable-next-line standard/no-callback-literal + callback('Some Internal processing error while parsing user details', null) } - - } - - - - -function programSearch(req, response) { - const fieldsToSelect = _.compact(_.split(_.get(req, 'query.fields'), ',')); - const requiredKeys = ['program_id', 'type', 'name', 'description', 'image_path'] - const searchCriteria = _.uniq([...requiredKeys, ...fieldsToSelect]); - const searchQuery = _.get(req, 'body.request'); - programDBModel.instance.program.findAsync(searchQuery, { +function programSearch (req, response) { + const fieldsToSelect = _.compact(_.split(_.get(req, 'query.fields'), ',')) + const requiredKeys = [ + 'program_id', + 'type', + 'name', + 'description', + 'image_path' + ] + const searchCriteria = _.uniq([...requiredKeys, ...fieldsToSelect]) + const searchQuery = _.get(req, 'body.request') + // eslint-disable-next-line no-undef + model.program + .findAsync(searchQuery, { allow_filtering: true, select: searchCriteria, raw: true }) - .then(resData => { - return response.status(200).send(successResponse({ - apiId: 'api.program.search', - ver: '1.0', - msgid: uuid(), - responseCode: 'OK', - result: resData - })); - }).catch(error => { - return response.status(400).send(errorResponse({ - apiId: 'api.program.search', - ver: '1.0', - msgid: uuid(), - responseCode: 'ERR_SEARCH_PROGRAM', - result: error.message || error - })); + .then((resData) => { + return response.status(200).send( + successResponse({ + apiId: 'api.program.search', + ver: '1.0', + msgid: uuid(), + responseCode: 'OK', + result: resData + }) + ) + }) + .catch((error) => { + return response.status(400).send( + errorResponse({ + apiId: 'api.program.search', + ver: '1.0', + msgid: uuid(), + responseCode: 'ERR_SEARCH_PROGRAM', + result: error.message || error + }) + ) }) } -function getProgramContentTypes(req, response) { - var rspObj = req.rspObj; +function getProgramContentTypes (req, response) { + var rspObj = req.rspObj rspObj.errCode = contentTypeMessages.FETCH.FAILED_CODE rspObj.errMsg = contentTypeMessages.FETCH.FAILED_MESSAGE rspObj.responseCode = responseCode.SERVER_ERROR - logger.debug({ - msg: 'Request to program to fetch content types' - }, req) - model.contenttypes.findAndCountAll() - .then(res => { + logger.debug( + { + msg: 'Request to program to fetch content types' + }, + req + ) + model.contenttypes + .findAndCountAll() + .then((res) => { rspObj.result = { count: res.count, contentType: res.rows } rspObj.responseCode = 'OK' return response.status(200).send(successResponse(rspObj)) - }).catch(error => { - logger.error({ - msg: 'Error fetching program content types', - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode + }) + .catch((error) => { + logger.error( + { + msg: 'Error fetching program content types', + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + }, + additionalInfo: { + error + } }, - additionalInfo: { - error - } - }, req) - return response.status(400).send(errorResponse(rspObj)); + req + ) + return response.status(400).send(errorResponse(rspObj)) }) } -function getAllConfigurations(req, response) { - var rspObj = req.rspObj; +function getAllConfigurations (req, response) { + var rspObj = req.rspObj rspObj.errCode = configurationMessages.FETCH.FAILED_CODE rspObj.errMsg = configurationMessages.FETCH.FAILED_MESSAGE rspObj.responseCode = configurationMessages.SERVER_ERROR - logger.debug({ - msg: 'Request to fetch program configuration' - }, req) + logger.debug( + { + msg: 'Request to fetch program configuration' + }, + req + ) - model.configuration.findAndCountAll() - .then(res => { + model.configuration + .findAndCountAll() + .then((res) => { rspObj.result = { count: res.count, configuration: res.rows } rspObj.responseCode = 'OK' return response.status(200).send(successResponse(rspObj)) - }).catch(error => { - loggerError('Error fetching program configurations', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, error, req); - return response.status(400).send(errorResponse(rspObj)); + }) + .catch((error) => { + loggerError( + 'Error fetching program configurations', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + error, + req + ) + return response.status(400).send(errorResponse(rspObj)) }) } -function getConfigurationByKey(req, response) { - var rspObj = req.rspObj; - var data = req.body; - if(!data || !data.request || !data.request.key || !data.request.status) { +function getConfigurationByKey (req, response) { + var rspObj = req.rspObj + var data = req.body + if (!data || !data.request || !data.request.key || !data.request.status) { rspObj.errCode = configurationMessages.SEARCH.MISSING_CODE rspObj.errMsg = configurationMessages.SEARCH.MISSING_MESSAGE rspObj.responseCode = responseCode.CLIENT_ERROR - loggerError('Error due to missing request or request key or status', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, null, req) + loggerError( + 'Error due to missing request or request key or status', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + null, + req + ) return response.status(400).send(errorResponse(rspObj)) } rspObj.errCode = configurationMessages.FETCH.FAILED_CODE rspObj.errMsg = configurationMessages.FETCH.FAILED_MESSAGE rspObj.responseCode = configurationMessages.SERVER_ERROR - logger.debug({ - msg: 'Request to fetch program configuration' - }, req) + logger.debug( + { + msg: 'Request to fetch program configuration' + }, + req + ) - model.configuration.findAll({ - where: { - key: data.request.key, - status: data.request.status - } - }) - .then(res => { + model.configuration + .findAll({ + where: { + key: data.request.key, + status: data.request.status + } + }) + .then((res) => { const result = _.first(res) rspObj.result = { configuration: result ? result.dataValues : [] } rspObj.responseCode = 'OK' return response.status(200).send(successResponse(rspObj)) - }).catch(error => { - loggerError('Error fetching program configurations', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, error, req); - return response.status(400).send(errorResponse(rspObj)); + }) + .catch((error) => { + loggerError( + 'Error fetching program configurations', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + error, + req + ) + return response.status(400).send(errorResponse(rspObj)) }) } -function programUpdateCollection(req, response) { +function programUpdateCollection (req, response) { const data = req.body const rspObj = req.rspObj - const url = `${envVariables.SUNBIRD_URL}/action/system/v3/content/update`; + const url = `${envVariables.SUNBIRD_URL}/action/system/v3/content/update` if (!data.request || !data.request.program_id || !data.request.collection) { rspObj.errCode = programMessages.LINK.MISSING_CODE rspObj.errMsg = programMessages.LINK.MISSING_MESSAGE rspObj.responseCode = responseCode.CLIENT_ERROR - logger.error({ - msg: 'Error due to missing request or request program_id or request collections', - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode + logger.error( + { + msg: + 'Error due to missing request or request program_id or request collections', + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + }, + additionalInfo: { + data + } }, - additionalInfo: { - data - } - }, req) + req + ) return response.status(400).send(errorResponse(rspObj)) } const updateQuery = { - "request": { - "content": { - "programId": req.body.request.program_id + request: { + content: { + programId: req.body.request.program_id } } } - const updateUrls = _.map(req.body.request.collection, collection => { + const updateUrls = _.map(req.body.request.collection, (collection) => { return axios({ method: 'patch', url: `${url}/${collection}`, headers: req.headers, data: updateQuery - }); + }) }) - forkJoin(updateUrls).subscribe(resData => { - const consolidatedResult = _.map(resData, r => r.data.result) - return response.status(200).send(successResponse({ - apiId: 'api.program.collection.link', - ver: '1.0', - msgid: uuid(), - responseCode: 'OK', - result: consolidatedResult - })); - }, (error) => { - rspObj.errCode = programMessages.LINK.MISSING_CODE - rspObj.errMsg = programMessages.LINK.MISSING_MESSAGE - rspObj.responseCode = responseCode.RESOURCE_NOT_FOUND - logger.error({ - msg: 'Error due to resource not found', - err: { - errCode: rspObj.errCode, - errMsg: rspObj.errMsg, - responseCode: rspObj.responseCode - }, - additionalInfo: { - data - } - }, req) + forkJoin(updateUrls).subscribe( + (resData) => { + const consolidatedResult = _.map(resData, (r) => r.data.result) + return response.status(200).send( + successResponse({ + apiId: 'api.program.collection.link', + ver: '1.0', + msgid: uuid(), + responseCode: 'OK', + result: consolidatedResult + }) + ) + }, + (error) => { + rspObj.errCode = programMessages.LINK.MISSING_CODE + rspObj.errMsg = programMessages.LINK.MISSING_MESSAGE + rspObj.responseCode = responseCode.RESOURCE_NOT_FOUND + logger.error( + { + msg: 'Error due to resource not found', + err: { + errCode: rspObj.errCode, + errMsg: rspObj.errMsg, + responseCode: rspObj.responseCode + }, + additionalInfo: { + data + } + }, + req + ) - return response.status(400).send(errorResponse({ - apiId: 'api.program.collection.link', - ver: '1.0', - msgId: uuid(), - errCode: error.response.data.params.err, - status: error.response.data.params.status, - errMsg: error.response.data.params.errmsg, - responseCode: error.response.data.responseCode, - result: error.response.data.result - })); - }) + return response.status(400).send( + errorResponse({ + apiId: 'api.program.collection.link', + ver: '1.0', + msgId: uuid(), + errCode: error.response.data.params.err, + status: error.response.data.params.status, + errMsg: error.response.data.params.errmsg, + responseCode: error.response.data.responseCode, + result: error.response.data.result + }) + ) + } + ) } -async function programCopyCollections(req, response) { - const data = req.body; - const rspObj = req.rspObj; - const reqHeaders = req.headers; - - if (!data.request || !data.request.program_id || !data.request.collections || !data.request.allowed_content_types || !data.request.channel) { - rspObj.errCode = programMessages.COPY_COLLECTION.COPY.MISSING_CODE; - rspObj.errMsg = programMessages.COPY_COLLECTION.COPY.MISSING_MESSAGE; - rspObj.responseCode = responseCode.CLIENT_ERROR; - loggerError('Error due to missing request or program_id or request collections or request allowed_content_types or channel', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, null, req ) +async function programCopyCollections (req, response) { + const data = req.body + const rspObj = req.rspObj + const reqHeaders = req.headers + + if ( + !data.request || + !data.request.program_id || + !data.request.collections || + !data.request.allowed_content_types || + !data.request.channel + ) { + rspObj.errCode = programMessages.COPY_COLLECTION.COPY.MISSING_CODE + rspObj.errMsg = programMessages.COPY_COLLECTION.COPY.MISSING_MESSAGE + rspObj.responseCode = responseCode.CLIENT_ERROR + loggerError( + 'Error due to missing request or program_id or request collections or request allowed_content_types or channel', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + null, + req + ) return response.status(400).send(errorResponse(rspObj)) } - const collections = _.get(data, 'request.collections'); + const collections = _.get(data, 'request.collections') const additionalMetaData = { programId: _.get(data, 'request.program_id'), allowedContentTypes: _.get(data, 'request.allowed_content_types'), channel: _.get(data, 'request.channel'), openForContribution: true } - hierarchyService.filterExistingTextbooks(collections, reqHeaders) - .subscribe( - (resData) => { - const consolidatedResult = _.map(resData, r => { - return { - result: r.data.result, - config: r.config.data - } - }) - const existingTextbooks = hierarchyService.getExistingCollection(consolidatedResult); - const nonExistingTextbooks = hierarchyService.getNonExistingCollection(consolidatedResult) - if (existingTextbooks && existingTextbooks.length > 0) { - hierarchyService.getHierarchy(existingTextbooks, reqHeaders) - .subscribe( - (originHierarchyResult) => { - const originHierarchyResultData = _.map(originHierarchyResult, r => { - return _.get(r, 'data') - }) - const getCollectiveRequest = _.map(originHierarchyResultData, c => { - return hierarchyService.existingHierarchyUpdateRequest(c, additionalMetaData); - }) - hierarchyService.bulkUpdateHierarchy(getCollectiveRequest, reqHeaders) - .subscribe(updateResult => { - const updateResultData = _.map(updateResult, obj => { - return obj.data - }) - rspObj.result = updateResultData; - rspObj.responseCode = 'OK' - response.status(200).send(successResponse(rspObj)) - }, error => { - rspObj.errCode = programMessages.COPY_COLLECTION.BULK_UPDATE_HIERARCHY.FAILED_CODE; - rspObj.errMsg = programMessages.COPY_COLLECTION.BULK_UPDATE_HIERARCHY.FAILED_MESSAGE; - rspObj.responseCode = responseCode.SERVER_ERROR - console.log('Error updating hierarchy for collections', error) - loggerError('Error updating hierarchy for collections', rspObj.errCode, rspObj.errMsg, rspObj.responseCode, error, req) - return response.status(400).send(errorResponse(rspObj)) + hierarchyService.filterExistingTextbooks(collections, reqHeaders).subscribe( + (resData) => { + const consolidatedResult = _.map(resData, (r) => { + return { + result: r.data.result, + config: r.config.data + } + }) + const existingTextbooks = hierarchyService.getExistingCollection( + consolidatedResult + ) + const nonExistingTextbooks = hierarchyService.getNonExistingCollection( + consolidatedResult + ) + if (existingTextbooks && existingTextbooks.length > 0) { + hierarchyService.getHierarchy(existingTextbooks, reqHeaders).subscribe( + (originHierarchyResult) => { + const originHierarchyResultData = _.map( + originHierarchyResult, + (r) => { + return _.get(r, 'data') + } + ) + const getCollectiveRequest = _.map( + originHierarchyResultData, + (c) => { + return hierarchyService.existingHierarchyUpdateRequest( + c, + additionalMetaData + ) + } + ) + hierarchyService + .bulkUpdateHierarchy(getCollectiveRequest, reqHeaders) + .subscribe( + (updateResult) => { + const updateResultData = _.map(updateResult, (obj) => { + return obj.data }) - }, error => { - rspObj.errCode = programMessages.COPY_COLLECTION.GET_HIERARCHY.FAILED_CODE; - rspObj.errMsg = programMessages.COPY_COLLECTION.GET_HIERARCHY.FAILED_MESSAGE; + rspObj.result = updateResultData + rspObj.responseCode = 'OK' + response.status(200).send(successResponse(rspObj)) + }, + (error) => { + rspObj.errCode = + programMessages.COPY_COLLECTION.BULK_UPDATE_HIERARCHY.FAILED_CODE + rspObj.errMsg = + programMessages.COPY_COLLECTION.BULK_UPDATE_HIERARCHY.FAILED_MESSAGE rspObj.responseCode = responseCode.SERVER_ERROR - console.log('Error fetching hierarchy for collections', error) - loggerError('Error fetching hierarchy for collections', rspObj.errCode, rspObj.errMsg, rspObj.responseCode, error, req) - return response.status(400).send(errorResponse(rspObj)) - }) - } - if (nonExistingTextbooks && nonExistingTextbooks.length > 0) { - hierarchyService.getHierarchy(nonExistingTextbooks, reqHeaders) - .subscribe( - (originHierarchyResult) => { - const originHierarchyResultData = _.map(originHierarchyResult, r => { + console.log( + 'Error updating hierarchy for collections', + error + ) + loggerError( + 'Error updating hierarchy for collections', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + error, + req + ) + return response.status(400).send(errorResponse(rspObj)) + } + ) + }, + (error) => { + rspObj.errCode = + programMessages.COPY_COLLECTION.GET_HIERARCHY.FAILED_CODE + rspObj.errMsg = + programMessages.COPY_COLLECTION.GET_HIERARCHY.FAILED_MESSAGE + rspObj.responseCode = responseCode.SERVER_ERROR + console.log('Error fetching hierarchy for collections', error) + loggerError( + 'Error fetching hierarchy for collections', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + error, + req + ) + return response.status(400).send(errorResponse(rspObj)) + } + ) + } + if (nonExistingTextbooks && nonExistingTextbooks.length > 0) { + hierarchyService + .getHierarchy(nonExistingTextbooks, reqHeaders) + .subscribe( + (originHierarchyResult) => { + const originHierarchyResultData = _.map( + originHierarchyResult, + (r) => { return _.get(r, 'data') - }) - hierarchyService.createCollection(originHierarchyResultData, reqHeaders) - .subscribe(createResponse => { - const originHierarchy = _.map(originHierarchyResultData, 'result.content'); - - const createdCollections = _.map(createResponse, cr => { + } + ) + hierarchyService + .createCollection(originHierarchyResultData, reqHeaders) + .subscribe( + (createResponse) => { + const originHierarchy = _.map( + originHierarchyResultData, + 'result.content' + ) + + const createdCollections = _.map(createResponse, (cr) => { const mapOriginalHierarchy = { creationResult: cr.data, hierarchy: { @@ -1469,164 +1922,303 @@ async function programCopyCollections(req, response) { }) } } - mapOriginalHierarchy.hierarchy.content.identifier = cr.config.params.identifier - return mapOriginalHierarchy; - }) - const getBulkUpdateRequest = _.map(createdCollections, item => { - return hierarchyService.newHierarchyUpdateRequest(item, additionalMetaData) + mapOriginalHierarchy.hierarchy.content.identifier = + cr.config.params.identifier + return mapOriginalHierarchy }) - hierarchyService.bulkUpdateHierarchy(getBulkUpdateRequest, reqHeaders) - .subscribe(updateResult => { - const updateResultData = _.map(updateResult, obj => { - return obj.data - }) - rspObj.result = updateResultData; - rspObj.responseCode = 'OK' - response.status(200).send(successResponse(rspObj)) - }, error => { - rspObj.errCode = _.get(error.response, 'data.params.err') || programMessages.COPY_COLLECTION.BULK_UPDATE_HIERARCHY.FAILED_CODE; - rspObj.errMsg = _.get(error.response, 'data.params.errmsg') || programMessages.COPY_COLLECTION.BULK_UPDATE_HIERARCHY.FAILED_MESSAGE; - rspObj.responseCode = _.get(error.response, 'data.responseCode') || responseCode.SERVER_ERROR - console.log('Error updating hierarchy for collections', error) - loggerError('Error updating hierarchy for collections', rspObj.errCode, rspObj.errMsg, rspObj.responseCode, error, req) - return response.status(400).send(errorResponse(rspObj)) - }) - }, error => { - rspObj.errCode = _.get(error.response, 'data.params.err') || programMessages.COPY_COLLECTION.CREATE_COLLECTION.FAILED_CODE; - rspObj.errMsg = _.get(error.response, 'data.params.errmsg') || programMessages.COPY_COLLECTION.CREATE_COLLECTION.FAILED_MESSAGE; - rspObj.responseCode = _.get(error.response, 'data.responseCode') || responseCode.SERVER_ERROR + const getBulkUpdateRequest = _.map( + createdCollections, + (item) => { + return hierarchyService.newHierarchyUpdateRequest( + item, + additionalMetaData + ) + } + ) + hierarchyService + .bulkUpdateHierarchy(getBulkUpdateRequest, reqHeaders) + .subscribe( + (updateResult) => { + const updateResultData = _.map( + updateResult, + (obj) => { + return obj.data + } + ) + rspObj.result = updateResultData + rspObj.responseCode = 'OK' + response.status(200).send(successResponse(rspObj)) + }, + (error) => { + rspObj.errCode = + _.get(error.response, 'data.params.err') || + programMessages.COPY_COLLECTION + .BULK_UPDATE_HIERARCHY.FAILED_CODE + rspObj.errMsg = + _.get(error.response, 'data.params.errmsg') || + programMessages.COPY_COLLECTION + .BULK_UPDATE_HIERARCHY.FAILED_MESSAGE + rspObj.responseCode = + _.get(error.response, 'data.responseCode') || + responseCode.SERVER_ERROR + console.log( + 'Error updating hierarchy for collections', + error + ) + loggerError( + 'Error updating hierarchy for collections', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + error, + req + ) + return response + .status(400) + .send(errorResponse(rspObj)) + } + ) + }, + (error) => { + rspObj.errCode = + _.get(error.response, 'data.params.err') || + programMessages.COPY_COLLECTION.CREATE_COLLECTION + .FAILED_CODE + rspObj.errMsg = + _.get(error.response, 'data.params.errmsg') || + programMessages.COPY_COLLECTION.CREATE_COLLECTION + .FAILED_MESSAGE + rspObj.responseCode = + _.get(error.response, 'data.responseCode') || + responseCode.SERVER_ERROR console.log('Error creating collection', error) - loggerError('Error creating collection', rspObj.errCode, rspObj.errMsg, rspObj.responseCode, error, req) + loggerError( + 'Error creating collection', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + error, + req + ) return response.status(400).send(errorResponse(rspObj)) - }) - }, (error) => { - rspObj.errCode = programMessages.COPY_COLLECTION.GET_HIERARCHY.FAILED_CODE; - rspObj.errMsg = programMessages.COPY_COLLECTION.GET_HIERARCHY.FAILED_MESSAGE; - rspObj.responseCode = responseCode.SERVER_ERROR - console.log('Error fetching hierarchy for collections', error) - loggerError('Error fetching hierarchy for collections', rspObj.errCode, rspObj.errMsg, rspObj.responseCode, error, req) - return response.status(400).send(errorResponse(rspObj)) - }) - } - }, - (error) => { - rspObj.errCode = programMessages.COPY_COLLECTION.SEARCH_DOCK_COLLECTION.FAILED_CODE; - rspObj.errMsg = error.message || programMessages.COPY_COLLECTION.SEARCH_DOCK_COLLECTION.FAILED_MESSAGE; - rspObj.responseCode = error.response.statusText || responseCode.SERVER_ERROR - console.log('Error searching for collections', error) - loggerError('Error searching for collections', rspObj.errCode, rspObj.errMsg, rspObj.responseCode, error, req) - return response.status(error.response.status || 400).send(errorResponse(rspObj)) + } + ) + }, + (error) => { + rspObj.errCode = + programMessages.COPY_COLLECTION.GET_HIERARCHY.FAILED_CODE + rspObj.errMsg = + programMessages.COPY_COLLECTION.GET_HIERARCHY.FAILED_MESSAGE + rspObj.responseCode = responseCode.SERVER_ERROR + console.log('Error fetching hierarchy for collections', error) + loggerError( + 'Error fetching hierarchy for collections', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + error, + req + ) + return response.status(400).send(errorResponse(rspObj)) + } + ) } - ) + }, + (error) => { + rspObj.errCode = + programMessages.COPY_COLLECTION.SEARCH_DOCK_COLLECTION.FAILED_CODE + rspObj.errMsg = + error.message || + programMessages.COPY_COLLECTION.SEARCH_DOCK_COLLECTION.FAILED_MESSAGE + rspObj.responseCode = + error.response.statusText || responseCode.SERVER_ERROR + console.log('Error searching for collections', error) + loggerError( + 'Error searching for collections', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + error, + req + ) + return response + .status(error.response.status || 400) + .send(errorResponse(rspObj)) + } + ) } -async function generateApprovedContentReport(req, res) { +async function generateApprovedContentReport (req, res) { const data = req.body const rspObj = req.rspObj - let programArr = [], cacheData = [], filteredPrograms = []; + let programArr = [] + const cacheData = [] + const filteredPrograms = [] rspObj.errCode = programMessages.CONTENT_REPORT.FAILED_CODE rspObj.errMsg = programMessages.CONTENT_REPORT.FAILED_MESSAGE rspObj.responseCode = responseCode.SERVER_ERROR - if (!data.request || !data.request.filters || !data.request.filters.program_id || !data.request.filters.report) { + if ( + !data.request || + !data.request.filters || + !data.request.filters.program_id || + !data.request.filters.report + ) { rspObj.errCode = programMessages.CONTENT_REPORT.MISSING_CODE rspObj.errMsg = programMessages.CONTENT_REPORT.MISSING_MESSAGE rspObj.responseCode = responseCode.CLIENT_ERROR - loggerError('Error due to missing request or request.filters or request.filters.program_id or data.request.filters.report', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, null, req) - return res.status(400).send(errorResponse(rspObj)); + loggerError( + 'Error due to missing request or request.filters or request.filters.program_id or data.request.filters.report', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + null, + req + ) + return res.status(400).send(errorResponse(rspObj)) } - programArr = _.isArray(data.request.filters.program_id) ? data.request.filters.program_id : []; + programArr = _.isArray(data.request.filters.program_id) + ? data.request.filters.program_id + : [] await _.forEach(programArr, (program) => { - cacheManager_programReport.get(`approvedContentCount_${program}`, (err, cache) => { - if (err || !cache) { - filteredPrograms.push(program); - } else { - cacheData.push(cache); + cacheManagerProgramReport.get( + `approvedContentCount_${program}`, + (err, cache) => { + if (err || !cache) { + filteredPrograms.push(program) + } else { + cacheData.push(cache) + } } - }); - }); - + ) + }) + if (filteredPrograms.length) { try { - const requests = _.map(filteredPrograms, program => programServiceHelper.getCollectionHierarchy(req, program)); - const aggregatedResult = await Promise.all(requests); - _.forEach(aggregatedResult, result => { - cacheManager_programReport.set({ key: `approvedContentCount_${result.program_id}`, value: result }, - function (err, cacheCSVData) { - if (err) { - logger.error({msg: 'Error - caching', err, additionalInfo: {approvedContentCount: result}}, req) - } else { - logger.debug({msg: 'Caching approvedContentCount - done', additionalInfo: {approvedContentCount: result}}, req) + const requests = _.map(filteredPrograms, (program) => + programServiceHelper.getCollectionHierarchy(req, program) + ) + const aggregatedResult = await Promise.all(requests) + _.forEach(aggregatedResult, (result) => { + cacheManagerProgramReport.set( + { key: `approvedContentCount_${result.program_id}`, value: result }, + function (err, cacheCSVData) { + if (err) { + logger.error( + { + msg: 'Error - caching', + err, + additionalInfo: { approvedContentCount: result } + }, + req + ) + } else { + logger.debug( + { + msg: 'Caching approvedContentCount - done', + additionalInfo: { approvedContentCount: result } + }, + req + ) + } } - }); - }); + ) + }) - if (data.request.filters.report === 'textbookLevelReport') { - const textbookLevelReport = await programServiceHelper.textbookLevelContentMetrics([...aggregatedResult, ...cacheData]); - rspObj.result = { - tableData: textbookLevelReport + if (data.request.filters.report === 'textbookLevelReport') { + const textbookLevelReport = await programServiceHelper.textbookLevelContentMetrics( + [...aggregatedResult, ...cacheData] + ) + rspObj.result = { + tableData: textbookLevelReport + } + rspObj.responseCode = 'OK' + return res.status(200).send(successResponse(rspObj)) + } else if (data.request.filters.report === 'chapterLevelReport') { + const chapterLevelReport = await programServiceHelper.chapterLevelContentMetrics( + [...aggregatedResult, ...cacheData] + ) + rspObj.result = { + tableData: chapterLevelReport + } + rspObj.responseCode = 'OK' + return res.status(200).send(successResponse(rspObj)) + } else { + // eslint-disable-next-line no-throw-literal + throw 'programServiceException: Invalid report name' } - rspObj.responseCode = 'OK' - return res.status(200).send(successResponse(rspObj)); - } else if (data.request.filters.report === 'chapterLevelReport') { - const chapterLevelReport = await programServiceHelper.chapterLevelContentMetrics([...aggregatedResult, ...cacheData]); - rspObj.result = { - tableData: chapterLevelReport + } catch (err) { + if (_.includes(err, 'programServiceException')) { + rspObj.errMsg = err } - rspObj.responseCode = 'OK' - return res.status(200).send(successResponse(rspObj)); - } else { - throw 'programServiceException: Invalid report name' - } - } catch(err) { - if (_.includes(err, 'programServiceException')) { - rspObj.errMsg = err; - } - loggerError('Error in preparing content metrics', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, err, req) - return res.status(400).send(errorResponse(rspObj)); + loggerError( + 'Error in preparing content metrics', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + err, + req + ) + return res.status(400).send(errorResponse(rspObj)) } } else { try { if (data.request.filters.report === 'textbookLevelReport') { - const textbookLevelReport = await programServiceHelper.textbookLevelContentMetrics([...cacheData]); + const textbookLevelReport = await programServiceHelper.textbookLevelContentMetrics( + [...cacheData] + ) rspObj.result = { tableData: textbookLevelReport } rspObj.responseCode = 'OK' - return res.status(200).send(successResponse(rspObj)); + return res.status(200).send(successResponse(rspObj)) } else if (data.request.filters.report === 'chapterLevelReport') { - const chapterLevelReport = await programServiceHelper.chapterLevelContentMetrics([...cacheData]); + const chapterLevelReport = await programServiceHelper.chapterLevelContentMetrics( + [...cacheData] + ) rspObj.result = { tableData: chapterLevelReport } rspObj.responseCode = 'OK' - return res.status(200).send(successResponse(rspObj)); + return res.status(200).send(successResponse(rspObj)) } else { + // eslint-disable-next-line no-throw-literal throw 'programServiceException: Invalid report name' } - }catch(err) { + } catch (err) { if (_.includes(err, 'programServiceException')) { - rspObj.errMsg = err; + rspObj.errMsg = err } - loggerError('Error in preparing content metrics', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, err, req) - return res.status(400).send(errorResponse(rspObj)); + loggerError( + 'Error in preparing content metrics', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + err, + req + ) + return res.status(400).send(errorResponse(rspObj)) } } } -function publishContent(req, response){ - var rspObj = req.rspObj; - const reqHeaders = req.headers; - var data = req.body; - if (!data.request || !data.request.content_id || !data.request.origin || - !data.request.origin.channel || !data.request.origin.textbook_id || !data.request.origin.units) { +function publishContent (req, response) { + var rspObj = req.rspObj + const reqHeaders = req.headers + var data = req.body + if ( + !data.request || + !data.request.content_id || + !data.request.origin || + !data.request.origin.channel || + !data.request.origin.textbook_id || + !data.request.origin.units + ) { rspObj.errCode = programMessages.CONTENT_PUBLISH.MISSING_CODE rspObj.errMsg = programMessages.CONTENT_PUBLISH.MISSING_MESSAGE rspObj.responseCode = responseCode.CLIENT_ERROR logger.error({ - msg: 'Error due to missing request or content_id or origin textbook_id or origin units or origin channel', + msg: + 'Error due to missing request or content_id or origin textbook_id or origin units or origin channel', err: { errCode: rspObj.errCode, errMsg: rspObj.errMsg, @@ -1639,66 +2231,92 @@ function publishContent(req, response){ return response.status(400).send(errorResponse(rspObj)) } - publishHelper.getContentMetaData(data.request.content_id, reqHeaders) + publishHelper + .getContentMetaData(data.request.content_id, reqHeaders) .pipe( - map(responseMetaData => { - const contentMetaData = _.get(responseMetaData, 'data.result.content'); - if(!contentMetaData) { - throw new Error("Fetching content metadata failed!"); + map((responseMetaData) => { + const contentMetaData = _.get(responseMetaData, 'data.result.content') + if (!contentMetaData) { + throw new Error('Fetching content metadata failed!') } - return contentMetaData; + return contentMetaData }), - catchError(err => { - throw err; + catchError((err) => { + throw err }) ) .subscribe( (contentMetaData) => { - contentMetaData.channel = _.get(data, 'request.origin.channel') || contentMetaData.channel; - var units = _.isArray(data.request.origin.units) ? data.request.origin.units : [data.request.origin.units]; - const eventData = publishHelper.getPublishContentEvent(contentMetaData, data.request.origin.textbook_id, units); + contentMetaData.channel = + _.get(data, 'request.origin.channel') || contentMetaData.channel + var units = _.isArray(data.request.origin.units) + ? data.request.origin.units + : [data.request.origin.units] + const eventData = publishHelper.getPublishContentEvent( + contentMetaData, + data.request.origin.textbook_id, + units + ) KafkaService.sendRecord(eventData, function (err, res) { if (err) { - logger.error({ msg: 'Error while sending event to kafka', err, additionalInfo: { eventData } }) + logger.error({ + msg: 'Error while sending event to kafka', + err, + additionalInfo: { eventData } + }) rspObj.errCode = programMessages.CONTENT_PUBLISH.FAILED_CODE rspObj.errMsg = 'Error while sending event to kafka' rspObj.responseCode = responseCode.SERVER_ERROR - return response.status(400).send(errorResponse(rspObj)); + return response.status(400).send(errorResponse(rspObj)) } else { rspObj.responseCode = 'OK' rspObj.result = { - 'publishStatus': `Publish Operation for Content Id ${data.request.content_id} Started Successfully!` + publishStatus: `Publish Operation for Content Id ${data.request.content_id} Started Successfully!` } - return response.status(200).send(successResponse(rspObj)); + return response.status(200).send(successResponse(rspObj)) } - }); + }) }, (error) => { rspObj.errCode = programMessages.CONTENT_PUBLISH.FAILED_CODE rspObj.errMsg = programMessages.CONTENT_PUBLISH.FAILED_MESSAGE rspObj.responseCode = responseCode.SERVER_ERROR - loggerError('Unable to publish content', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, error); - return response.status(400).send(errorResponse(rspObj)); + loggerError( + 'Unable to publish content', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + error + ) + return response.status(400).send(errorResponse(rspObj)) } ) } -function loggerError(msg, errCode, errMsg, responseCode, error, req) { - logger.error({ msg: msg, err: { errCode, errMsg, responseCode }, additionalInfo: { error } }, req) +function loggerError (msg, errCode, errMsg, responseCode, error, req) { + logger.error( + { + msg: msg, + err: { errCode, errMsg, responseCode }, + additionalInfo: { error } + }, + req + ) } -function health(req, response) { - return response.status(200).send(successResponse({ - apiId: 'api.program.health', - ver: '1.0', - msgid: uuid(), - responseCode: 'OK', - result: {} - })); +function health (req, response) { + return response.status(200).send( + successResponse({ + apiId: 'api.program.health', + ver: '1.0', + msgid: uuid(), + responseCode: 'OK', + result: {} + }) + ) } -function successResponse(data) { +function successResponse (data) { var response = {} response.id = data.apiId response.ver = data.apiVersion @@ -1714,7 +2332,7 @@ function successResponse(data) { * @param {Object} data * @returns {nm$_responseUtil.errorResponse.response} */ -function errorResponse(data) { +function errorResponse (data) { var response = {} response.id = data.apiId response.ver = data.apiVersion @@ -1725,7 +2343,7 @@ function errorResponse(data) { return response } -function getParams(msgId, status, errCode, msg) { +function getParams (msgId, status, errCode, msg) { var params = {} params.resmsgid = uuid() params.msgid = msgId || null @@ -1751,10 +2369,10 @@ module.exports.downloadNominationListAPI = downloadNominationList module.exports.programGetContentTypesAPI = getProgramContentTypes module.exports.getUserDetailsAPI = getUsersDetailsById module.exports.healthAPI = health -module.exports.programCopyCollectionAPI = programCopyCollections; -module.exports.getAllConfigurationsAPI = getAllConfigurations; -module.exports.getConfigurationByKeyAPI = getConfigurationByKey; +module.exports.programCopyCollectionAPI = programCopyCollections +module.exports.getAllConfigurationsAPI = getAllConfigurations +module.exports.getConfigurationByKeyAPI = getConfigurationByKey module.exports.downloadProgramDetailsAPI = downloadProgramDetails module.exports.generateApprovedContentReportAPI = generateApprovedContentReport module.exports.publishContentAPI = publishContent -module.exports.programCountsByOrgAPI = getProgramCountsByOrg \ No newline at end of file +module.exports.programCountsByOrgAPI = getProgramCountsByOrg diff --git a/src/service/registryService.js b/src/service/registryService.js index fae1d91ef9923dee9064be47547d836ff11ba11c..aeb41bbf7cd7d31e7d75058d05b1db2c37d36855 100644 --- a/src/service/registryService.js +++ b/src/service/registryService.js @@ -1,82 +1,79 @@ const envVariables = require('../envVariables') -const registryUrl = envVariables['OPENSABER_SERVICE_URL'] -const axios = require('axios'); - +const registryUrl = envVariables.OPENSABER_SERVICE_URL +const axios = require('axios') class RegistryService { - - constructor() { - } - - addRecord(value, callback) { - const headers = this.getDefaultHeaders() - axios.post(registryUrl+'/add', value.body, headers) - .then((res) =>{ - callback(null, res) - }, - (error)=>{ - callback(error) - }); - - } - - updateRecord(value, callback) { - const headers = this.getDefaultHeaders() - - axios.post(registryUrl+'/update', value.body, headers) - .then((res) =>{ - callback(null, res) - }, - (error)=>{ - callback(error) - }); - - } - - readRecord(value, callback) { - const headers = this.getDefaultHeaders() - - axios.post(registryUrl+'/read', value.body, headers) - .then((res) =>{ - callback(null, res) - }, - (error)=>{ - callback(error) - }); - } - - searchRecord(value, callback) { - const headers = this.getDefaultHeaders() - - axios.post(registryUrl+'/search', value.body, headers) - .then((res) =>{ - callback(null, res) - }, - (error)=>{ - callback(error,null) - }); - } - - searchAuditRecords(value, callback) { - const headers = this.getDefaultHeaders() - - axios.post(registryUrl+"/audit", value.body, headers) - .then((res) =>{ - callback(null, res) - }, - (error)=>{ - callback(error) - }); - } - - getDefaultHeaders() { - let headers = { - 'content-type': 'application/json', - 'accept': 'application/json' - } - return headers; + addRecord (value, callback) { + const headers = this.getDefaultHeaders() + axios.post(registryUrl + '/add', value.body, headers).then( + (res) => { + callback(null, res) + }, + (error) => { + callback(error) + } + ) + } + + updateRecord (value, callback) { + const headers = this.getDefaultHeaders() + + axios.post(registryUrl + '/update', value.body, headers).then( + (res) => { + callback(null, res) + }, + (error) => { + callback(error) + } + ) + } + + readRecord (value, callback) { + const headers = this.getDefaultHeaders() + + axios.post(registryUrl + '/read', value.body, headers).then( + (res) => { + callback(null, res) + }, + (error) => { + callback(error) + } + ) + } + + searchRecord (value, callback) { + const headers = this.getDefaultHeaders() + + axios.post(registryUrl + '/search', value.body, headers).then( + (res) => { + callback(null, res) + }, + (error) => { + callback(error, null) + } + ) + } + + searchAuditRecords (value, callback) { + const headers = this.getDefaultHeaders() + + axios.post(registryUrl + '/audit', value.body, headers).then( + (res) => { + callback(null, res) + }, + (error) => { + callback(error) + } + ) + } + + getDefaultHeaders () { + const headers = { + 'content-type': 'application/json', + accept: 'application/json' } + return headers + } } - -module.exports = RegistryService; +module.exports = RegistryService diff --git a/src/service/telemetryService.js b/src/service/telemetryService.js index f33a47e208adda3c4ae3811c163994e229632844..205bedef00ecdf41e452f115802ce18ada9aef90 100644 --- a/src/service/telemetryService.js +++ b/src/service/telemetryService.js @@ -1,38 +1,41 @@ -const TelemetryServiceInstance = require('sb_telemetry_util'); -const envVariables = require('../envVariables'); -const _ = require("lodash"); -const telemetryEventConfig = require('../config/telemetryEventConfig.json'); +const TelemetryServiceInstance = require('sb_telemetry_util') +const envVariables = require('../envVariables') +const _ = require('lodash') +const telemetryEventConfig = require('../config/telemetryEventConfig.json') -const telemetryInstance = new TelemetryServiceInstance(); +const telemetryInstance = new TelemetryServiceInstance() -function initTelemetry() { - config = { - host: envVariables.telemetryConfig.host, - endpoint: envVariables.telemetryConfig.endpoint, - method: envVariables.telemetryConfig.method, - batchsize: 10 - } - telemetryInstance.init(config); +function initTelemetry () { + var config = { + host: envVariables.telemetryConfig.host, + endpoint: envVariables.telemetryConfig.endpoint, + method: envVariables.telemetryConfig.method, + batchsize: 10 + } + telemetryInstance.init(config) } -function generateAuditEvent(DBinstance, model, action) { - const event = {}; - event['context'] = { - pdata: telemetryEventConfig.pdata, - env: model.name, - channel: '' - } - event['edata'] = { - state: DBinstance.status || '', - prevstate: action === 'create' ? '' : DBinstance.previous().status || DBinstance.status, - props: _.keys(DBinstance.previous()) - } - event['object'] = { - id: DBinstance[model.primaryKeyAttributes[0]] || '', - type: model.name - } - telemetryInstance.audit(event); +function generateAuditEvent (DBinstance, model, action) { + const event = {} + event.context = { + pdata: telemetryEventConfig.pdata, + env: model.name, + channel: '' + } + event.edata = { + state: DBinstance.status || '', + prevstate: + action === 'create' + ? '' + : DBinstance.previous().status || DBinstance.status, + props: _.keys(DBinstance.previous()) + } + event.object = { + id: DBinstance[model.primaryKeyAttributes[0]] || '', + type: model.name + } + telemetryInstance.audit(event) } module.exports.initializeTelemetryService = initTelemetry -module.exports.generateAuditEvent = generateAuditEvent \ No newline at end of file +module.exports.generateAuditEvent = generateAuditEvent diff --git a/src/service/userProgramPreference.js b/src/service/userProgramPreference.js index 423a02096208766b79c13afa6eac588ef16ddcee..caa3e60737a8e6b40cc20b9a8cd171e8269fb0a5 100644 --- a/src/service/userProgramPreference.js +++ b/src/service/userProgramPreference.js @@ -1,92 +1,109 @@ -const _ = require("lodash"); -const uuid = require("uuid/v1"); -const logger = require('sb_logger_util_v2'); -const messageUtils = require('./messageUtil'); -const Sequelize = require('sequelize'); -const moment = require('moment'); -const responseCode = messageUtils.RESPONSE_CODE; -const programMessages = messageUtils.PROGRAM; -const model = require('../models'); -const { - forkJoin -} = require('rxjs'); -const envVariables = require('../envVariables'); -const RedisManager = require('../helpers/redisUtil'); -var async = require('async'); -const redisManager = new RedisManager(); +const _ = require('lodash') +const uuid = require('uuid/v1') +const logger = require('sb_logger_util_v2') +const messageUtils = require('./messageUtil') +const moment = require('moment') +const responseCode = messageUtils.RESPONSE_CODE +const programMessages = messageUtils.PROGRAM +const model = require('../models') +const RedisManager = require('../helpers/redisUtil') +const redisManager = new RedisManager() -function getPreferences(req, response) { - var data = req.body; - var rspObj = req.rspObj; - rspObj.apiId = 'api.preference.read'; +function getPreferences (req, response) { + var data = req.body + var rspObj = req.rspObj + rspObj.apiId = 'api.preference.read' rspObj.apiVersion = '1.0' if (!data.request || !data.request.program_id || !data.request.user_id) { rspObj.errCode = programMessages.PREFERENCES.READ.MISSING_CODE rspObj.errMsg = programMessages.PREFERENCES.READ.MISSING_MESSAGE - rspObj.responseCode = responseCode.CLIENT_ERROR; - loggerError('Error due to missing request or user_id or program_id', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, null, req) + rspObj.responseCode = responseCode.CLIENT_ERROR + loggerError( + 'Error due to missing request or user_id or program_id', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + null, + req + ) return response.status(400).send(errorResponse(rspObj)) } - var redisKey = data.request.user_id + ':' + data.request.program_id; + var redisKey = data.request.user_id + ':' + data.request.program_id redisManager.getData(redisKey, (err, cacheData) => { if (err || !cacheData) { // If redis cache is failed to give the response - getPreferencefromtable(data.request.user_id, data.request.program_id).then((result) => { + getPreferencefromtable( + data.request.user_id, + data.request.program_id + ).then((result) => { if (!result.error) { - setDatainRedis(data.request.user_id, data.request.program_id, result.res, true, req); + setDatainRedis( + data.request.user_id, + data.request.program_id, + result.res, + true, + req + ) rspObj.result = { - 'contributor_preference': {}, - 'sourcing_preference': {}, - 'synced': true + contributor_preference: {}, + sourcing_preference: {}, + synced: true } if (result.res !== null) { - rspObj.result.contributor_preference = result.res.contributor_preference, + rspObj.result.contributor_preference = + result.res.contributor_preference rspObj.result.sourcing_preference = result.res.sourcing_preference } - rspObj.responseCode = 'OK'; - return response.status(200).send(successResponse(rspObj)); + rspObj.responseCode = 'OK' + return response.status(200).send(successResponse(rspObj)) } else { - rspObj.responseCode = 'ERR_GET_USER_PREFERENCE_FAILED'; - rspObj.result = result.result; - return response.status(400).send(errorResponse(rspObj)); + rspObj.responseCode = 'ERR_GET_USER_PREFERENCE_FAILED' + rspObj.result = result.result + return response.status(400).send(errorResponse(rspObj)) } - }); + }) } else { // sync back cache data to user_preferences table - syncCacheToPreferenceTable(data.request.user_id, data.request.program_id, cacheData); + syncCacheToPreferenceTable( + data.request.user_id, + data.request.program_id, + cacheData + ) rspObj.responseCode = 'OK' - rspObj.result = JSON.parse(cacheData); + rspObj.result = JSON.parse(cacheData) return response.status(200).send(successResponse(rspObj)) } - }); + }) } -function getPreferencefromtable(userId, programId) { +function getPreferencefromtable (userId, programId) { return new Promise((resolve, reject) => { - const retObj = { error: false, res: {} }; - model.user_program_preference.findOne({ - where: { - user_id: userId, - program_id: programId, - } - }).then(function (res) { - retObj.res = res; - return resolve(retObj); - }).catch(function (err) { - retObj.error = true; - retObj.res = err; - return reject(retObj); - }); - }); + const retObj = { error: false, res: {} } + model.user_program_preference + .findOne({ + where: { + user_id: userId, + program_id: programId + } + }) + .then(function (res) { + retObj.res = res + return resolve(retObj) + }) + .catch(function (err) { + retObj.error = true + retObj.res = err + return reject(retObj) + }) + }) } -function addPreferencetotable(userId, programId, preferenceObj) { +function addPreferencetotable (userId, programId, preferenceObj) { return new Promise((resolve, reject) => { - const retObj = { error: false, res: {} }; + const retObj = { error: false, res: {} } // add preference const insertObj = { user_id: userId, @@ -94,240 +111,312 @@ function addPreferencetotable(userId, programId, preferenceObj) { contributor_preference: preferenceObj.contributor_preference, sourcing_preference: preferenceObj.sourcing_preference, createdby: userId, - createdon: new Date(), + createdon: new Date() } - model.user_program_preference.create(insertObj).then(res => { - retObj.res = res.dataValues; - return resolve(retObj); - }).catch(function (err) { - retObj.error = true; - retObj.res = err; - return reject(retObj); - }); - }); + model.user_program_preference + .create(insertObj) + .then((res) => { + retObj.res = res.dataValues + return resolve(retObj) + }) + .catch(function (err) { + retObj.error = true + retObj.res = err + return reject(retObj) + }) + }) } -function updatePreferencetotable(userId, programId, preferenceObj) { +function updatePreferencetotable (userId, programId, preferenceObj) { return new Promise((resolve, reject) => { - const retObj = { error: false, res: {} }; + const retObj = { error: false, res: {} } const updateQuery = { where: { user_id: userId, program_id: programId } - }; + } const updateValue = { contributor_preference: preferenceObj.contributor_preference, sourcing_preference: preferenceObj.sourcing_preference, updatedBy: userId, - updatedOn: new Date(), + updatedOn: new Date() } - model.user_program_preference.update(updateValue, updateQuery).then(resData => { - if (_.isArray(resData) && !resData[0]) { - retObj.error = true; - retObj.res = "Record not found"; - return resolve(retObj); - } - else { - retObj.res = updateValue; - return resolve(retObj); - } - }).catch(function (err) { - retObj.error = true; - retObj.res = err; - return reject(retObj); - }); - }); + model.user_program_preference + .update(updateValue, updateQuery) + .then((resData) => { + if (_.isArray(resData) && !resData[0]) { + retObj.error = true + retObj.res = 'Record not found' + return resolve(retObj) + } else { + retObj.res = updateValue + return resolve(retObj) + } + }) + .catch(function (err) { + retObj.error = true + retObj.res = err + return reject(retObj) + }) + }) } -function setDatainRedis(userId, programId, obj, syncFlag, req = {}) { +function setDatainRedis (userId, programId, obj, syncFlag, req = {}) { const redisValue = { - 'contributor_preference': {}, - 'sourcing_preference': {}, - 'synced': syncFlag + contributor_preference: {}, + sourcing_preference: {}, + synced: syncFlag } // So if the data is being written in redis only, the sync flag will be false and hence to keep the timestamp when data was first updated, the timestamp should be updated when synced - redisValue.timestamp = (!syncFlag && obj.timestamp !== undefined) ? obj.timestamp : new Date(); - redisValue.contributor_preference = (!_.isEmpty(obj) && obj.contributor_preference !== undefined) ? obj.contributor_preference : {}; - redisValue.sourcing_preference = (!_.isEmpty(obj) && obj.sourcing_preference !== undefined) ? obj.sourcing_preference : {}; + redisValue.timestamp = + !syncFlag && obj.timestamp !== undefined ? obj.timestamp : new Date() + redisValue.contributor_preference = + !_.isEmpty(obj) && obj.contributor_preference !== undefined + ? obj.contributor_preference + : {} + redisValue.sourcing_preference = + !_.isEmpty(obj) && obj.sourcing_preference !== undefined + ? obj.sourcing_preference + : {} - redisManager.setData({ key: `${userId}:${programId}`, value: JSON.stringify(redisValue) }, + redisManager.setData( + { key: `${userId}:${programId}`, value: JSON.stringify(redisValue) }, function (err, cacheCSVData) { if (err) { - logger.error({ msg: 'Error - caching', err, additionalInfo: { preference: obj } }, req); + logger.error( + { msg: 'Error - caching', err, additionalInfo: { preference: obj } }, + req + ) } else { // Whenever writing to redis, if the syncFlag is false, i.e. data is not synched yet, sync it to database - if (syncFlag == false) { - syncCacheToPreferenceTable(userId, programId, redisValue); + if (syncFlag === false) { + syncCacheToPreferenceTable(userId, programId, redisValue) } - logger.debug({ msg: 'Caching preferences - done', additionalInfo: { preference: obj } }, req); + logger.debug( + { + msg: 'Caching preferences - done', + additionalInfo: { preference: obj } + }, + req + ) } - }); + } + ) } -function syncCacheToPreferenceTable(userId, programId, cacheObj) { +function syncCacheToPreferenceTable (userId, programId, cacheObj) { // check if the cacheObj.timestamp and current time has 4 Hours of difference - if (cacheObj.timestamp && diffinHours(cacheObj.timestamp) > 4 && !cacheObj.synced) { + if ( + cacheObj.timestamp && + diffinHours(cacheObj.timestamp) > 4 && + !cacheObj.synced + ) { // sync the cache data back to userpreference table // find if the entry for the user_id and program_id exists getPreferencefromtable(userId, programId).then((result) => { if (result.error) { - logger.error({ - msg: 'syncing caching preferences - failed - error while checking if record exists', - additionalInfo: { - key: `${userId} : ${programId}`, - preference: cacheObj - } - }, {}); + logger.error( + { + msg: + 'syncing caching preferences - failed - error while checking if record exists', + additionalInfo: { + key: `${userId} : ${programId}`, + preference: cacheObj + } + }, + {} + ) } if (!result.res) { addPreferencetotable(userId, programId, cacheObj).then((addRes) => { if (addRes.error) { - logger.error({ - msg: 'syncing caching preferences - failed', - additionalInfo: { - key: `${userId} : ${programId}`, - preference: cacheObj - } - }, {}); + logger.error( + { + msg: 'syncing caching preferences - failed', + additionalInfo: { + key: `${userId} : ${programId}`, + preference: cacheObj + } + }, + {} + ) + } else { + const tableRes = addRes.res + setDatainRedis(userId, programId, tableRes, true) + logger.info( + { + msg: 'syncing caching preferences - done', + additionalInfo: { + key: `${userId} : ${programId}`, + preference: cacheObj + } + }, + {} + ) } - else { - const tableRes = addRes.res; - setDatainRedis(userId, programId, tableRes, true); - logger.info({ - msg: 'syncing caching preferences - done', - additionalInfo: { - key: `${userId} : ${programId}`, - preference: cacheObj - } - }, {}); - } - }); + }) } else if (result.res.id) { - updatePreferencetotable(userId, programId, cacheObj).then((updateRes) => { - if (updateRes.error) { - logger.error({ - msg: 'syncing caching preferences - failed', - additionalInfo: { - key: `${userId} : ${programId}`, - preference: cacheObj - } - }, {}); - } - else { - setDatainRedis(userId, programId, cacheObj, true); - logger.info({ - msg: 'syncing caching preferences - done', - additionalInfo: { - key: `${userId} : ${programId}`, - preference: cacheObj - } - }, {}); + updatePreferencetotable(userId, programId, cacheObj).then( + (updateRes) => { + if (updateRes.error) { + logger.error( + { + msg: 'syncing caching preferences - failed', + additionalInfo: { + key: `${userId} : ${programId}`, + preference: cacheObj + } + }, + {} + ) + } else { + setDatainRedis(userId, programId, cacheObj, true) + logger.info( + { + msg: 'syncing caching preferences - done', + additionalInfo: { + key: `${userId} : ${programId}`, + preference: cacheObj + } + }, + {} + ) + } } - }); + ) } - }); + }) } } -function setPreferences(req, response) { +function setPreferences (req, response) { var data = req.body var rspObj = req.rspObj - rspObj.apiId = 'api.preference.create'; - rspObj.apiVersion = '1.0'; + rspObj.apiId = 'api.preference.create' + rspObj.apiVersion = '1.0' - if (!data.request || !data.request.program_id || !data.request.user_id || !data.request.preference) { + if ( + !data.request || + !data.request.program_id || + !data.request.user_id || + !data.request.preference + ) { rspObj.errCode = programMessages.PREFERENCES.CREATE.MISSING_CODE rspObj.errMsg = programMessages.PREFERENCES.CREATE.MISSING_MESSAGE - rspObj.responseCode = responseCode.CLIENT_ERROR; - loggerError('Error due to missing request or user_id or program_id or preference', - rspObj.errCode, rspObj.errMsg, rspObj.responseCode, null, req) + rspObj.responseCode = responseCode.CLIENT_ERROR + loggerError( + 'Error due to missing request or user_id or program_id or preference', + rspObj.errCode, + rspObj.errMsg, + rspObj.responseCode, + null, + req + ) return response.status(400).send(errorResponse(rspObj)) } // Todo- check if the preferences is json of MSG - const userId = data.request.user_id; - const programId = data.request.program_id; - const preference = data.request.preference; + const userId = data.request.user_id + const programId = data.request.program_id + const preference = data.request.preference - data.request.sourcing_preference = {}; - data.request.contributor_preference = {}; + data.request.sourcing_preference = {} + data.request.contributor_preference = {} if (data.request.type && data.request.type === 'sourcing') { - data.request.sourcing_preference = preference; + data.request.sourcing_preference = preference } else { - data.request.contributor_preference = preference; + data.request.contributor_preference = preference } - rspObj.result = _.cloneDeep(data.request); - delete(rspObj.result['preference']); + rspObj.result = _.cloneDeep(data.request) + delete rspObj.result.preference - var redisKey = userId + ':' + programId; + var redisKey = userId + ':' + programId redisManager.getData(redisKey, (err, cacheData) => { if (err || !cacheData) { // If redis cache is failed to give the response getPreferencefromtable(userId, programId).then((result) => { if (result.error) { - rspObj.responseCode = 'ERR_GET_USER_PREFERENCE_FAILED'; - rspObj.result = result.result; - return response.status(400).send(errorResponse(rspObj)); + rspObj.responseCode = 'ERR_GET_USER_PREFERENCE_FAILED' + rspObj.result = result.result + return response.status(400).send(errorResponse(rspObj)) } if (!result.res) { - addPreferencetotable(userId, programId, data.request).then((addRes) => { - if (addRes.error) { - rspObj.errMsg = programMessages.PREFERENCES.CREATE.FAILED_MESSAGE - rspObj.responseCode = programMessages.PREFERENCES.CREATE.FAILED_CODE; - rspObj.result = addRes.res; - return response.status(400).send(errorResponse(rspObj)); - } - else { - const tableRes = addRes.res; - setDatainRedis(userId, programId, tableRes, true); - rspObj.responseCode = 'OK'; - return response.status(200).send(successResponse(rspObj)); + addPreferencetotable(userId, programId, data.request).then( + (addRes) => { + if (addRes.error) { + rspObj.errMsg = + programMessages.PREFERENCES.CREATE.FAILED_MESSAGE + rspObj.responseCode = + programMessages.PREFERENCES.CREATE.FAILED_CODE + rspObj.result = addRes.res + return response.status(400).send(errorResponse(rspObj)) + } else { + const tableRes = addRes.res + setDatainRedis(userId, programId, tableRes, true) + rspObj.responseCode = 'OK' + return response.status(200).send(successResponse(rspObj)) + } } - }); + ) } else if (result.res.id) { - updatePreferencetotable(userId, programId, data.request).then((updateRes) => { - if (updateRes.error) { - rspObj.errMsg = programMessages.PREFERENCES.UPDATE.FAILED_MESSAGE - rspObj.responseCode = programMessages.PREFERENCES.UPDATE.FAILED_CODE; - rspObj.result = updateRes.res; - return response.status(400).send(errorResponse(rspObj)); - } - else { - const tableRes = updateRes.res; - setDatainRedis(userId, programId, tableRes, true); - rspObj.responseCode = 'OK'; - return response.status(200).send(successResponse(rspObj)); + updatePreferencetotable(userId, programId, data.request).then( + (updateRes) => { + if (updateRes.error) { + rspObj.errMsg = + programMessages.PREFERENCES.UPDATE.FAILED_MESSAGE + rspObj.responseCode = + programMessages.PREFERENCES.UPDATE.FAILED_CODE + rspObj.result = updateRes.res + return response.status(400).send(errorResponse(rspObj)) + } else { + const tableRes = updateRes.res + setDatainRedis(userId, programId, tableRes, true) + rspObj.responseCode = 'OK' + return response.status(200).send(successResponse(rspObj)) + } } - }); + ) } - }); + }) } else { - data.request.timestamp = JSON.parse(cacheData).timestamp; - setDatainRedis(data.request.user_id, data.request.program_id, data.request, false); - rspObj.responseCode = 'OK'; - return response.status(200).send(successResponse(rspObj)); + data.request.timestamp = JSON.parse(cacheData).timestamp + setDatainRedis( + data.request.user_id, + data.request.program_id, + data.request, + false + ) + rspObj.responseCode = 'OK' + return response.status(200).send(successResponse(rspObj)) } - }); + }) } -function diffinHours(checkDateTime) { - var cacheTime = moment(checkDateTime, 'YYYY-MM-DD HH:mm:ss'); - var now = moment(new Date(), 'YYYY-MM-DD HH:mm:ss'); - var duration = moment.duration(now.diff(cacheTime)); - return duration.asHours(); +function diffinHours (checkDateTime) { + var cacheTime = moment(checkDateTime, 'YYYY-MM-DD HH:mm:ss') + var now = moment(new Date(), 'YYYY-MM-DD HH:mm:ss') + var duration = moment.duration(now.diff(cacheTime)) + return duration.asHours() } -function loggerError(msg, errCode, errMsg, responseCode, error, req) { - logger.error({ msg: msg, err: { errCode, errMsg, responseCode }, additionalInfo: { error } }, req) +function loggerError (msg, errCode, errMsg, responseCode, error, req) { + logger.error( + { + msg: msg, + err: { errCode, errMsg, responseCode }, + additionalInfo: { error } + }, + req + ) } -function successResponse(data) { +function successResponse (data) { var response = {} response.id = data.apiId response.ver = data.apiVersion @@ -343,7 +432,7 @@ function successResponse(data) { * @param {Object} data * @returns {nm$_responseUtil.errorResponse.response} */ -function errorResponse(data) { +function errorResponse (data) { var response = {} response.id = data.apiId response.ver = data.apiVersion @@ -354,7 +443,7 @@ function errorResponse(data) { return response } -function getParams(msgId, status, errCode, msg) { +function getParams (msgId, status, errCode, msg) { var params = {} params.resmsgid = uuid() params.msgid = msgId || null @@ -365,6 +454,5 @@ function getParams(msgId, status, errCode, msg) { return params } -module.exports.setUserPreferences = setPreferences; -module.exports.getUserPreferences = getPreferences; - +module.exports.setUserPreferences = setPreferences +module.exports.getUserPreferences = getPreferences diff --git a/src/service/utilsService.js b/src/service/utilsService.js index 018c867d172f157d7fde4438198f3bdb4fd552f1..22603716a8a0e4964852b54972447f6ae40d569b 100644 --- a/src/service/utilsService.js +++ b/src/service/utilsService.js @@ -17,9 +17,12 @@ var configUtil = require('sb-config-util') * @returns {getAppIDForRESP.appId|String} */ function getAppIDForRESP (path) { - var arr = path.split(':')[0].split('/').filter(function (n) { - return n !== '' - }) + var arr = path + .split(':')[0] + .split('/') + .filter(function (n) { + return n !== '' + }) var appId if (arr.length === 1) { appId = 'api.' + arr[arr.length - 1] @@ -33,30 +36,30 @@ function getLoggerData (rspObj, level, file, method, message, data, stacktrace) var newDataObj = {} if (data && data.headers && data.headers.telemetryData) { newDataObj = JSON.parse(JSON.stringify(data)) - delete newDataObj.headers['telemetryData'] + delete newDataObj.headers.telemetryData } else { newDataObj = data } var dataObj = { - 'eid': 'BE_LOG', - 'did': rspObj.did, - 'ets': Date.now(), - 'ver': '1.0', - 'mid': rspObj.msgid, - 'context': { - 'pdata': { - 'id': rspObj.apiId, - 'ver': rspObj.apiVersion + eid: 'BE_LOG', + did: rspObj.did, + ets: Date.now(), + ver: '1.0', + mid: rspObj.msgid, + context: { + pdata: { + id: rspObj.apiId, + ver: rspObj.apiVersion } }, - 'edata': { - 'eks': { - 'level': level, - 'class': file, - 'method': method, - 'message': message, - 'data': newDataObj, - 'stacktrace': stacktrace + edata: { + eks: { + level: level, + class: file, + method: method, + message: message, + data: newDataObj, + stacktrace: stacktrace } } } @@ -64,26 +67,34 @@ function getLoggerData (rspObj, level, file, method, message, data, stacktrace) return dataObj } -function getPerfLoggerData (rspObj, level, file, method, message, data, stacktrace) { +function getPerfLoggerData ( + rspObj, + level, + file, + method, + message, + data, + stacktrace +) { var dataObj = { - 'eid': 'PERF_LOG', - 'ets': Date.now(), - 'ver': '1.0', - 'mid': rspObj.msgid, - 'context': { - 'pdata': { - 'id': rspObj.apiId, - 'ver': rspObj.apiVersion + eid: 'PERF_LOG', + ets: Date.now(), + ver: '1.0', + mid: rspObj.msgid, + context: { + pdata: { + id: rspObj.apiId, + ver: rspObj.apiVersion } }, - 'edata': { - 'eks': { - 'level': level, - 'class': file, - 'method': method, - 'message': message, - 'data': data, - 'stacktrace': stacktrace + edata: { + eks: { + level: level, + class: file, + method: method, + message: message, + data: data, + stacktrace: stacktrace } } } @@ -98,11 +109,11 @@ function getPerfLoggerData (rspObj, level, file, method, message, data, stacktra function getParamsDataForLogEvent (data) { const url = getApiUrl(data.path) const params = [ - {'rid': data.msgid}, - {'title': API_CONFIG[url] && API_CONFIG[url].title}, - {'category': API_CONFIG[url] && API_CONFIG[url].category}, - {'url': url}, - {'method': data.method} + { rid: data.msgid }, + { title: API_CONFIG[url] && API_CONFIG[url].title }, + { category: API_CONFIG[url] && API_CONFIG[url].category }, + { url: url }, + { method: data.method } ] return params } @@ -140,7 +151,7 @@ function getTelemetryContextData (req) { * @param {Object} req */ function updateContextData (oldData, newData) { - let contextData = {} + const contextData = {} contextData.channel = newData.channel || oldData.channel contextData.env = newData.env || oldData.env contextData.cdata = newData.cdata || oldData.cdata @@ -157,16 +168,21 @@ function getTelemetryActorData (req) { if (req.rspObj && req.rspObj.userId) { actor.id = _.toString(req.rspObj.userId) actor.type = 'user' - } else if (req && req['headers'] && req['headers'] && req['headers']['x-authenticated-user-token']) { - var payload = jwt.decode(req['headers']['x-authenticated-user-token']) - var userId = payload['sub'].split(':') + } else if ( + req && + req.headers && + req.headers && + req.headers['x-authenticated-user-token'] + ) { + var payload = jwt.decode(req.headers['x-authenticated-user-token']) + var userId = payload.sub.split(':') actor.id = userId[userId.length - 1] actor.type = 'user' } else { actor.id = _.toString(req.headers['x-consumer-id']) actor.type = req.headers['x-consumer-username'] } - if (!actor['id'] || actor['id'] === '') { + if (!actor.id || actor.id === '') { actor.id = _.toString(process.pid) actor.type = 'service' } @@ -191,7 +207,9 @@ function getObjectData (id, type, ver, rollup) { * @param {object} res */ function getHttpStatus (res) { - return res && res.statusCode >= 100 && res.statusCode < 600 ? res.statusCode : 500 + return res && res.statusCode >= 100 && res.statusCode < 600 + ? res.statusCode + : 500 } /** @@ -201,11 +219,20 @@ function getHttpStatus (res) { * @param {object} msgObject */ function getErrorResponse (rspObj, serverRsp, msgObject) { - rspObj.errCode = _.get(serverRsp, 'params.err') ? serverRsp.params.err - : (msgObject && msgObject['FAILED_CODE'] ? msgObject['FAILED_CODE'] : null) - rspObj.errMsg = _.get(serverRsp, 'params.errmsg') ? serverRsp.params.errmsg - : (msgObject && msgObject['FAILED_MESSAGE'] ? msgObject['FAILED_MESSAGE'] : null) - rspObj.responseCode = serverRsp && serverRsp.responseCode ? serverRsp.responseCode : responseCode['SERVER_ERROR'] + rspObj.errCode = _.get(serverRsp, 'params.err') + ? serverRsp.params.err + : msgObject && msgObject.FAILED_CODE + ? msgObject.FAILED_CODE + : null + rspObj.errMsg = _.get(serverRsp, 'params.errmsg') + ? serverRsp.params.errmsg + : msgObject && msgObject.FAILED_MESSAGE + ? msgObject.FAILED_MESSAGE + : null + rspObj.responseCode = + serverRsp && serverRsp.responseCode + ? serverRsp.responseCode + : responseCode.SERVER_ERROR return rspObj }