hay-caf
Version:
Haystacks Cloud Automation Framework: A demonstration testing automation framework application for the purposes of demonstrating the usage and integration of D-CAF, Hest, Hexiom, HayRunner, HayMonkey, and HayD-CAG in a single testing automation framework
362 lines (353 loc) • 20.1 kB
JavaScript
/**
* @file applicationSystem.js
* @module applicationSystem
* @description Contains all client application system commands for execution of the client application with basic system operations.
* @requires module:application.constants
* @requires {@link https://www.npmjs.com/package/@haystacks/async|@haystacks/async}
* @requires {@link https://www.npmjs.com/package/@haystacks/constants|@haystacks/constants}
* @requires {@link https://www.npmjs.com/package/path|path}
* @author Seth Hollingsead
* @date 2023/03/30
* @copyright Copyright © 2023-… by Seth Hollingsead. All rights reserved
*/
// Internal imports
import * as apc from '../../constants/application.constants.js';
import * as app_msg from '../../constants/application.message.constants.js';
// External imports
import haystacks from '@haystacks/async';
import hayConst from '@haystacks/constants';
import path from 'path';
const {bas, biz, cmd, msg, wrd} = hayConst;
const baseFileName = path.basename(import.meta.url, path.extname(import.meta.url));
// application.hay-CAF.commands.clientCommands.applicationSystem.
const namespacePrefix = wrd.capplication + bas.cDot + apc.cApplicationName + bas.cDot + wrd.ccommands + bas.cDot + wrd.cclient + wrd.cCommands + bas.cDot + baseFileName + bas.cDot;
/**
* @function instructions
* @description Provides instructions to the end user on what steps they need to perform to get up and running and interface with the system.
* @param {string} inputData Not used for this command.
* @param {string} inputMetaData Not used or this command.
* @return {array<boolean,string>} An array with a boolean True or False value to indicate if the application should exit or not exit, followed by an empty string.
* @author Seth Hollingsead
* @date 2023/03/30
*/
async function instructions(inputData, inputMetaData) {
let functionName = instructions.name;
await haystacks.consoleLog(namespacePrefix, functionName, msg.cBEGIN_Function);
await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputDataIs + inputData);
await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputMetaDataIs + inputMetaData);
let returnData = [true, ''];
// Instructions to end user:
console.log(app_msg.cinstructionsMessage00)
// ....More instructions ADD HERE!
await haystacks.consoleLog(namespacePrefix, functionName, msg.creturnDataIs + JSON.stringify(returnData));
await haystacks.consoleLog(namespacePrefix, functionName, msg.cEND_Function);
return returnData;
}
/**
* @function applicationHelp
* @description A command to list the application commands. (There are no plugins for this application.)
* See the Haystacks testHarness code for how to do this with plugins.
* @param {string} inputData Not used for this command.
* @param {string} inputMetaData Not used for this command.
* @return {array<boolean,string>} An array with a boolean True or False value to indicate if the application should exit or not exit, followed by an empty string.
* @author Seth Hollingsead
* @date 2023/03/30
*/
async function applicationHelp(inputData, inputMetaData) {
let functionName = applicationHelp.name;
await haystacks.consoleLog(namespacePrefix, functionName, msg.cBEGIN_Function);
await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputDataIs + inputData);
await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputMetaDataIs + inputMetaData);
let returnData = [true, ''];
await haystacks.enqueueCommand(wrd.chelp + bas.cSpace + wrd.cApplication);
await haystacks.consoleLog(namespacePrefix, functionName, msg.creturnDataIs + JSON.stringify(returnData));
await haystacks.consoleLog(namespacePrefix, functionName, msg.cEND_Function);
return returnData;
}
/**
* @function applicationWorkflowHelp
* @description A command to list the application workflows. (There are no plugins for this application.)
* See the Haystacks testHarness code for how to do this with plugins.
* @param {string} inputData Not used for this command.
* @param {string} inputMetaData Not used for this command.
* @return {array<boolean,string>} An array ith a boolean True or False value to indicate if the application should exit or not exit, followed by an empty string.
* @author Seth Hollingsead
* @date 2023/03/30
*/
async function applicationWorkflowHelp(inputData, inputMetaData) {
let functionName = applicationWorkflowHelp.name;
await haystacks.consoleLog(namespacePrefix, functionName, msg.cBEGIN_Function);
await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputDataIs + inputData);
await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputMetaDataIs + inputMetaData);
let returnData = [true, ''];
await haystacks.enqueueCommand(cmd.cworkflowHelp + bas.cSpace + wrd.cApplication);
await haystacks.consoleLog(namespacePrefix, functionName, msg.creturnDataIs + JSON.stringify(returnData));
await haystacks.consoleLog(namespacePrefix, functionName, msg.cEND_Function);
return returnData;
}
/**
* @function encryptString
* @description A command to encrypt a string. This is a wrapper for calling the Haystacks-async business rule to encrypt a string.
* The intended use is for a system administrator to encrypt test account credentials so that the username and password can be stored
* securely in the page data CSV files, and also when the data is used to perform the login action, and those actions are performed
* on the browser, when those actions get logged the user account credentials will also get obfuscated for the console log and log files.
* @param {array<string>} inputData An array that could actually contain anything,
* depending on what the user entered. But the function filters all of that internally and
* extracts the case the user has entered a string to be encrypted first,
* followed by a private_public key to be used as a seed to encrypt the string.
* inputData[0] === 'encryptString'
* inputData[1] === The string to be encrypted.
* inputData[2] === 'privateKey_publicKey'
* @param {string} inputMetaData Not used for this command.
* @return {string} The encrypted string.
* @author Seth Hollingsead
* @date 2024/09/24
*/
async function encryptString(inputData, inputMetaData) {
let functionName = encryptString.name;
await haystacks.consoleLog(namespacePrefix, functionName, msg.cBEGIN_Function);
await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputDataIs + JSON.stringify(inputData));
await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputMetaDataIs + inputMetaData);
let returnData = [true, ''];
let validInputData = false;
let validEncryptString = false;
let validPublicPrivateKey = false;
let stringToEncrypt = '';
let encryptionKey = '';
let encryptionKeyArray = [];
let publicKey = '';
let encryptedString = '';
let encryptionSuccessful = false;
if (inputData && Array.isArray(inputData) && inputData.length === 3 &&
typeof inputData[1] === wrd.cstring && inputData[1] !== '' &&
typeof inputData[2] === wrd.cstring && inputData[2] !== '' && inputData[2].includes(bas.cUnderscore)) {
validInputData = true;
validEncryptString = true;
validPublicPrivateKey = true;
stringToEncrypt = inputData[1];
encryptionKey = inputData[2];
encryptionKeyArray = inputData[2].split(bas.cUnderscore);
publicKey = encryptionKeyArray[1];
} else {
// Pop some instructions to the user,
// and we will collect data until we have a valid set of inputs such that we can proceed with the encryption process.
while (validInputData === false) {
// WARNING: No valid inputs where provided to the command.
console.log(app_msg.cencryptStringMessage01);
// This command is intended to be used by the system administrator.
console.log(app_msg.cencryptStringMessage02);
// The system administrator will have a private key used by the testing framework, to be combined with the public key.
console.log(app_msg.cencryptStringMessage03);
// This privateKey should be combined with a publicKey uniquely generated for this specific string encryption.
console.log(app_msg.cencryptStringMessage04);
// The publicKey should be stored in the testing framework page data according to the instructions in the framework documentation,
console.log(app_msg.cencryptStringMessage05);
// along side the encrypted string. The testing framework will take these two pieces of data and combine it with the
console.log(app_msg.cencryptStringMessage06);
// privateKey stored in the testing framework to decrypt the data at the point of use.
console.log(app_msg.cencryptStringMessage07);
// This will allow your testing account credentials to remain secure across the entire testing framework.
console.log(app_msg.cencryptStringMessage08);
// Testing account credentials at rest (test page data) as well as in use (execution/debug logs) will remain confidential
console.log(app_msg.cencryptStringMessage09);
// under all circumstances and usage.
console.log(app_msg.cencryptStringMessage10);
// Make certain that the privateKey you use is the same privateKey used in the testing framework.
console.log(app_msg.cencryptStringMessage11);
// ************
console.log(bas.cStar.repeat(12));
while (validEncryptString === false) {
// Please enter the string to be encrypted.
console.log(app_msg.cencryptStringMessage12);
stringToEncrypt = await haystacks.executeBusinessRules([bas.cGreaterThan, ''], [biz.cprompt]);
// stringToEncrypt is:
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cstringToEncryptIs + stringToEncrypt);
if (stringToEncrypt !== '') {
validEncryptString = true;
// valid encrypt string
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cvalidEncryptString);
}
}
while (validPublicPrivateKey === false) {
// Please enter a privateKey_publicKey to be used as a seed for the encryption process.
console.log(app_msg.cencryptStringMessage13);
encryptionKey = await haystacks.executeBusinessRules([bas.cGreaterThan, ''], [biz.cprompt]);
// encryptionKey is:
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cencryptionKeyIs + encryptionKey);
if (encryptionKey !== '' && encryptionKey.includes(bas.cUnderscore)) {
validPublicPrivateKey = true;
// valid public-private key
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cvalidPublicPrivateKey);
encryptionKeyArray = encryptionKey.split(bas.cUnderscore);
// encryptionKeyArray is:
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cencryptionKeyArrayIs + JSON.stringify(encryptionKeyArray));
publicKey = encryptionKeyArray[1];
// publicKey is:
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cpublicKeyIs + publicKey);
}
}
if (validEncryptString === true && validPublicPrivateKey === true) {
validInputData = true;
// valid input data
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cvalidInputData);
}
}
}
// At this point the user has entered valid data, now we can proceed with the encryption process.
if (validInputData === true && validEncryptString === true && validPublicPrivateKey === true) {
encryptedString = await haystacks.executeBusinessRules([stringToEncrypt, encryptionKey], [biz.cencryptStringAes256]);
// encryptedString is:
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cencryptedStringIs + encryptedString);
if (encryptedString && typeof encryptedString === wrd.cstring && encryptedString !== '') {
encryptionSuccessful = true;
// encryption successful
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cencryptionSuccessful);
}
}
if (encryptionSuccessful === true) {
// encrypted string is:
console.log(app_msg.cencryptedStringIs + encryptedString);
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cencryptedStringIs + encryptedString);
// publicKey is:
console.log(app_msg.cpublicKeyIs + publicKey);
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cpublicKeyIs + publicKey);
// Make certain you store the encrypted string and the public key in the testing framework page data,
console.log(app_msg.cencryptStringMessage14);
// according to the instructions in the framework documentation.
console.log(app_msg.cencryptStringMessage15);
} else {
// ERROR: Failure to encrypt string. Please file a support ticket with the Hay-CAF repo,
console.log(app_msg.cencryptStringMessage16);
// or contact Haystacks Tech support team, repo link and contact details are provided in the Hay-CAF product documentation.
console.log(app_msg.cencryptStringMessage17);
}
await haystacks.consoleLog(namespacePrefix, functionName, msg.creturnDataIs + returnData);
await haystacks.consoleLog(namespacePrefix, functionName, msg.cEND_Function);
return returnData;
}
/**
* @function decryptString
* @description A command to decrypt a string. This is a wrapper for calling the Haystacks-async business rule to decrypt a string.
* The intended use is for a system administrator to test decryption of test account credentials so that successful extraction of
* username and password can be independently validated.
* @param {array<string>} inputData An array that could actually contain anything,
* depending on what the user entered. But the function filters all of that internally and
* extracts the case the user has entered a string to be decrypted first,
* followed by a private_public key to be used as a seed to decrypt the string.
* inputData[0] === 'decryptString'
* inputData[1] === The string to be decrypted.
* inputData[2] === 'privateKey_publicKey'
* @param {string} inputMetaData Not used for this command.
* @return {string} The decrypted string.
* @author Seth Hollingsead
* @date 2024/09/24
*/
async function decryptString(inputData, inputMetaData) {
let functionName = decryptString.name;
await haystacks.consoleLog(namespacePrefix, functionName, msg.cBEGIN_Function);
await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputDataIs + JSON.stringify(inputData));
await haystacks.consoleLog(namespacePrefix, functionName, msg.cinputMetaDataIs + inputMetaData);
let returnData = [true, ''];
let validInputData = false;
let validDecryptString = false;
let validPublicPrivateKey = false;
let stringToDecrypt = '';
let decryptionKey = '';
let decryptionKeyArray = [];
let publicKey = '';
let decryptedString = '';
let decryptionSuccessful = false;
if (inputData && Array.isArray(inputData) && inputData.length === 3 &&
typeof inputData[1] === wrd.cstring && inputData[1] !== '' &&
typeof inputData[2] === wrd.cstring && inputData[2] !== '' && inputData[2].includes(bas.cUnderscore)) {
validInputData = true;
validDecryptString = true;
validPublicPrivateKey = true;
stringToDecrypt = inputData[1];
decryptionKey = inputData[2];
decryptionKeyArray = inputData[2].split(bas.cUnderscore);
publicKey = decryptionKeyArray[1];
} else {
// Pop some instructions to the user,
// and we will collect data until we have a valid set of inputs such that we can proceed with the encryption process.
while (validInputData === false) {
// WARNING: No valid inputs where provided to the command.
console.log(app_msg.cencryptStringMessage01);
// This command is intended to be used by the system administrator.
console.log(app_msg.cencryptStringMessage02);
// The system administrator will have a private key used by the testing framework, to be combined with the public key.
console.log(app_msg.cencryptStringMessage03);
// This privateKey should be combined with a publicKey that was previously uniquely generated and used for the encryption process.
console.log(app_msg.cdecryptStringMessage01);
// The publicKey should be stored in the testing framework page data according to the instructions in the framework documentation,
console.log(app_msg.cencryptStringMessage05);
// along side the encrypted string. The testing framework will take these two pieces of data and combine it with the
console.log(app_msg.cencryptStringMessage06);
// privateKey stored in the testing framework to decrypt the data at the point of use.
console.log(app_msg.cencryptStringMessage07);
// If you have the privateKey and the publicKey as well as the encrypted string,
console.log(app_msg.cdecryptStringMessage02);
// you can use this function to manually test the decryption process.
console.log(app_msg.cdecryptStringMessage03);
// Make certain that the privateKey you use is the same privateKey used in the testing framework.
console.log(app_msg.cencryptStringMessage11);
// ***********
console.log(bas.cStar.repeat(12));
while (validDecryptString === false) {
// Please enter the string to be decrypted.
console.log(app_msg.cdecryptStringMessage04);
stringToDecrypt = await haystacks.executeBusinessRules([bas.cGreaterThan, ''], [biz.cprompt]);
if (stringToDecrypt !== '') {
validDecryptString = true;
}
}
while (validPublicPrivateKey === false) {
// Please enter the same privateKey_publicKey that was used as a seed for the encryption process.
console.log(app_msg.cdecryptStringMessage05);
decryptionKey = await haystacks.executeBusinessRules([bas.cGreaterThan, ''], [biz.cprompt]);
if (decryptionKey !== '' && decryptionKey.includes(bas.cUnderscore)) {
validPublicPrivateKey = true;
decryptionKeyArray = inputData[2].split(bas.cUnderscore);
publicKey = decryptionKeyArray[1];
}
}
if (validDecryptString === true && validPublicPrivateKey === true) {
validInputData = true;
}
}
}
// At this point the user has entered valid data, now we can proceed with the decryption process.
if (validInputData === true && validDecryptString === true && validPublicPrivateKey === true) {
decryptedString = await haystacks.executeBusinessRules([stringToDecrypt, decryptionKey], [biz.cdecryptStringAes256]);
if (decryptedString && typeof decryptedString === wrd.cstring && decryptedString !== '') {
decryptionSuccessful = true;
}
}
if (decryptionSuccessful === true) {
// decrypted string is:
console.log(app_msg.cdecryptedStringIs + decryptedString);
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cdecryptedStringIs + decryptedString);
// publicKey is:
console.log(app_msg.cpublicKeyIs + publicKey);
await haystacks.consoleLog(namespacePrefix, functionName, app_msg.cpublicKeyIs + publicKey);
// Make certain the decrypted string matches with the original string that you encrypted.
console.log(app_msg.cdecryptStringMessage06);
// You are responsible to verify and confirm that the encryption and decryption is working successfully with the correct data.
console.log(app_msg.cdecryptStringMessage07);
} else {
// ERROR: Failure to decrypt the string. Please file a support ticket with the Hay-CAF repo,
console.log(app_msg.cdecryptStringMessage08);
// or contact Haystacks Tech support team, repo link and contact details are provided in the Hay-CAF product documentation.
console.log(app_msg.cencryptStringMessage17);
}
await haystacks.consoleLog(namespacePrefix, functionName, msg.creturnDataIs + returnData);
await haystacks.consoleLog(namespacePrefix, functionName, msg.cEND_Function);
return returnData;
}
export default {
instructions,
applicationHelp,
applicationWorkflowHelp,
encryptString,
decryptString
};