From ddf8c2f04294fcb94a7b37beaee5eff2a396459d Mon Sep 17 00:00:00 2001 From: Raghu A <125877471+raga-adbe-gh@users.noreply.github.com> Date: Thu, 7 Sep 2023 21:49:10 +0530 Subject: [PATCH] MWPW-134761 Authenticated Preview/Publish API calls for restricted sites (#54) Moved the helix admin function out of utils to helixUtils. Updated preview/publish to pass the Authorization code, if the key is defined in config. Below config to be added to .env HELIX_ADMIN_API_KEYS={"cc": "", "cc-pink": ""} Checked for below, With Preview Enabled (on CC / CC-Pink) Non Protected Site (CC-Pink - No Key) - Preview passed Protected Site (CC) with valid Key - Preview passed Protected Site (CC) with Invalid/Missing Key - Preview failed and logged in xlsx Preview/Publish is disabled back till the bulk API is fixed. Co-authored-by: Raghu A --- actions/appConfig.js | 1 + actions/copy/worker.js | 5 ++-- actions/helixUtils.js | 51 +++++++++++++++++++++++++++++++++++++++ actions/promote/worker.js | 5 ++-- actions/utils.js | 24 ------------------ app.config.yaml | 1 + 6 files changed, 59 insertions(+), 28 deletions(-) create mode 100644 actions/helixUtils.js diff --git a/actions/appConfig.js b/actions/appConfig.js index 140029f..189c60f 100644 --- a/actions/appConfig.js +++ b/actions/appConfig.js @@ -54,6 +54,7 @@ class AppConfig { this.configMap.siteRootPathRex = this.siteRootPathRex || '.*/sites(/.*)<'; this.configMap.siteRootPath = this.getSiteRootPath(params.shareUrl); this.configMap.siteFgRootPath = this.getSiteRootPath(params.fgShareUrl); + this.configMap.helixAdminApiKeys = this.getJsonFromStr(params.helixAdminApiKeys); this.extractPrivateKey(); } diff --git a/actions/copy/worker.js b/actions/copy/worker.js index f619b83..ddab799 100644 --- a/actions/copy/worker.js +++ b/actions/copy/worker.js @@ -20,8 +20,9 @@ const { updateExcelTable, getFile, saveFile, copyFile, bulkCreateFolders } = require('../sharepoint'); const { - getAioLogger, simulatePreviewPublish, handleExtension, delay, PREVIEW, logMemUsage, COPY_ACTION + getAioLogger, handleExtension, delay, PREVIEW, logMemUsage, COPY_ACTION } = require('../utils'); +const helixUtils = require('../helixUtils'); const appConfig = require('../appConfig'); const urlInfo = require('../urlInfo'); const FgStatus = require('../fgStatus'); @@ -167,7 +168,7 @@ async function floodgateContent(projectExcelPath, projectDetail, fgStatus) { for (let i = 0; i < copyStatuses.length; i += 1) { if (copyStatuses[i].success) { // eslint-disable-next-line no-await-in-loop - const result = await simulatePreviewPublish(handleExtension(copyStatuses[i].srcPath), PREVIEW, 1, true); + const result = await helixUtils.simulatePreviewPublish(handleExtension(copyStatuses[i].srcPath), PREVIEW, true); previewStatuses.push(result); } // eslint-disable-next-line no-await-in-loop diff --git a/actions/helixUtils.js b/actions/helixUtils.js new file mode 100644 index 0000000..07e2e5a --- /dev/null +++ b/actions/helixUtils.js @@ -0,0 +1,51 @@ +/* ************************************************************************ +* ADOBE CONFIDENTIAL +* ___________________ +* +* Copyright 2023 Adobe +* All Rights Reserved. +* +* NOTICE: All information contained herein is, and remains +* the property of Adobe and its suppliers, if any. The intellectual +* and technical concepts contained herein are proprietary to Adobe +* and its suppliers and are protected by all applicable intellectual +* property laws, including trade secret and copyright laws. +* Dissemination of this information or reproduction of this material +* is strictly forbidden unless prior written permission is obtained +* from Adobe. +************************************************************************* */ + +const fetch = require('node-fetch'); +const appConfig = require('./appConfig'); +const urlInfo = require('./urlInfo'); + +const MAX_RETRIES = 5; + +class HelixUtils { + async simulatePreviewPublish(path, operation, isFloodgate, retryAttempt = 1) { + let previewStatus = { success: true, path }; + try { + const repo = isFloodgate ? `${urlInfo.getRepo()}-pink` : urlInfo.getRepo(); + const previewUrl = `https://admin.hlx.page/${operation}/${urlInfo.getOwner()}/${repo}/${urlInfo.getBranch()}${path}`; + const options = { method: 'POST' }; + const { helixAdminApiKeys } = appConfig.getConfig(); + if (helixAdminApiKeys && helixAdminApiKeys[repo]) { + options.headers = new fetch.Headers(); + options.headers.append('Authorization', `token ${helixAdminApiKeys[repo]}`); + } + const response = await fetch( + `${previewUrl}`, + options, + ); + if (!response.ok && retryAttempt <= MAX_RETRIES) { + previewStatus = await this.simulatePreviewPublish(path, operation, retryAttempt + 1, isFloodgate); + } + previewStatus.responseJson = await response.json(); + } catch (error) { + previewStatus.success = false; + } + return previewStatus; + } +} + +module.exports = new HelixUtils(); diff --git a/actions/promote/worker.js b/actions/promote/worker.js index 22eac1d..101abaf 100644 --- a/actions/promote/worker.js +++ b/actions/promote/worker.js @@ -21,8 +21,9 @@ const { getAuthorizedRequestOption, saveFile, getFileUsingDownloadUrl, fetchWithRetry } = require('../sharepoint'); const { - getAioLogger, simulatePreviewPublish, handleExtension, delay, logMemUsage, getInstanceKey, PREVIEW, PUBLISH, PROMOTE_ACTION, PROMOTE_BATCH + getAioLogger, handleExtension, delay, logMemUsage, getInstanceKey, PREVIEW, PUBLISH, PROMOTE_ACTION, PROMOTE_BATCH } = require('../utils'); +const helixUtils = require('../helixUtils'); const appConfig = require('../appConfig'); const urlInfo = require('../urlInfo'); const FgStatus = require('../fgStatus'); @@ -213,7 +214,7 @@ async function promoteFloodgatedFiles(doPublish, batchManager) { for (let ip = 0; ip < promoteStatuses.length; ip += 1) { if (promoteStatuses[ip].success) { // eslint-disable-next-line no-await-in-loop - const result = await simulatePreviewPublish(handleExtension(promoteStatuses[ip].srcPath), operation, 1, false); + const result = await helixUtils.simulatePreviewPublish(handleExtension(promoteStatuses[ip].srcPath), operation, false); statuses.push(result); } await delay(); diff --git a/actions/utils.js b/actions/utils.js index 62d4722..9aa833c 100644 --- a/actions/utils.js +++ b/actions/utils.js @@ -16,9 +16,7 @@ ************************************************************************* */ const AioLogger = require('@adobe/aio-lib-core-logging'); -const fetch = require('node-fetch'); const events = require('events'); -const urlInfo = require('./urlInfo'); const COPY_ACTION = 'copyAction'; const PROMOTE_ACTION = 'promoteAction'; @@ -27,33 +25,12 @@ const DELETE_ACTION = 'deleteAction'; const PREVIEW = 'preview'; const PUBLISH = 'live'; -const MAX_RETRIES = 5; let eventEmitter = null; function getAioLogger(loggerName = 'main', logLevel = 'info') { return AioLogger(loggerName, { level: logLevel }); } -// eslint-disable-next-line default-param-last -async function simulatePreviewPublish(path, operation, retryAttempt = 1, isFloodgate) { - let previewStatus = { success: true, path }; - try { - const repo = isFloodgate ? `${urlInfo.getRepo()}-pink` : urlInfo.getRepo(); - const previewUrl = `https://admin.hlx.page/${operation}/${urlInfo.getOwner()}/${repo}/${urlInfo.getBranch()}${path}`; - const response = await fetch( - `${previewUrl}`, - { method: 'POST' }, - ); - if (!response.ok && retryAttempt <= MAX_RETRIES) { - previewStatus = await simulatePreviewPublish(path, operation, retryAttempt + 1, isFloodgate); - } - previewStatus.responseJson = await response.json(); - } catch (error) { - previewStatus.success = false; - } - return previewStatus; -} - function handleExtension(path) { if (path.endsWith('.xlsx')) { return path.replace('.xlsx', '.json'); @@ -130,7 +107,6 @@ function getInstanceKey(params) { module.exports = { getAioLogger, - simulatePreviewPublish, handleExtension, getDocPathFromUrl, delay, diff --git a/app.config.yaml b/app.config.yaml index e84a79d..baab9ec 100644 --- a/app.config.yaml +++ b/app.config.yaml @@ -23,6 +23,7 @@ application: fgAdminGroups: $FG_ADMIN_GROUPS fgDirPattern: $FG_DIR_PATTERN siteRootPathRex: $SITE_ROOT_PATH_REX + helixAdminApiKeys: $HELIX_ADMIN_API_KEYS actions: copy: function: actions/copy/copy.js