From d8af60b54a700736e31e30f2391e1d13dcf395f4 Mon Sep 17 00:00:00 2001 From: Kartheek Palla <palla.kartheekreddy@gmail.com> Date: Mon, 22 Jun 2020 22:12:00 +0530 Subject: [PATCH] Issue #DP-728 fix: eslint changes --- .gitignore | 2 - src/.eslintrc.js | 15 + src/.eslintrc.json | 9 + src/.gitignore | 3 + src/app.js | 75 +- src/envVariables.js | 60 +- src/helpers/helperService.js | 25 +- src/helpers/kafkaUtil.js | 15 +- src/helpers/programHelper.js | 806 ++++--- src/helpers/publishHelper.js | 119 +- src/helpers/redisUtil.js | 180 +- src/helpers/updateHierarchy.helper.js | 281 +-- src/middlewares/request.middleware.js | 432 ++-- src/models/configuration.js | 76 +- src/models/contenttypes.js | 56 +- src/models/index.js | 45 +- src/models/nomination.js | 22 +- src/models/program.js | 180 +- src/models/user_preference.js | 20 +- src/package-lock.json | 1372 ++++++++++++ src/package.json | 10 + src/routes/index.js | 9 - src/routes/programRoutes.js | 302 ++- src/routes/users.js | 9 - src/service/messageUtil.js | 146 +- src/service/programService.js | 2920 +++++++++++++++---------- src/service/registryService.js | 149 +- src/service/telemetryService.js | 65 +- src/service/userProgramPreference.js | 516 +++-- src/service/utilsService.js | 135 +- 30 files changed, 5340 insertions(+), 2714 deletions(-) delete mode 100644 .gitignore create mode 100644 src/.eslintrc.js create mode 100644 src/.eslintrc.json create mode 100644 src/.gitignore delete mode 100644 src/routes/index.js delete mode 100644 src/routes/users.js diff --git a/.gitignore b/.gitignore deleted file mode 100644 index fed401d..0000000 --- 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 0000000..d85cd21 --- /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 0000000..71ac1f7 --- /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 0000000..c7895cd --- /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 e1d0324..275426f 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 e29158d..cecf7a1 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 0c76a2e..8e4c7dd 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 68d422b..0116926 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 a949382..1a64e5a 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 dd4948b..4a3af3b 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 275ec1b..a78dc1e 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 7b89d89..016d354 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 b391bab..cefd54e 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 db63e72..dd864aa 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 03b32fb..e20e53e 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 3d83cf8..f735991 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 361cad6..c4607cf 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 d56013b..8e016ef 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 9745e97..d1ce3d2 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 a705a5f..a6bbe8e 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 7b7b14e..f943bcd 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 ecca96a..0000000 --- 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 f857a24..417b8ee 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 623e430..0000000 --- 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 c60ccf9..1a88ef7 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 33780db..0f8601d 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 fae1d91..aeb41bb 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 f33a47e..205bede 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 423a020..caa3e60 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 018c867..2260371 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 } -- GitLab