diff --git a/src/lib/app/class_allapps.js b/src/lib/app/class_allapps.js index c4888c3..4d0e837 100644 --- a/src/lib/app/class_allapps.js +++ b/src/lib/app/class_allapps.js @@ -2,11 +2,12 @@ import * as rax from 'retry-axios'; import axios from 'axios'; import path from 'node:path'; import FormData from 'form-data'; -import fs from "node:fs/promises"; +import fs from 'node:fs/promises'; import fs2 from 'node:fs'; import { v4 as uuidv4, validate } from 'uuid'; import yesno from 'yesno'; -import { logger, execPath, mergeDirFilePath, verifyFileExists, sleep, isPkg } from '../../globals.js'; + +import { logger, execPath, mergeDirFilePath, verifyFileExists, sleep } from '../../globals.js'; import { setupQrsConnection } from '../util/qseow/qrs.js'; import { getAppColumnPosFromHeaderRow } from '../util/qseow/lookups.js'; import QlikSenseApp from './class_app.js'; @@ -14,6 +15,7 @@ import { getTagIdByName } from '../util/qseow/tag.js'; import { getAppById, deleteAppById } from '../util/qseow/app.js'; import { getCustomPropertyDefinitionByName, doesCustomPropertyValueExist } from '../util/qseow/customproperties.js'; import { catchLog } from '../util/log.js'; +import { getCertFilePaths } from '../util/qseow/cert.js'; class QlikSenseApps { constructor() { @@ -25,12 +27,14 @@ class QlikSenseApps { this.appList = []; this.options = options; - // Should cerrificates be used for authentication? + // Should certificates be used for authentication? if (options.authType === 'cert') { - // Make sure certificates exist - this.fileCert = path.resolve(execPath, options.authCertFile); - this.fileCertKey = path.resolve(execPath, options.authCertKeyFile); - this.fileCertCA = path.resolve(execPath, options.authRootCertFile); + // Get certificate paths + const { fileCert, fileCertKey, fileCertCA } = getCertFilePaths(options); + + this.fileCert = fileCert; + this.fileCertKey = fileCertKey; + this.fileCertCA = fileCertCA; } // Map that will connect app counter from Excel file with ID an app gets after import to QSEoW @@ -117,7 +121,7 @@ class QlikSenseApps { } } - // Should cerrificates be used for authentication? + // Should certificates be used for authentication? let axiosConfig; if (this.options.authType === 'cert') { if (filter === '') { @@ -309,7 +313,7 @@ class QlikSenseApps { .map((cp) => cp.trim()); if (tmpCustomProperty?.length === 2) { - const customProperty = await getCustomPropertyDefinitionByName('App', tmpCustomProperty[0], cpExisting); + const customProperty = getCustomPropertyDefinitionByName('App', tmpCustomProperty[0], cpExisting); if (customProperty === false) { // Failed getting custom property id, most likely because the custom property does not exist. logger.error( @@ -321,7 +325,7 @@ class QlikSenseApps { } // Verify custom property value is valid - const cpValueExists = await doesCustomPropertyValueExist( + const cpValueExists = doesCustomPropertyValueExist( 'App', tmpCustomProperty[0], tmpCustomProperty[1], @@ -542,7 +546,7 @@ class QlikSenseApps { // Function to update tags, custom properties and owner of uploaded app async updateUploadedApp(newApp, uploadedAppId) { try { - // Should cerrificates be used for authentication? + // Should certificates be used for authentication? let axiosConfigUploadedApp; if (this.options.authType === 'cert') { // Get info about just uploaded app @@ -584,7 +588,7 @@ class QlikSenseApps { `userDirectory eq '${newApp.appOwnerUserDirectory}' and userId eq '${newApp.appOwnerUserId}'` ); - // Should cerrificates be used for authentication? + // Should certificates be used for authentication? let axiosConfigUser; if (this.options.authType === 'cert') { // Get info about just uploaded app @@ -633,7 +637,7 @@ class QlikSenseApps { // Pause for a while to let Sense repository catch up await sleep(1000); - // Should cerrificates be used for authentication? + // Should certificates be used for authentication? let axiosConfig2; if (this.options.authType === 'cert') { // Uppdate app with tags, custom properties and app owner @@ -855,7 +859,7 @@ class QlikSenseApps { { name: 'name', value: appName }, ]; - // Should cerrificates be used for authentication? + // Should certificates be used for authentication? let axiosConfig; if (this.options.authType === 'cert') { // Build QRS query @@ -901,7 +905,7 @@ class QlikSenseApps { // Define query parameters const queryParameters = [{ name: 'app', value: targetAppId }]; - // Should cerrificates be used for authentication? + // Should certificates be used for authentication? let axiosConfig; if (this.options.authType === 'cert') { // Build QRS query @@ -962,7 +966,7 @@ class QlikSenseApps { filter = encodeURIComponent(`stream.name eq '${streamName}' and name eq '${appName}'`); } - // Should cerrificates be used for authentication? + // Should certificates be used for authentication? let axiosConfig; if (this.options.authType === 'cert') { // Build QRS query @@ -1009,7 +1013,7 @@ class QlikSenseApps { // Build QRS query const filter = encodeURIComponent(`stream.name eq '${streamName}' and name eq '${appName}'`); - // Should cerrificates be used for authentication? + // Should certificates be used for authentication? let axiosConfig; if (this.options.authType === 'cert') { // Build QRS query @@ -1073,7 +1077,7 @@ class QlikSenseApps { if (validate(uploadedAppInfo.appPublishToStream)) { // It's a valid GUID - // Should cerrificates be used for authentication? + // Should certificates be used for authentication? if (this.options.authType === 'cert') { // Build QRS query axiosConfigPublish = setupQrsConnection(this.options, { @@ -1101,7 +1105,7 @@ class QlikSenseApps { // Provided stream name is not a GUID, make sure only one stream exists with this name, then get its GUID const filter = encodeURIComponent(`name eq '${uploadedAppInfo.appPublishToStream}'`); - // Should cerrificates be used for authentication? + // Should certificates be used for authentication? if (this.options.authType === 'cert') { // Build QRS query axiosConfigPublish = setupQrsConnection(this.options, { @@ -1266,7 +1270,7 @@ class QlikSenseApps { const exportToken = uuidv4(); const excludeData = this.options.excludeAppData === 'true' ? 'true' : 'false'; - // Should cerrificates be used for authentication? + // Should certificates be used for authentication? let axiosConfig; if (this.options.authType === 'cert') { // Build QRS query @@ -1379,7 +1383,7 @@ class QlikSenseApps { } else { writer = fs2.createWriteStream(fileName); - // Should cerrificates be used for authentication? + // Should certificates be used for authentication? let axiosConfig; if (this.options.authType === 'cert') { // Build QRS query diff --git a/src/lib/cli/qseow-show-version.js b/src/lib/cli/qseow-show-version.js index 3b6f259..d5a159f 100644 --- a/src/lib/cli/qseow-show-version.js +++ b/src/lib/cli/qseow-show-version.js @@ -1,7 +1,5 @@ import { Option } from 'commander'; -import { catchLog } from '../util/log.js'; - export function setupQseowShowVersionCommand(qseow) { qseow .command('version') @@ -9,7 +7,6 @@ export function setupQseowShowVersionCommand(qseow) { .addOption( new Option('--log-level ', 'log level').choices(['error', 'warn', 'info', 'verbose', 'debug', 'silly']).default('info') ) - // eslint-disable-next-line no-unused-vars .action(async (options) => { logger.verbose(`Version: ${appVersion}`); }); diff --git a/src/lib/cmd/qseow/importapp.js b/src/lib/cmd/qseow/importapp.js index 8d6d416..9ff5830 100644 --- a/src/lib/cmd/qseow/importapp.js +++ b/src/lib/cmd/qseow/importapp.js @@ -1,5 +1,3 @@ -// import { csvParse } from 'csv-parse'; - import xlsx from 'node-xlsx'; import { logger, setLoggingLevel, isPkg, execPath, verifyFileExists, isNumeric } from '../../../globals.js'; @@ -25,6 +23,7 @@ const importAppFromFile = async (options) => { // Get all custom properties const cpExisting = await getCustomPropertiesFromQseow(options); + logger.info(`Successfully retrieved ${cpExisting.length} custom properties from QSEoW`); // Verify file exists const appFileExists = await verifyFileExists(options.fileName); diff --git a/src/lib/cmd/qseow/importtask.js b/src/lib/cmd/qseow/importtask.js index 3f24231..ff047cd 100644 --- a/src/lib/cmd/qseow/importtask.js +++ b/src/lib/cmd/qseow/importtask.js @@ -1,7 +1,6 @@ import xlsx from 'node-xlsx'; import { parse } from 'csv-parse'; import fs from 'node:fs'; -import { finished } from 'node:stream/promises'; import { logger, setLoggingLevel, isPkg, execPath, verifyFileExists, isNumeric } from '../../../globals.js'; import QlikSenseTasks from '../../task/class_alltasks.js'; @@ -22,7 +21,6 @@ const getHeaders = async (options) => { ); // Get the header row - // eslint-disable-next-line no-restricted-syntax for await (const record of parser) { if (record.info.lines === 1) { // Header row @@ -39,7 +37,6 @@ const processCsvFile = async (options) => { const headerRow = []; // Push all column headers to array - // eslint-disable-next-line no-restricted-syntax for (const record of headers[0]) { // Get each column header text headerRow.push(record); @@ -284,7 +281,6 @@ const processCsvFile = async (options) => { }) ); - // eslint-disable-next-line no-restricted-syntax for await (const record of parser) { // ALways add the header line if (record.info.lines === 1) { @@ -319,6 +315,7 @@ const importTaskFromFile = async (options) => { // Get all custom properties const cpExisting = await getCustomPropertiesFromQseow(options); + logger.info(`Successfully retrieved ${cpExisting.length} custom properties from QSEoW`); // Verify task definitions file exists const taskFileExists = await verifyFileExists(options.fileName); @@ -343,7 +340,6 @@ const importTaskFromFile = async (options) => { data: [], }; - // eslint-disable-next-line no-restricted-syntax for (const item of tmpTasksFromFile) { tasksFromFile.data.push(item); } diff --git a/src/lib/cmd/qseow/settaskcp.js b/src/lib/cmd/qseow/settaskcp.js index 0d88e9f..ea3a3fe 100644 --- a/src/lib/cmd/qseow/settaskcp.js +++ b/src/lib/cmd/qseow/settaskcp.js @@ -42,7 +42,6 @@ const updateTask = async (options, customPropertyDef, task) => // Should new values be replacing or appended to existing values? if (options.updateMode === 'append') { - // eslint-disable-next-line no-restricted-syntax for (const newCpValue of options.customPropertyValue) { // Don't append a value if it's already set for the custom property if (!newPayload.task?.customProperties?.find((item) => item.value === newCpValue)) @@ -52,14 +51,13 @@ const updateTask = async (options, customPropertyDef, task) => }); } } else if (options.updateMode === 'replace') { - // First clear the custom property, then add the values provided via --custom-property-value + // First copy all existing CP values that should not be replaced to the new payload const cp = newPayload.task?.customProperties.filter( (existingCustomProperty) => existingCustomProperty.definition.name !== options.customPropertyName ); newPayload.task.customProperties = cp; // Now add the new CP values - // eslint-disable-next-line no-restricted-syntax for (const newCpValue of options.customPropertyValue) { newPayload.task?.customProperties?.push({ definition: { id: customPropertyDef[0].id, name: customPropertyDef[0].name }, @@ -75,12 +73,10 @@ const updateTask = async (options, customPropertyDef, task) => let ok; logger.info(); if (options.updateMode === 'replace') { - // eslint-disable-next-line no-await-in-loop ok = await yesno({ question: ` Replace current values in custom property "${options.customPropertyName}" with new ones? (y/n)`, }); } else if (options.updateMode === 'append') { - // eslint-disable-next-line no-await-in-loop ok = await yesno({ question: ` Append new values to custom property "${options.customPropertyName}"? (y/n)`, }); @@ -92,7 +88,6 @@ const updateTask = async (options, customPropertyDef, task) => logger.debug(`SET RELOAD TASK CP: Update payload for task ${task.id}: ${JSON.stringify(newPayload, null, 2)}`); if (options.dryRun === undefined || options.dryRun === false) { - // eslint-disable-next-line no-await-in-loop updateResult = await updateReloadTask(options, newPayload); } else { logger.info(`DRY RUN: Update of task custom property ${task.customPropertyName} would happen here.`); @@ -101,7 +96,6 @@ const updateTask = async (options, customPropertyDef, task) => logger.info(`Did not update task "${task.name}"`); } } else if (options.dryRun === undefined || options.dryRun === false) { - // eslint-disable-next-line no-await-in-loop updateResult = await updateReloadTask(options, newPayload); } else { logger.info(`DRY RUN: Update of task custom property ${task.customPropertyName} would happen here.`); @@ -123,7 +117,6 @@ const updateTask = async (options, customPropertyDef, task) => // Custom property does NOT already have the custom property set for this task. // Add CP values to task - // eslint-disable-next-line no-restricted-syntax for (const newCpValue of options.customPropertyValue) { newPayload.task?.customProperties?.push({ definition: { id: customPropertyDef[0].id, name: customPropertyDef[0].name }, @@ -133,7 +126,6 @@ const updateTask = async (options, customPropertyDef, task) => // Update task logger.debug(`SET RELOAD TASK CP: Update payload for task ${task.id}: ${JSON.stringify(newPayload, null, 2)}`); - // eslint-disable-next-line no-await-in-loop const updateResult = await updateReloadTask(options, newPayload); if (updateResult) { @@ -177,7 +169,6 @@ const setTaskCustomProperty = async (options) => { } // Ensure that the new CP values are among the CP's choiceValues - // eslint-disable-next-line no-restricted-syntax for (const newCPValue of options.customPropertyValue) { if (!customPropertyDef[0].choiceValues.find((item) => item === newCPValue)) { // An invalud custom property value detected @@ -195,22 +186,15 @@ const setTaskCustomProperty = async (options) => { // Log which tasks will be processed logger.info(`Number of tasks that will be updated: ${taskList.length}`); - // const updateTasks = []; - // eslint-disable-next-line no-restricted-syntax for (const task of taskList) { - // updateTasks.push(updateTask(options, customPropertyDef, task)); - logger.info(``); logger.info(`-----------------------------------------------------------`); logger.info(`Processing task "${task.name}" with ID=${task.id}`); - // eslint-disable-next-line no-await-in-loop const res = await updateTask(options, customPropertyDef, task); logger.debug(`Custom property update result: ${res}`); } - // await Promise.all(updateTasks); - // logger.debug('Update task custom property: All promises resolved'); return true; } } catch (err) { diff --git a/src/lib/task/class_allcompositeevents.js b/src/lib/task/class_allcompositeevents.js index 3bc4a89..7e7e1a1 100644 --- a/src/lib/task/class_allcompositeevents.js +++ b/src/lib/task/class_allcompositeevents.js @@ -1,12 +1,13 @@ import axios from 'axios'; import path from 'node:path'; + import { logger, execPath, verifyFileExists } from '../../globals.js'; import { setupQrsConnection } from '../util/qseow/qrs.js'; import QlikSenseCompositeEvent from './class_compositeevent.js'; import { catchLog } from '../util/log.js'; +import { getCertFilePaths } from '../util/qseow/cert.js'; class QlikSenseCompositeEvents { - // eslint-disable-next-line no-useless-constructor constructor() { // } @@ -16,11 +17,14 @@ class QlikSenseCompositeEvents { this.compositeEventList = []; this.options = options; + // Should certificates be used for authentication? if (this.options.authType === 'cert') { - // Make sure certificates exist - this.fileCert = path.resolve(execPath, options.authCertFile); - this.fileCertKey = path.resolve(execPath, options.authCertKeyFile); - this.fileCertCA = path.resolve(execPath, options.authRootCertFile); + // Get certificate paths + const { fileCert, fileCertKey, fileCertCA } = getCertFilePaths(options); + + this.fileCert = fileCert; + this.fileCertKey = fileCertKey; + this.fileCertCA = fileCertCA; } } catch (err) { catchLog(`GET COMPOSITE EVENT`, err); diff --git a/src/lib/task/class_allschemaevents.js b/src/lib/task/class_allschemaevents.js index 3e2bf94..80007d9 100644 --- a/src/lib/task/class_allschemaevents.js +++ b/src/lib/task/class_allschemaevents.js @@ -1,12 +1,11 @@ import axios from 'axios'; -import path from 'node:path'; -import { logger, execPath } from '../../globals.js'; +import { logger } from '../../globals.js'; import { setupQrsConnection } from '../util/qseow/qrs.js'; import QlikSenseSchemaEvent from './class_schemaevent.js'; import { catchLog } from '../util/log.js'; +import { getCertFilePaths } from '../util/qseow/cert.js'; class QlikSenseSchemaEvents { - // eslint-disable-next-line no-useless-constructor constructor() { // } @@ -17,10 +16,12 @@ class QlikSenseSchemaEvents { this.options = options; if (this.options.authType === 'cert') { - // Make sure certificates exist - this.fileCert = path.resolve(execPath, options.authCertFile); - this.fileCertKey = path.resolve(execPath, options.authCertKeyFile); - this.fileCertCA = path.resolve(execPath, options.authRootCertFile); + // Get certificate paths + const { fileCert, fileCertKey, fileCertCA } = getCertFilePaths(options); + + this.fileCert = fileCert; + this.fileCertKey = fileCertKey; + this.fileCertCA = fileCertCA; } } catch (err) { catchLog(`GET SCHEMA EVENT INIT`, err); @@ -38,7 +39,6 @@ class QlikSenseSchemaEvents { } getSchemaEventsFromFile(schemaEvent) { - // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { logger.debug('GET SCHEMA EVENT: Starting get schema events from QSEoW'); @@ -54,7 +54,6 @@ class QlikSenseSchemaEvents { } getSchemaEventsFromQseow() { - // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { logger.debug('GET SCHEMA EVENT: Starting get schema events from QSEoW'); @@ -75,7 +74,6 @@ class QlikSenseSchemaEvents { logger.verbose(`GET SCHEMA EVENT: Total number of schema events: ${schemaEvents.length}`); this.clear(); - // eslint-disable-next-line no-plusplus for (let i = 0; i < schemaEvents.length; i++) { this.addSchemaEvent(schemaEvents[i]); } diff --git a/src/lib/task/class_alltasks.js b/src/lib/task/class_alltasks.js index 4925337..2dccbde 100644 --- a/src/lib/task/class_alltasks.js +++ b/src/lib/task/class_alltasks.js @@ -1,7 +1,6 @@ import axios from 'axios'; -import path from 'node:path'; import { v4 as uuidv4, validate } from 'uuid'; -import { logger, execPath } from '../../globals.js'; +import { logger } from '../../globals.js'; import { setupQrsConnection } from '../util/qseow/qrs.js'; import { @@ -21,9 +20,9 @@ import { getCustomPropertyIdByName } from '../util/qseow/customproperties.js'; import { getAppById } from '../util/qseow/app.js'; import { taskExistById, getTaskById } from '../util/qseow/task.js'; import { catchLog } from '../util/log.js'; +import { getCertFilePaths } from '../util/qseow/cert.js'; class QlikSenseTasks { - // eslint-disable-next-line no-useless-constructor constructor() { // } @@ -43,10 +42,12 @@ class QlikSenseTasks { this.taskTreeCyclicVisited = new Set(); if (options.authType === 'cert') { - // Make sure certificates exist - this.fileCert = path.resolve(execPath, options.authCertFile); - this.fileCertKey = path.resolve(execPath, options.authCertKeyFile); - this.fileCertCA = path.resolve(execPath, options.authRootCertFile); + // Get certificate paths + const { fileCert, fileCertKey, fileCertCA } = getCertFilePaths(options); + + this.fileCert = fileCert; + this.fileCertKey = fileCertKey; + this.fileCertCA = fileCertCA; } this.qlikSenseSchemaEvents = new QlikSenseSchemaEvents(); @@ -166,7 +167,6 @@ class QlikSenseTasks { process.exit(1); } - // eslint-disable-next-line no-await-in-loop const app = await getAppById(appId, param?.options); if (!app) { @@ -178,7 +178,6 @@ class QlikSenseTasks { } else if (validate(appIdRaw)) { // App ID is a proper UUID. We don't know if the app actually exists though. - // eslint-disable-next-line no-await-in-loop const app = await getAppById(appIdRaw, param?.options); if (!app) { @@ -244,9 +243,7 @@ class QlikSenseTasks { .filter((item) => item.trim().length !== 0) .map((item) => item.trim()); - // eslint-disable-next-line no-restricted-syntax for (const item of tmpTags) { - // eslint-disable-next-line no-await-in-loop const tagId = await getTagIdByName(item, param.tagsExisting); currentTask.tags.push({ id: tagId, @@ -262,7 +259,6 @@ class QlikSenseTasks { .filter((item) => item.trim().length !== 0) .map((cp) => cp.trim()); - // eslint-disable-next-line no-restricted-syntax for (const item of tmpCustomProperties) { const tmpCustomProperty = item .split('=') @@ -271,8 +267,7 @@ class QlikSenseTasks { // Do we have two items in the array? First is the custom property name, second is the value if (tmpCustomProperty?.length === 2) { - // eslint-disable-next-line no-await-in-loop - const customPropertyId = await getCustomPropertyIdByName('ReloadTask', tmpCustomProperty[0], param.cpExisting); + const customPropertyId = getCustomPropertyIdByName('ReloadTask', tmpCustomProperty[0], param.cpExisting); // If previous call returned false, it means the custom property does not exist in Sense // or cannot be used with this task type. In that case, skip it. @@ -387,9 +382,7 @@ class QlikSenseTasks { .filter((item) => item.trim().length !== 0) .map((item) => item.trim()); - // eslint-disable-next-line no-restricted-syntax for (const item of tmpTags) { - // eslint-disable-next-line no-await-in-loop const tagId = await getTagIdByName(item, param.tagsExisting); currentTask.tags.push({ id: tagId, @@ -405,7 +398,6 @@ class QlikSenseTasks { .filter((item) => item.trim().length !== 0) .map((cp) => cp.trim()); - // eslint-disable-next-line no-restricted-syntax for (const item of tmpCustomProperties) { const tmpCustomProperty = item .split('=') @@ -414,8 +406,7 @@ class QlikSenseTasks { // Do we have two items in the array? First is the custom property name, second is the value if (tmpCustomProperty?.length === 2) { - // eslint-disable-next-line no-await-in-loop - const customPropertyId = await getCustomPropertyIdByName('ExternalProgramTask', tmpCustomProperty[0], param.cpExisting); + const customPropertyId = getCustomPropertyIdByName('ExternalProgramTask', tmpCustomProperty[0], param.cpExisting); // If previous call returned false, it means the custom property does not exist in Sense // or cannot be used with this task type. In that case, skip it. @@ -486,7 +477,6 @@ class QlikSenseTasks { ); // Add schema edges and start/trigger nodes - // eslint-disable-next-line no-restricted-syntax for (const schemaEventRow of schemaEventRows) { // Create object using same format that Sense uses for schema events const schemaEvent = { @@ -605,7 +595,6 @@ class QlikSenseTasks { ); // Loop over all composite events, adding them and their event rules - // eslint-disable-next-line no-restricted-syntax for (const compositeEventRow of compositeEventRows) { // Get value in "Event counter" column for this composite event, then get array of all associated event rules const compositeEventCounter = compositeEventRow[param.taskFileColumnHeaders.eventCounter.pos]; @@ -645,7 +634,6 @@ class QlikSenseTasks { } // Add rules - // eslint-disable-next-line no-restricted-syntax for (const rule of compositeEventRules) { // Does the upstream task pointed to by the composite rule exist? // If it *does* exist it means it's a real, existing task in QSEoW that should be used. @@ -654,7 +642,6 @@ class QlikSenseTasks { if (validate(rule[param.taskFileColumnHeaders.ruleTaskId.pos])) { // The rule points to an valid UUID. It should exist, otherwise it's an error - // eslint-disable-next-line no-await-in-loop const taskExists = await taskExistById(rule[param.taskFileColumnHeaders.ruleTaskId.pos], this.options); if (taskExists) { @@ -711,7 +698,6 @@ class QlikSenseTasks { upstreamTaskExistence = 'exists-in-source-file'; } else { - // eslint-disable-next-line no-await-in-loop upstreamTask = await getTaskById(rule[param.taskFileColumnHeaders.ruleTaskId.pos], param?.options); // Save upstream task in shared task list @@ -810,7 +796,6 @@ class QlikSenseTasks { param.nodesWithEvents.add(nodeId); // Add edges from upstream tasks to the new meta node - // eslint-disable-next-line no-restricted-syntax for (const rule of compositeEvent.compositeRules) { this.taskNetwork.edges.push({ from: rule.task.id, @@ -850,7 +835,6 @@ class QlikSenseTasks { // - cpExisting: Array of existing custom properties in QSEoW // - options: Options object passed on the command line async getTaskModelFromFile(tasksFromFile, tagsExisting, cpExisting, options) { - // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { logger.debug('PARSE TASKS FROM FILE: Starting get tasks from data in file'); @@ -947,7 +931,6 @@ class QlikSenseTasks { // Create a fake ID for this task. Used to associate task with schema/composite events const fakeTaskId = `reload-task-${uuidv4()}`; - // eslint-disable-next-line no-await-in-loop const res = await this.parseReloadTask({ taskRows, taskFileColumnHeaders, @@ -963,7 +946,6 @@ class QlikSenseTasks { // NB: A top level node is defined as: // 1. A task whose taskID does not show up in the "to" field of any edge. - // eslint-disable-next-line no-restricted-syntax this.taskNetwork.nodes.push({ id: res.currentTask.id, metaNode: false, @@ -1007,7 +989,6 @@ class QlikSenseTasks { if (this.options.updateMode === 'create') { // Create new task if (this.options.dryRun === false || this.options.dryRun === undefined) { - // eslint-disable-next-line no-await-in-loop const newTaskId = await this.createReloadTaskInQseow(res.currentTask, taskCounter); logger.info( `(${taskCounter}) Created new reload task "${res.currentTask.name}", new task id: ${newTaskId}.` @@ -1024,7 +1005,6 @@ class QlikSenseTasks { res.currentTask.idRef = res.currentTask.id; res.currentTask.id = newTaskId; - // eslint-disable-next-line no-await-in-loop await this.addTask('from_file', res.currentTask, false); } else { logger.info(`(${taskCounter}) DRY RUN: Creating reload task in QSEoW "${res.currentTask.name}"`); @@ -1078,7 +1058,6 @@ class QlikSenseTasks { // Create a fake ID for this task. Used to associate task with schema/composite events const fakeTaskId = `ext-pgm-task-${uuidv4()}`; - // eslint-disable-next-line no-await-in-loop const res = await this.parseExternalProgramTask({ taskRows, taskFileColumnHeaders, @@ -1094,7 +1073,6 @@ class QlikSenseTasks { // NB: A top level node is defined as: // 1. A task whose taskID does not show up in the "to" field of any edge. - // eslint-disable-next-line no-restricted-syntax this.taskNetwork.nodes.push({ id: res.currentTask.id, metaNode: false, @@ -1123,7 +1101,6 @@ class QlikSenseTasks { if (this.options.updateMode === 'create') { // Create new task if (this.options.dryRun === false || this.options.dryRun === undefined) { - // eslint-disable-next-line no-await-in-loop const newTaskId = await this.createExternalProgramTaskInQseow(res.currentTask, taskCounter); logger.info( `(${taskCounter}) Created new external program task "${res.currentTask.name}", new task id: ${newTaskId}.` @@ -1140,7 +1117,6 @@ class QlikSenseTasks { res.currentTask.idRef = res.currentTask.id; res.currentTask.id = newTaskId; - // eslint-disable-next-line no-await-in-loop await this.addTask('from_file', res.currentTask, false); } else { logger.info(`(${taskCounter}) DRY RUN: Creating external program task in QSEoW "${res.currentTask.name}"`); @@ -1211,7 +1187,6 @@ class QlikSenseTasks { taskType = task.taskType; // const { taskType } = this.taskNetwork.nodes.find((node) => node.id === id).completeTaskObject; } else if (b.upstreamTaskExistence === 'exists-in-sense') { - // eslint-disable-next-line no-await-in-loop const task = this.compositeEventUpstreamTask.find((item4) => item4.id === b.task.id); // Ensure we got a task back @@ -1256,10 +1231,8 @@ class QlikSenseTasks { logger.info('-------------------------------------------------------------------'); logger.info('Creating composite events for the just created tasks...'); - // eslint-disable-next-line no-restricted-syntax for (const { compositeEvent } of this.qlikSenseCompositeEvents.compositeEventList) { if (this.options.dryRun === false || this.options.dryRun === undefined) { - // eslint-disable-next-line no-await-in-loop await this.createCompositeEventInQseow(compositeEvent); } else { logger.info(`DRY RUN: Creating composite event "${compositeEvent.name}"`); @@ -1288,7 +1261,6 @@ class QlikSenseTasks { } createCompositeEventInQseow(newCompositeEvent) { - // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { logger.debug('CREATE COMPOSITE EVENT IN QSEOW: Starting'); @@ -1341,7 +1313,6 @@ class QlikSenseTasks { // Function to create new reload task in QSEoW createReloadTaskInQseow(newTask, taskCounter) { - // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { logger.debug(`(${taskCounter}) CREATE RELOAD TASK IN QSEOW: Starting`); @@ -1407,7 +1378,6 @@ class QlikSenseTasks { // - newTask: Object containing task data // - taskCounter: Task counter, unique for each task in the source file createExternalProgramTaskInQseow(newTask, taskCounter) { - // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { logger.debug(`(${taskCounter}) CREATE EXTERNAL PROGRAM TASK IN QSEOW: Starting`); @@ -1466,14 +1436,11 @@ class QlikSenseTasks { } saveTaskModelToQseow() { - // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { try { logger.debug('SAVE TASKS TO QSEOW: Starting save tasks to QSEoW'); - // eslint-disable-next-line no-restricted-syntax for (const task of this.taskList) { - // eslint-disable-next-line no-await-in-loop await new Promise((resolve2, reject2) => { // Build a body for the API call const body = { @@ -1533,7 +1500,6 @@ class QlikSenseTasks { } async getTasksFromQseow() { - // eslint-disable-next-line no-async-promise-executor, no-unused-vars return new Promise(async (resolve, reject) => { // try { logger.debug('GET TASKS FROM QSEOW: Starting get reload tasks from QSEoW'); @@ -1702,7 +1668,6 @@ class QlikSenseTasks { const downstreamTasks = self.taskNetwork.edges.filter((edge) => edge.from === task.id); let kids = []; - // eslint-disable-next-line no-restricted-syntax for (const downstreamTask of downstreamTasks) { logger.debug( `GET TASK SUBTREE: Processing downstream task: ${downstreamTask.to}. Current/source task: ${downstreamTask.from}` @@ -1722,7 +1687,6 @@ class QlikSenseTasks { ]; } else { // Check for cyclic task tree - // eslint-disable-next-line no-lonely-if if (this.isTaskTreeCyclic(tmp)) { if (parentTask) { logger.warn( @@ -1896,7 +1860,6 @@ class QlikSenseTasks { const downstreamTasks = self.taskNetwork.edges.filter((edge) => edge.from === task.id); // console.log('downStreamTasks 1: ' + JSON.stringify(downstreamTasks)); let kids = []; - // eslint-disable-next-line no-restricted-syntax for (const downstreamTask of downstreamTasks) { if (downstreamTask.to !== undefined) { // Get downstream task object @@ -2019,7 +1982,6 @@ class QlikSenseTasks { // Add schema edges and start/trigger nodes logger.verbose('GET TASK MODEL FROM QSEOW: Adding schema edges and start/trigger nodes to internal task model'); - // eslint-disable-next-line no-restricted-syntax for (const schemaEvent of this.qlikSenseSchemaEvents.schemaEventList) { logger.silly(`Schema event contents: ${JSON.stringify(schemaEvent, null, 2)}`); // Schedule is associated with a reload task @@ -2081,7 +2043,6 @@ class QlikSenseTasks { // Add composite events logger.verbose('GET TASK MODEL FROM QSEOW: Adding composite events to internal task model'); - // eslint-disable-next-line no-restricted-syntax for (const compositeEvent of this.qlikSenseCompositeEvents.compositeEventList) { logger.silly(`Composite event contents: ${JSON.stringify(compositeEvent, null, 2)}`); @@ -2178,7 +2139,6 @@ class QlikSenseTasks { nodesWithEvents.add(nodeId); // Add edges from upstream tasks to the new meta node - // eslint-disable-next-line no-restricted-syntax for (const rule of compositeEvent.compositeEvent.compositeRules) { if (validate(rule?.reloadTask?.id)) { // Upstream task is a reload task @@ -2315,7 +2275,6 @@ class QlikSenseTasks { nodesWithEvents.add(nodeId); // Add edges from upstream tasks to the new meta node - // eslint-disable-next-line no-restricted-syntax for (const rule of compositeEvent.compositeEvent.compositeRules) { if (validate(rule?.reloadTask?.id)) { // Upstream task is a reload task @@ -2380,7 +2339,6 @@ class QlikSenseTasks { // NB: A top level node is defined as: // 1. A task whose taskID does not show up in the "to" field of any edge. - // eslint-disable-next-line no-restricted-syntax for (const node of this.taskList) { if (node.completeTaskObject.schemaPath === 'ReloadTask') { this.taskNetwork.nodes.push({ diff --git a/src/lib/task/task_qrs.js b/src/lib/task/task_qrs.js index 07eec88..d8bfe85 100644 --- a/src/lib/task/task_qrs.js +++ b/src/lib/task/task_qrs.js @@ -1,12 +1,11 @@ import axios from 'axios'; -import path from 'node:path'; // const { promises: Fs } = require('fs'); // const yesno = require('yesno'); -import { logger, execPath } from '../../globals.js'; - +import { logger } from '../../globals.js'; import { setupQrsConnection } from '../util/qseow/qrs.js'; -import getCertFilePaths from '../util/cert.js'; +import { getCertFilePaths } from '../util/qseow/cert.js'; + import { catchLog } from '../util/log.js'; // const { QlikSenseTasks } = require('./class_alltasks'); // const { mapEventType, mapIncrementOption, mapDaylightSavingTime, mapRuleState } = require('../util/lookups'); @@ -26,7 +25,7 @@ export const getCustomProperty = async (options) => { try { // Get cert files - const certFilesFullPath = await getCertFilePaths(options); + const certFilesFullPath = getCertFilePaths(options); // Build QRS query string using custom property name const filter = encodeURIComponent(`name eq '${options.customPropertyName}'`); @@ -62,16 +61,11 @@ export const getCustomProperty = async (options) => { return cp; }; +// TODO Should this function support JWT auth too? export const getTasksFromQseow = async (options) => { let taskList; try { - // Get QRS certificates - const fileCert = path.resolve(execPath, options.authCertFile); - const fileCertKey = path.resolve(execPath, options.authCertKeyFile); - const fileCertCA = path.resolve(execPath, options.authRootCertFile); - - // // Build QRS query string using task IDs let filter = ''; if (options.taskId && options?.taskId.length >= 1) { @@ -112,9 +106,6 @@ export const getTasksFromQseow = async (options) => { const axiosConfig = await setupQrsConnection(options, { method: 'get', - fileCert, - fileCertKey, - fileCertCA, path: '/qrs/reloadtask/full', queryParameters: [{ name: 'filter', value: filter }], }); @@ -139,14 +130,9 @@ export const getTasksFromQseow = async (options) => { export const updateReloadTask = async (options, payload) => { try { - // Get cert files - const certFilesFullPath = await getCertFilePaths(options); - + // TODO Should be using PUT instead of POST if updating an existing task? const axiosConfig = await setupQrsConnection(options, { method: 'post', - fileCert: certFilesFullPath.fileCert, - fileCertKey: certFilesFullPath.fileCertKey, - fileCertCA: certFilesFullPath.fileCertCA, path: '/qrs/reloadtask/update', body: payload, }); @@ -154,6 +140,8 @@ export const updateReloadTask = async (options, payload) => { // Update reload task const result = await axios.request(axiosConfig); logger.debug(`UPDATE RELOAD TASK CUSTOM PROPERTY: Result=${result.status}`); + + // TODO Check if task was updated successfully. Log error and return false if not. } catch (err) { catchLog(`UPDATE RELOAD TASK`, err); return false; diff --git a/src/lib/util/qseow/about.js b/src/lib/util/qseow/about.js index 3b4333d..844e1d9 100644 --- a/src/lib/util/qseow/about.js +++ b/src/lib/util/qseow/about.js @@ -7,32 +7,14 @@ import { catchLog } from '../log.js'; async function getAboutFromQseow(options) { logger.verbose(`Getting about info from QSEoW...`); - // Should cerrificates be used for authentication? - let axiosConfig; - - if (options.authType === 'cert') { - // Make sure certificates exist - const fileCert = path.resolve(execPath, options.authCertFile); - const fileCertKey = path.resolve(execPath, options.authCertKeyFile); - const fileCertCA = path.resolve(execPath, options.authRootCertFile); - - axiosConfig = setupQrsConnection(options, { - method: 'get', - fileCert, - fileCertKey, - fileCertCA, - path: '/qrs/about', - }); - } else if (options.authType === 'jwt') { - axiosConfig = setupQrsConnection(options, { + try { + const axiosConfig = setupQrsConnection(options, { method: 'get', path: '/qrs/about', }); - } - logger.debug(`About to get about info from QSEoW`); + logger.debug(`About to get about info from QSEoW`); - try { const result = await axios.request(axiosConfig); if (result.status === 200) { diff --git a/src/lib/util/qseow/app.js b/src/lib/util/qseow/app.js index a42e308..67b5df8 100644 --- a/src/lib/util/qseow/app.js +++ b/src/lib/util/qseow/app.js @@ -57,34 +57,17 @@ export async function getApps(options, idArray, tagArray) { } logger.debug(`GET APPS: QRS query filter (incl ids, tags): ${filter}`); - let axiosConfig; if (filter === '') { // No apps matching the provided app IDs and tags. Error! logger.error('GET APPS: No apps matching the provided app IDs and and tags. Exiting.'); process.exit(1); } - // Should cerrificates be used for authentication? - else if (options.authType === 'cert') { - // Make sure certificates exist - const fileCert = path.resolve(execPath, options.authCertFile); - const fileCertKey = path.resolve(execPath, options.authCertKeyFile); - const fileCertCA = path.resolve(execPath, options.authRootCertFile); - - axiosConfig = setupQrsConnection(options, { - method: 'get', - fileCert, - fileCertKey, - fileCertCA, - path: '/qrs/app/full', - queryParameters: [{ name: 'filter', value: filter }], - }); - } else if (options.authType === 'jwt') { - axiosConfig = setupQrsConnection(options, { - method: 'get', - path: '/qrs/app/full', - queryParameters: [{ name: 'filter', value: filter }], - }); - } + + const axiosConfig = setupQrsConnection(options, { + method: 'get', + path: '/qrs/app/full', + queryParameters: [{ name: 'filter', value: filter }], + }); const result = await axios.request(axiosConfig); logger.debug(`GET APPS BY TAG: Result=result.status`); @@ -119,27 +102,11 @@ export async function getAppById(appId, optionsParam) { return false; } - // Should cerrificates be used for authentication? - let axiosConfig; - if (options.authType === 'cert') { - // Make sure certificates exist - const fileCert = path.resolve(execPath, options.authCertFile); - const fileCertKey = path.resolve(execPath, options.authCertKeyFile); - const fileCertCA = path.resolve(execPath, options.authRootCertFile); - - axiosConfig = setupQrsConnection(options, { - method: 'get', - fileCert, - fileCertKey, - fileCertCA, - path: `/qrs/app/${appId}`, - }); - } else if (options.authType === 'jwt') { - axiosConfig = setupQrsConnection(options, { - method: 'get', - path: `/qrs/app/${appId}`, - }); - } + // Should certificates be used for authentication? + const axiosConfig = setupQrsConnection(options, { + method: 'get', + path: `/qrs/app/${appId}`, + }); const result = await axios.request(axiosConfig); logger.debug(`GET APP BY ID: Result=${result.status}`); @@ -175,31 +142,10 @@ export async function deleteAppById(appId, options) { try { logger.debug(`DELETE APP: Starting delete app from QSEoW for app id ${appId}`); - // Get CLI options - // const cliOptions = getCliOptions(); - - // Should cerrificates be used for authentication? - let axiosConfig; - if (options.authType === 'cert') { - // Make sure certificates exist - const fileCert = path.resolve(execPath, options.authCertFile); - const fileCertKey = path.resolve(execPath, options.authCertKeyFile); - const fileCertCA = path.resolve(execPath, options.authRootCertFile); - - axiosConfig = setupQrsConnection(options, { - method: 'delete', - fileCert, - fileCertKey, - fileCertCA, - path: `/qrs/app/${appId}`, - }); - } else if (options.authType === 'jwt') { - axiosConfig = setupQrsConnection(options, { - method: 'delete', - path: `/qrs/app/${appId}`, - }); - } - + const axiosConfig = setupQrsConnection(options, { + method: 'delete', + path: `/qrs/app/${appId}`, + }); const result = await axios.request(axiosConfig); logger.debug(`DELETE APP: Result=result.status`); @@ -227,29 +173,11 @@ export async function appExistById(appId, options) { return false; } - // Should cerrificates be used for authentication? - let axiosConfig; - if (options.authType === 'cert') { - // Make sure certificates exist - const fileCert = path.resolve(execPath, options.authCertFile); - const fileCertKey = path.resolve(execPath, options.authCertKeyFile); - const fileCertCA = path.resolve(execPath, options.authRootCertFile); - - axiosConfig = setupQrsConnection(options, { - method: 'get', - fileCert, - fileCertKey, - fileCertCA, - path: '/qrs/app', - queryParameters: [{ name: 'filter', value: encodeURI(`id eq ${appId}`) }], - }); - } else if (options.authType === 'jwt') { - axiosConfig = setupQrsConnection(options, { - method: 'get', - path: '/qrs/app', - queryParameters: [{ name: 'filter', value: encodeURI(`id eq ${appId}`) }], - }); - } + const axiosConfig = setupQrsConnection(options, { + method: 'get', + path: '/qrs/app', + queryParameters: [{ name: 'filter', value: encodeURI(`id eq ${appId}`) }], + }); const result = await axios.request(axiosConfig); logger.debug(`APP EXIST BY ID: Result=${result.status}`); diff --git a/src/lib/util/cert.js b/src/lib/util/qseow/cert.js similarity index 60% rename from src/lib/util/cert.js rename to src/lib/util/qseow/cert.js index 9254c68..e025361 100644 --- a/src/lib/util/cert.js +++ b/src/lib/util/qseow/cert.js @@ -1,22 +1,20 @@ import path from 'node:path'; -import { logger, execPath } from '../../globals.js'; -import { catchLog } from './log.js'; +import { logger, execPath, verifyFileExists } from '../../../globals.js'; +import { catchLog } from '../log.js'; -const getCertFilePaths = async (options) => { +export function getCertFilePaths(options) { let fileCert; let fileCertKey; let fileCertCA; try { - // Make sure QRS certificates exist + // Get cert paths from command line options fileCert = path.resolve(execPath, options.authCertFile); fileCertKey = path.resolve(execPath, options.authCertKeyFile); fileCertCA = path.resolve(execPath, options.authRootCertFile); } catch (err) { - catchLog('GET TASK QRS (ID). Exiting. ', err); + catchLog('GET CERT FILE PATHS', err); process.exit(1); } return { fileCert, fileCertKey, fileCertCA }; -}; - -export default getCertFilePaths; +} diff --git a/src/lib/util/qseow/proxy.js b/src/lib/util/qseow/proxy.js index b68face..2eaa563 100644 --- a/src/lib/util/qseow/proxy.js +++ b/src/lib/util/qseow/proxy.js @@ -7,16 +7,9 @@ import { catchLog } from '../log.js'; const getProxiesFromQseow = async (options, _sessionCookie) => { logger.verbose(`Getting all proxies from QSEoW...`); - // Make sure certificates exist - const fileCert = path.resolve(execPath, options.authCertFile); - const fileCertKey = path.resolve(execPath, options.authCertKeyFile); - const fileCertCA = path.resolve(execPath, options.authRootCertFile); - + // TODO Should support JWTs here too? const axiosConfig = setupQrsConnection(options, { method: 'get', - fileCert, - fileCertKey, - fileCertCA, path: '/qrs/proxyservice/full', sessionCookie: null, }); diff --git a/src/lib/util/qseow/qps.js b/src/lib/util/qseow/qps.js index 5e3ffe4..efc7126 100644 --- a/src/lib/util/qseow/qps.js +++ b/src/lib/util/qseow/qps.js @@ -2,7 +2,6 @@ import https from 'node:https'; import { logger, generateXrfKey, readCert } from '../../../globals.js'; const setupQPSConnection = (options, param) => { - // eslint-disable-next-line no-unused-vars // Ensure valid http method if (!param.method || (param.method.toLowerCase() !== 'get' && param.method.toLowerCase() !== 'delete')) { logger.error(`Setting up connection to QPS. Invalid http method '${param.method}'. Exiting.`); @@ -17,7 +16,7 @@ const setupQPSConnection = (options, param) => { let axiosConfig; - // Use cerrificates be used for authentication + // Use certificates be used for authentication if (options.authType === 'cert') { logger.debug(`Using certificates for authentication with QPS`); logger.debug(`QPS host: ${options.hostProxy}`); @@ -68,7 +67,6 @@ const setupQPSConnection = (options, param) => { // Add parameters (if any) if (param.queryParameters?.length > 0) { - // eslint-disable-next-line no-restricted-syntax for (const queryParam of param.queryParameters) { axiosConfig.url += `&${queryParam.name}=${queryParam.value}`; } diff --git a/src/lib/util/qseow/qrs.js b/src/lib/util/qseow/qrs.js index ef77826..7b46606 100644 --- a/src/lib/util/qseow/qrs.js +++ b/src/lib/util/qseow/qrs.js @@ -1,6 +1,7 @@ import https from 'node:https'; import { logger, generateXrfKey, readCert } from '../../../globals.js'; +import { getCertFilePaths } from '../qseow/cert.js'; // Function to sanitize virtual proxy export function sanitizeVirtualProxy(virtualProxy) { @@ -75,17 +76,34 @@ export function setupQrsConnection(options, param) { } let axiosConfig; - // Should cerrificates be used for authentication? + // Should certificates be used for authentication? if (options.authType === 'cert') { logger.debug(`Using certificates for authentication with QRS`); logger.debug(`QRS host: ${options.host}`); logger.debug(`Reject unauthorized certificate: ${options.secure}`); + // Get certificate paths + // If specified in the param object, use those paths + // Otherwise, use the paths from the command line options + let { fileCert, fileCertKey, fileCertCA } = getCertFilePaths(options); + + if (param.fileCert) { + fileCert = param.fileCert; + } + + if (param.fileCertKey) { + fileCertKey = param.fileCertKey; + } + + if (param.fileCertCA) { + fileCertCA = param.fileCertCA; + } + const httpsAgent = new https.Agent({ rejectUnauthorized: options.secure !== 'false', - cert: readCert(param.fileCert), - key: readCert(param.fileCertKey), - ca: readCert(param.fileCertCA), + cert: readCert(fileCert), + key: readCert(fileCertKey), + ca: readCert(fileCertCA), }); axiosConfig = { diff --git a/src/lib/util/qseow/session.js b/src/lib/util/qseow/session.js index dfdb667..5bd5532 100644 --- a/src/lib/util/qseow/session.js +++ b/src/lib/util/qseow/session.js @@ -66,17 +66,12 @@ const consoleProxiesTableConfig = { export const getSessionsFromQseow = async (options, sessionCookie) => { logger.verbose(`Getting sessions from QSEoW...`); - // Only cerrificates allowed for authentication + // Only certificates allowed for authentication if (options.authType !== 'cert') { logger.error(`Only certificates allowed for authentication with Qlik Proxy Service (QPS)`); return false; } - // Make sure certificates exist - const fileCert = path.resolve(execPath, options.authCertFile); - const fileCertKey = path.resolve(execPath, options.authCertKeyFile); - const fileCertCA = path.resolve(execPath, options.authRootCertFile); - let axiosConfig; let virtualProxiesToProcess = []; @@ -91,9 +86,6 @@ export const getSessionsFromQseow = async (options, sessionCookie) => { const vpFilter = options.sessionVirtualProxy.map((vp) => `prefix eq '${vp}'`).join(' or '); axiosConfig = setupQrsConnection(options, { method: 'get', - fileCert, - fileCertKey, - fileCertCA, path: '/qrs/virtualproxyconfig/full', queryParameters: [{ name: 'filter', value: encodeURI(vpFilter) }], }); @@ -101,9 +93,6 @@ export const getSessionsFromQseow = async (options, sessionCookie) => { // No virtual proxies specified, get all of them from QRS axiosConfig = setupQrsConnection(options, { method: 'get', - fileCert, - fileCertKey, - fileCertCA, path: '/qrs/virtualproxyconfig/full', }); } @@ -191,7 +180,6 @@ export const getSessionsFromQseow = async (options, sessionCookie) => { let sessions = []; // Loop over virtual proxies and get sessions for each, but only if the linked proxy is in the list of proxies to process - // eslint-disable-next-line no-restricted-syntax for (const vp of virtualProxiesToProcess) { // Is this virtual proxy linked to at least one proxy? const proxiesVirtualProxy = proxiesAvailable.filter((p) => p.settings.virtualProxies.find((q) => q.id === vp.id)); @@ -209,7 +197,6 @@ export const getSessionsFromQseow = async (options, sessionCookie) => { let sessionPerVirtualProxy = 0; // Loop over all proxies linked to this virtual proxy, get the proxy sessions for each one - // eslint-disable-next-line no-restricted-syntax for (const proxy of proxiesVirtualProxy) { // Is this proxy in list of proxies to process? if (proxiesToProcess.length > 0 && !proxiesToProcess.includes(proxy.serverNodeConfiguration.hostName)) { @@ -231,7 +218,6 @@ export const getSessionsFromQseow = async (options, sessionCookie) => { }); try { - // eslint-disable-next-line no-await-in-loop const result = await axios.request(axiosConfig); if (result.status === 200) { @@ -268,17 +254,12 @@ export const getSessionsFromQseow = async (options, sessionCookie) => { export const deleteSessionsFromQSEoWIds = async (options) => { logger.verbose(`Deleting proxy sessions from QSEoW...`); - // Only cerrificates allowed for authentication + // Only certificates allowed for authentication if (options.authType !== 'cert') { logger.error(`Only certificates allowed for authentication with Qlik Proxy Service (QPS)`); return false; } - // Make sure certificates exist - const fileCert = path.resolve(execPath, options.authCertFile); - const fileCertKey = path.resolve(execPath, options.authCertKeyFile); - const fileCertCA = path.resolve(execPath, options.authRootCertFile); - try { const sessionDelete = []; @@ -320,9 +301,7 @@ export const deleteSessionsFromQSEoWIds = async (options) => { } } else { // Use session IDs specified on command line - // eslint-disable-next-line no-restricted-syntax for (const s of options.sessionId) { - // eslint-disable-next-line no-restricted-syntax for (const vp of vpWithSessions) { if (vp.sessions.find((x) => x.SessionId === s)) { const sessionObject = { @@ -350,7 +329,6 @@ export const deleteSessionsFromQSEoWIds = async (options) => { let deleteCounter = 0; // Loop over all session IDs and delete each one - // eslint-disable-next-line no-restricted-syntax for (const s of sessionDelete) { logger.verbose( `Deleting session ID "${s.sessionId}" on proxy "${options.hostProxy}", virtual proxy "${options.sessionVirtualProxy}"...` @@ -361,14 +339,10 @@ export const deleteSessionsFromQSEoWIds = async (options) => { const axiosConfig = setupQPSConnection(options, { hostProxy: options.hostProxy, method: 'delete', - fileCert, - fileCertKey, - fileCertCA, path: `/qps/${options.sessionVirtualProxy}/session/${s.sessionId}`, sessionCookie: null, }); - // eslint-disable-next-line no-await-in-loop const result = await axios.request(axiosConfig); if (result.status === 200) { diff --git a/src/lib/util/qseow/tag.js b/src/lib/util/qseow/tag.js index 5138bd5..7eeba36 100644 --- a/src/lib/util/qseow/tag.js +++ b/src/lib/util/qseow/tag.js @@ -8,27 +8,10 @@ export function getTagsFromQseow(options) { return new Promise((resolve, _reject) => { logger.verbose(`Getting tags from QSEoW...`); - // Should cerrificates be used for authentication? - let axiosConfig; - if (options.authType === 'cert') { - // Make sure certificates exist - const fileCert = path.resolve(execPath, options.authCertFile); - const fileCertKey = path.resolve(execPath, options.authCertKeyFile); - const fileCertCA = path.resolve(execPath, options.authRootCertFile); - - axiosConfig = setupQrsConnection(options, { - method: 'get', - fileCert, - fileCertKey, - fileCertCA, - path: '/qrs/tag/full', - }); - } else if (options.authType === 'jwt') { - axiosConfig = setupQrsConnection(options, { - method: 'get', - path: '/qrs/tag/full', - }); - } + const axiosConfig = setupQrsConnection(options, { + method: 'get', + path: '/qrs/tag/full', + }); logger.debug(`About to retrieve tags from QRS API.`); @@ -68,32 +51,3 @@ export function getTagIdByName(tagName, tagsExisting) { } }); } - -// function getTagIdByName2(tagName, options, fileCert, fileCertKey) { -// return new Promise((resolve, reject) => { -// logger.debug(`Looking up ID for tag named "${tagName}"`); - -// // const filter = encodeURI(`name eq '👍😎 updateSheetThumbnail'`); -// const axiosConfig = setupQrsConnection(options, { -// method: 'get', -// fileCert, -// fileCertKey, -// path: '/qrs/tag', -// queryParameters: [{ name: 'filter', value: encodeURI(`name eq '${tagName}'`) }], -// }); - -// axios -// .request(axiosConfig) -// .then((result) => { -// if (result.data.length === 1) { -// logger.verbose(`Successfully found ID ${result.data[0].id} for tag named "${tagName}"`); -// // Yes, the tag exists -// resolve(result.data[0].id); -// } -// resolve(false); -// }) -// .catch((err) => { -// logger.error(`TAG ID BY NAME: ${err}`); -// }); -// }); -// } diff --git a/src/lib/util/qseow/task.js b/src/lib/util/qseow/task.js index 577d5ad..30d6484 100644 --- a/src/lib/util/qseow/task.js +++ b/src/lib/util/qseow/task.js @@ -1,8 +1,7 @@ import axios from 'axios'; import fs from 'node:fs'; -import path from 'node:path'; import { validate } from 'uuid'; -import { logger, execPath, getCliOptions } from '../../../globals.js'; +import { logger, getCliOptions } from '../../../globals.js'; import { setupQrsConnection } from './qrs.js'; import { catchLog } from '../log.js'; @@ -30,30 +29,11 @@ export async function taskExistById(taskId, optionsParam) { return false; } - // Should cerrificates be used for authentication? - let axiosConfig; - if (options.authType === 'cert') { - // Make sure certificates exist - const fileCert = path.resolve(execPath, options.authCertFile); - const fileCertKey = path.resolve(execPath, options.authCertKeyFile); - const fileCertCA = path.resolve(execPath, options.authRootCertFile); - - // const filter = encodeURI(`name eq '👍😎 updateSheetThumbnail'`); - axiosConfig = setupQrsConnection(options, { - method: 'get', - fileCert, - fileCertKey, - fileCertCA, - path: '/qrs/task', - queryParameters: [{ name: 'filter', value: encodeURI(`id eq ${taskId}`) }], - }); - } else if (options.authType === 'jwt') { - axiosConfig = setupQrsConnection(options, { - method: 'get', - path: '/qrs/task', - queryParameters: [{ name: 'filter', value: encodeURI(`id eq ${taskId}`) }], - }); - } + const axiosConfig = setupQrsConnection(options, { + method: 'get', + path: '/qrs/task', + queryParameters: [{ name: 'filter', value: encodeURI(`id eq ${taskId}`) }], + }); const result = await axios.request(axiosConfig); logger.debug(`TASK EXIST BY ID: Result=${result.status}`); @@ -101,28 +81,11 @@ export async function getTaskByName(taskName, optionsParam) { options = optionsParam; } - let axiosConfig; - if (options.authType === 'cert') { - // Make sure certificates exist - const fileCert = path.resolve(execPath, options.authCertFile); - const fileCertKey = path.resolve(execPath, options.authCertKeyFile); - const fileCertCA = path.resolve(execPath, options.authRootCertFile); - - axiosConfig = setupQrsConnection(options, { - method: 'get', - fileCert, - fileCertKey, - fileCertCA, - path: '/qrs/task/full', - queryParameters: [{ name: 'filter', value: encodeURI(`name eq '${taskName}'`) }], - }); - } else if (options.authType === 'jwt') { - axiosConfig = setupQrsConnection(options, { - method: 'get', - path: '/qrs/task/full', - queryParameters: [{ name: 'filter', value: encodeURI(`name eq '${taskName}'`) }], - }); - } + const axiosConfig = setupQrsConnection(options, { + method: 'get', + path: '/qrs/task/full', + queryParameters: [{ name: 'filter', value: encodeURI(`name eq '${taskName}'`) }], + }); const result = await axios.request(axiosConfig); logger.debug(`GET TASK BY NAME: Result=${result.status}`); @@ -173,28 +136,11 @@ export async function getTaskById(taskId, optionsParam) { logger.verbose(`GET TASK BY ID: Task ID ${taskId} is a valid GUID. Get associated task from QSEoW.`); - let axiosConfig; - if (options.authType === 'cert') { - // Make sure certificates exist - const fileCert = path.resolve(execPath, options.authCertFile); - const fileCertKey = path.resolve(execPath, options.authCertKeyFile); - const fileCertCA = path.resolve(execPath, options.authRootCertFile); - - axiosConfig = setupQrsConnection(options, { - method: 'get', - fileCert, - fileCertKey, - fileCertCA, - path: `/qrs/task/full`, - queryParameters: [{ name: 'filter', value: encodeURI(`id eq ${taskId}`) }], - }); - } else if (options.authType === 'jwt') { - axiosConfig = setupQrsConnection(options, { - method: 'get', - path: `/qrs/task/full`, - queryParameters: [{ name: 'filter', value: encodeURI(`id eq ${taskId}`) }], - }); - } + const axiosConfig = setupQrsConnection(options, { + method: 'get', + path: `/qrs/task/full`, + queryParameters: [{ name: 'filter', value: encodeURI(`id eq ${taskId}`) }], + }); const result = await axios.request(axiosConfig); logger.debug(`GET TASK BY ID: Result=${result.status}`); @@ -247,38 +193,10 @@ export async function deleteReloadTaskById(taskId, optionsParam) { logger.verbose(`DELETE RELOAD TASK BY ID: Task ID ${taskId} is a valid GUID. Delete associated task from QSEoW.`); - let axiosConfig; - - if (optionsParam.authType === 'cert') { - // Expand cert file paths - const fileCert = path.resolve(execPath, options.authCertFile); - const fileCertKey = path.resolve(execPath, options.authCertKeyFile); - const fileCertCA = path.resolve(execPath, options.authRootCertFile); - - // Make sure certificate files exist on disk - if (!fs.existsSync(fileCert)) { - logger.error(`DELETE RELOAD TASK BY ID: Certificate file ${fileCert} does not exist.`); - return false; - } - - if (!fs.existsSync(fileCertKey)) { - logger.error(`DELETE RELOAD TASK BY ID: Certificate key file ${fileCertKey} does not exist.`); - return false; - } - - axiosConfig = setupQrsConnection(options, { - method: 'delete', - fileCert, - fileCertKey, - fileCertCA, - path: `/qrs/reloadtask/${taskId}`, - }); - } else if (optionsParam.authType === 'jwt') { - axiosConfig = setupQrsConnection(options, { - method: 'delete', - path: `/qrs/reloadtask/${taskId}`, - }); - } + const axiosConfig = setupQrsConnection(options, { + method: 'delete', + path: `/qrs/reloadtask/${taskId}`, + }); const result = await axios.request(axiosConfig); logger.debug(`DELETE RELOAD TASK BY ID: Result=${result.status}`); @@ -319,38 +237,10 @@ export async function deleteExternalProgramTaskById(taskId, optionsParam) { logger.verbose(`DELETE EXT PGM TASK BY ID: Task ID ${taskId} is a valid GUID. Delete associated task from QSEoW.`); - let axiosConfig; - - if (optionsParam.authType === 'cert') { - // Expand cert file paths - const fileCert = path.resolve(execPath, options.authCertFile); - const fileCertKey = path.resolve(execPath, options.authCertKeyFile); - const fileCertCA = path.resolve(execPath, options.authRootCertFile); - - // Make sure certificate files exist on disk - if (!fs.existsSync(fileCert)) { - logger.error(`DELETE EXT PGM TASK BY ID: Certificate file ${fileCert} does not exist.`); - return false; - } - - if (!fs.existsSync(fileCertKey)) { - logger.error(`DELETE EXT PGM TASK BY ID: Certificate key file ${fileCertKey} does not exist.`); - return false; - } - - axiosConfig = setupQrsConnection(options, { - method: 'delete', - fileCert, - fileCertKey, - fileCertCA, - path: `/qrs/externalprogramtask/${taskId}`, - }); - } else if (optionsParam.authType === 'jwt') { - axiosConfig = setupQrsConnection(options, { - method: 'delete', - path: `/qrs/externalprogramtask/${taskId}`, - }); - } + const axiosConfig = setupQrsConnection(options, { + method: 'delete', + path: `/qrs/externalprogramtask/${taskId}`, + }); const result = await axios.request(axiosConfig); logger.debug(`DELETE TASK BY ID: Result=${result.status}`);