@contentstack/cli-utilities
Version:
Utilities for contentstack projects
188 lines (187 loc) • 8.42 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.redactObject = exports.formatError = exports.validateRegex = exports.validateFileName = exports.validateUids = exports.sanitizePath = exports.escapeRegExp = exports.validatePath = exports.createDeveloperHubUrl = exports.isManagementTokenValid = exports.doesBranchExist = exports.isAuthenticated = void 0;
const tslib_1 = require("tslib");
const recheck_1 = require("recheck");
const traverse_1 = tslib_1.__importDefault(require("traverse"));
const auth_handler_1 = tslib_1.__importDefault(require("./auth-handler"));
const _1 = require(".");
const isAuthenticated = () => auth_handler_1.default.isAuthenticated();
exports.isAuthenticated = isAuthenticated;
const doesBranchExist = async (stack, branchName) => {
return stack
.branch(branchName)
.fetch()
.catch((error) => {
return error;
});
};
exports.doesBranchExist = doesBranchExist;
const isManagementTokenValid = async (stackAPIKey, managementToken) => {
var _a;
const httpClient = new _1.HttpClient({ headers: { api_key: stackAPIKey, authorization: managementToken } });
try {
const response = (_a = (await httpClient.get(`${_1.configHandler.get('region').cma}/v3/environments?limit=1`))) === null || _a === void 0 ? void 0 : _a.data;
if (response === null || response === void 0 ? void 0 : response.environments) {
return { valid: true };
}
else if (response === null || response === void 0 ? void 0 : response.error_code) {
return { valid: false, message: response.error_message };
}
else {
throw typeof response === 'string' ? response : '';
}
}
catch (error) {
return { valid: 'failedToCheck', message: `Failed to check the validity of the Management token. ${error}` };
}
};
exports.isManagementTokenValid = isManagementTokenValid;
const createDeveloperHubUrl = (developerHubBaseUrl) => {
developerHubBaseUrl = developerHubBaseUrl === null || developerHubBaseUrl === void 0 ? void 0 : developerHubBaseUrl.replace('api', 'developerhub-api');
developerHubBaseUrl = developerHubBaseUrl.startsWith('dev11')
? developerHubBaseUrl.replace('dev11', 'dev')
: developerHubBaseUrl;
developerHubBaseUrl = developerHubBaseUrl.endsWith('io')
? developerHubBaseUrl.replace('io', 'com')
: developerHubBaseUrl;
return developerHubBaseUrl.startsWith('http') ? developerHubBaseUrl : `https://${developerHubBaseUrl}`;
};
exports.createDeveloperHubUrl = createDeveloperHubUrl;
const validatePath = (input) => {
const pattern = /[*$%#<>{}!&?]/g;
if (pattern.test(input)) {
_1.cliux.print(`\nPlease add a directory path without any of the special characters: (*,&,{,},[,],$,%,<,>,?,!)`, {
color: 'yellow',
});
return false;
}
return true;
};
exports.validatePath = validatePath;
// To escape special characters in a string
const escapeRegExp = (str) => str === null || str === void 0 ? void 0 : str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
exports.escapeRegExp = escapeRegExp;
// To remove the relative path
const sanitizePath = (str) => {
if (typeof str !== 'string')
return;
const decodedStr = decodeURIComponent(str);
return decodedStr === null || decodedStr === void 0 ? void 0 : decodedStr.replace(/^([\/\\]){2,}/, "./").replace(/[\/\\]+/g, "/").replace(/(\.\.(\/|\\|$))+/g, ""); // Remove directory traversal (../ or ..\)
};
exports.sanitizePath = sanitizePath;
// To validate the UIDs of assets
const validateUids = (uid) => /^[a-zA-Z0-9]+$/.test(uid);
exports.validateUids = validateUids;
// Validate File name
const validateFileName = (fileName) => /^[a-zA-Z0-9-_\.]+$/.test(fileName);
exports.validateFileName = validateFileName;
// Validate Regex for ReDDos
const validateRegex = (str) => {
const stringValue = typeof str === 'string' ? str : str.toString();
return (0, recheck_1.checkSync)(stringValue, '');
};
exports.validateRegex = validateRegex;
const formatError = function (error) {
let parsedError;
// Parse the error
try {
if (typeof error === 'string') {
parsedError = JSON.parse(error);
}
else if (typeof (error === null || error === void 0 ? void 0 : error.message) === 'string') {
parsedError = JSON.parse(error.message);
}
else {
parsedError = error;
}
}
catch (e) {
parsedError = error;
}
// Check if parsedError is an empty object
if (parsedError && typeof parsedError === 'object' && Object.keys(parsedError).length === 0) {
return `An unknown error occurred. ${error}`;
}
// Check for specific SSL error
if ((parsedError === null || parsedError === void 0 ? void 0 : parsedError.code) === 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY') {
return 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY occurred during SSL certificate verification! Please check your certificate configuration.';
}
// Handle self signed certificate error
if ((parsedError === null || parsedError === void 0 ? void 0 : parsedError.code) === 'SELF_SIGNED_CERT_IN_CHAIN') {
return 'Self-signed certificate in the certificate chain! Please ensure your certificate configuration is correct and the necessary CA certificates are trusted.';
}
// Determine the error message
let message = parsedError.errorMessage || parsedError.error_message || (parsedError === null || parsedError === void 0 ? void 0 : parsedError.code) || parsedError.message || parsedError;
if (typeof message === 'object') {
message = JSON.stringify(message);
}
// If message is in JSON format, parse it to extract the actual message string
try {
const parsedMessage = JSON.parse(message);
if (typeof parsedMessage === 'object') {
message = (parsedMessage === null || parsedMessage === void 0 ? void 0 : parsedMessage.message) || message;
}
}
catch (e) {
// message is not in JSON format, no need to parse
}
// Append detailed error information if available
if (parsedError.errors && Object.keys(parsedError.errors).length > 0) {
const entityNames = {
authorization: 'Authentication',
api_key: 'Stack API key',
uid: 'Content Type',
access_token: 'Delivery Token',
};
message +=
' ' +
Object.entries(parsedError.errors)
.map(([key, value]) => `${entityNames[key] || key} ${value}`)
.join(' ');
}
return message;
};
exports.formatError = formatError;
/**
* The function checks if a given key string matches any of the sensitive keys defined in an array.
* @param {string} keyStr - The parameter `keyStr` is a string that represents a key.
* @returns a boolean value. It returns true if the keyStr matches any of the regular expressions in
* the sensitiveKeys array, and false otherwise.
*/
const isSensitiveKey = function (keyStr) {
if (keyStr && typeof keyStr === 'string') {
return sensitiveKeys.some((regex) => regex.test(keyStr));
}
};
/**
* The function redactObject takes an object as input and replaces any sensitive keys with the string
* '[REDACTED]'.
* @param {any} obj - The `obj` parameter is an object that you want to redact sensitive information
* from.
*/
const redactObject = function (obj) {
(0, traverse_1.default)(obj).forEach(function redactor() {
// Check if the current key is sensitive
if (isSensitiveKey(this.key)) {
// Update the current value with '[REDACTED]'
this.update('[REDACTED]');
}
});
return obj;
};
exports.redactObject = redactObject;
/* The `sensitiveKeys` array is used to store regular expressions that match sensitive keys. These
keys are used to redact sensitive information from log messages. When logging an object, any keys
that match the regular expressions in the `sensitiveKeys` array will be replaced with the string
'[REDACTED]'. This helps to prevent sensitive information from being logged or displayed. */
const sensitiveKeys = [
/authtoken/i,
/^email$/,
/^password$/i,
/secret/i,
/token/i,
/api[-._]?key/i,
/management[-._]?token/i,
/delivery[-._]?token/i,
];