From a31347359dba5c299d827a6a3ba0cc2e0bf08b32 Mon Sep 17 00:00:00 2001 From: amit-kumaryadav Date: Wed, 8 Sep 2021 18:16:54 +0530 Subject: [PATCH 1/6] Added proxy for private content update --- src/protectedApi_v8/contentprivate.ts | 115 ++++++++++++++++++++++++++ src/protectedApi_v8/protectedApiV8.ts | 2 + 2 files changed, 117 insertions(+) create mode 100644 src/protectedApi_v8/contentprivate.ts diff --git a/src/protectedApi_v8/contentprivate.ts b/src/protectedApi_v8/contentprivate.ts new file mode 100644 index 00000000..7d5e9c6e --- /dev/null +++ b/src/protectedApi_v8/contentprivate.ts @@ -0,0 +1,115 @@ +import axios from 'axios' +import { Router } from 'express' + +import { axiosRequestConfig } from '../configs/request.config' +import { CONSTANTS } from '../utils/env' +import { logError } from '../utils/logger' +import { ERROR } from '../utils/message' +import { extractUserId, extractUserToken } from '../utils/requestExtract' + +export const contentPrivateApi = Router() + +const API_END_POINTS = { + getHierarchyDetails: (id: string) => `${CONSTANTS.KNOWLEDGE_MW_API_BASE}/action/content/v3/hierarchy/${id}?mode=edit`, + readUserEndPoint: (userId: string) => `${CONSTANTS.KONG_API_BASE}/user/v2/read/${userId}`, + updateContentEndPoint: (id: string) => `${CONSTANTS.KONG_API_BASE}/private/content/v3/update/${id}`, +} + +const editableFields = ['versionKey', 'createdBy', 'creatorContacts'] +const userIdFailedMessage = 'NO_USER_ID' +const FIELD_VALIDATION_ERROR = 'TRYING_TO_UPDATE_NON_EDITABLE_FIELDS' +const CHANNEL_VALIDATION_ERROR = 'SOURCE_MISMATCH_ERROR' + +contentPrivateApi.patch('/update/:id', async (req, res) => { + try { + const id = req.params.id + const content = req.body.content + const fields = Object.keys(content) + const userId = extractUserId(req) + const userToken = extractUserToken(req) as string + if (!userId) { + res.status(400).send(userIdFailedMessage) + return + } + if (fields instanceof Array) { + for (const entry of fields) { + if (editableFields.indexOf(entry) === -1) { + res.status(400).send({ + msg: res.status(400).send({ + msg: FIELD_VALIDATION_ERROR, + }), + }) + } + } + } + const userChannel = getUserChannel(userToken, userId) + const hierarchySource = getHierarchyDetails(userToken, id) + if (userChannel !== hierarchySource) { + res.status(400).send({ + msg: res.status(400).send({ + msg: CHANNEL_VALIDATION_ERROR, + }), + }) + } + const response = await axios.patch( + API_END_POINTS.updateContentEndPoint(id), + req.body, + { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': userToken, + }, + } + ) + res.status(response.status).send(response.data) + } catch (err) { + logError(Error + err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: ERROR.GENERAL_ERR_MSG, + } + ) + } +}) + +export async function getHierarchyDetails(token: string, id: string) { + try { + const response = await axios.get(API_END_POINTS.getHierarchyDetails(id), { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': token, + }, + }) + const hierarchyResult = response.data.result.content + if (typeof hierarchyResult !== 'undefined' && hierarchyResult != null) { + return hierarchyResult.source + } + } catch (error) { + logError('ERROR WHILE FETCHING THE Hierarchy DETAILS --> ', error) + return 'contentSourceDetails' + } +} + +export async function getUserChannel(token: string, userId: string) { + try { + const response = await axios.get(API_END_POINTS.readUserEndPoint(userId), { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': token, + }, + }) + const userProfileResult = response.data.result.response + if (typeof userProfileResult !== 'undefined' && userProfileResult != null) { + return userProfileResult.channel + } + } catch (error) { + logError('ERROR WHILE FETCHING THE USER DETAILS --> ', error) + return 'userChannelDetails' + } +} diff --git a/src/protectedApi_v8/protectedApiV8.ts b/src/protectedApi_v8/protectedApiV8.ts index 9f92a395..1bbb53e0 100644 --- a/src/protectedApi_v8/protectedApiV8.ts +++ b/src/protectedApi_v8/protectedApiV8.ts @@ -11,6 +11,7 @@ import { conceptGraphApi } from './concept' // import { connectionsApi } from './connections' import { connectionsV2Api } from './connections_v2' import { contentApi } from './content' +import { contentPrivateApi } from './contentprivate' import { contentValidationApi } from './contentValidation' import { counterApi } from './counter' import { deptApi } from './departments' @@ -79,3 +80,4 @@ protectedApiV8.use('/roleactivity', roleActivityApi) protectedApiV8.use('/resource', userAuthKeyCloakApi) protectedApiV8.use('/workallocation', workAllocationApi) protectedApiV8.use('/frac', fracApi) +protectedApiV8.use('/contentprivate', contentPrivateApi) From 1c76483fe137fdd05d7f47c159b7eff01fbb5960 Mon Sep 17 00:00:00 2001 From: amit-kumaryadav Date: Thu, 9 Sep 2021 15:16:38 +0530 Subject: [PATCH 2/6] Review comments --- src/protectedApi_v8/contentprivate.ts | 4 ++-- src/utils/permissionHelper.ts | 3 +++ src/utils/requestExtract.ts | 8 ++++++++ src/utils/whitelistApis.ts | 8 ++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/protectedApi_v8/contentprivate.ts b/src/protectedApi_v8/contentprivate.ts index 7d5e9c6e..0f41793e 100644 --- a/src/protectedApi_v8/contentprivate.ts +++ b/src/protectedApi_v8/contentprivate.ts @@ -5,7 +5,7 @@ import { axiosRequestConfig } from '../configs/request.config' import { CONSTANTS } from '../utils/env' import { logError } from '../utils/logger' import { ERROR } from '../utils/message' -import { extractUserId, extractUserToken } from '../utils/requestExtract' +import { extractUserId, extractUserToken, extractUserOrgData } from '../utils/requestExtract' export const contentPrivateApi = Router() @@ -42,7 +42,7 @@ contentPrivateApi.patch('/update/:id', async (req, res) => { } } } - const userChannel = getUserChannel(userToken, userId) + const userChannel = extractUserOrgData(req) const hierarchySource = getHierarchyDetails(userToken, id) if (userChannel !== hierarchySource) { res.status(400).send({ diff --git a/src/utils/permissionHelper.ts b/src/utils/permissionHelper.ts index 952dd976..214381f9 100644 --- a/src/utils/permissionHelper.ts +++ b/src/utils/permissionHelper.ts @@ -15,6 +15,9 @@ export const PERMISSION_HELPER = { reqObj.session.userRoles = userData.result.response.roles reqObj.session.orgs = userData.result.response.organisations reqObj.session.rootOrgId = userData.result.response.rootOrgId + reqObj.session.channel = userData.result.response.rootOrg.channel + reqObj.session.orgName = userData.result.response.rootOrg.orgName + if (!_.includes(reqObj.session.userRoles, 'PUBLIC')) { reqObj.session.userRoles.push('PUBLIC') } diff --git a/src/utils/requestExtract.ts b/src/utils/requestExtract.ts index c161f177..c6367653 100644 --- a/src/utils/requestExtract.ts +++ b/src/utils/requestExtract.ts @@ -1,5 +1,6 @@ import { Request } from 'express' import uuid from 'uuid' +import _ from 'lodash' export interface IAuthorizedRequest extends Request { kauth?: { grant: { @@ -73,4 +74,11 @@ export const extractRootOrgFromRequest = (req: IAuthorizedRequest): string => { } +export const extractUserOrgData = (req: Request) => { + return (_.get(req, 'session.orgs')) ? _.get(req, 'session.orgs') : [] +} + + + + export const getUUID = () => uuid.v1() diff --git a/src/utils/whitelistApis.ts b/src/utils/whitelistApis.ts index 5376810c..638afd85 100644 --- a/src/utils/whitelistApis.ts +++ b/src/utils/whitelistApis.ts @@ -1209,6 +1209,13 @@ export const API_LIST = { ROLE.PUBLIC, ], }, + '/protected/v8/contentprivate/update/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, }, URL_PATTERN: [ @@ -1379,5 +1386,6 @@ export const API_LIST = { '/protected/v8/connections/v2/connections/suggests', '/protected/v8/connections/v2/update/connection', '/protected/v8/user/profileDetails/createUserWithoutInvitationEmail', + '/protected/v8/contentprivate/update/:id', ], } From 34a119d5cfc4735ca85633325277fd91cc75e2bc Mon Sep 17 00:00:00 2001 From: amit-kumaryadav Date: Thu, 9 Sep 2021 16:54:08 +0530 Subject: [PATCH 3/6] Added logs --- src/protectedApi_v8/contentprivate.ts | 10 ++++++++-- src/utils/requestExtract.ts | 5 +---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/protectedApi_v8/contentprivate.ts b/src/protectedApi_v8/contentprivate.ts index 0f41793e..2994685c 100644 --- a/src/protectedApi_v8/contentprivate.ts +++ b/src/protectedApi_v8/contentprivate.ts @@ -5,7 +5,7 @@ import { axiosRequestConfig } from '../configs/request.config' import { CONSTANTS } from '../utils/env' import { logError } from '../utils/logger' import { ERROR } from '../utils/message' -import { extractUserId, extractUserToken, extractUserOrgData } from '../utils/requestExtract' +import { extractUserId, extractUserOrgData, extractUserToken } from '../utils/requestExtract' export const contentPrivateApi = Router() @@ -23,7 +23,7 @@ const CHANNEL_VALIDATION_ERROR = 'SOURCE_MISMATCH_ERROR' contentPrivateApi.patch('/update/:id', async (req, res) => { try { const id = req.params.id - const content = req.body.content + const content = req.body.request.content const fields = Object.keys(content) const userId = extractUserId(req) const userToken = extractUserToken(req) as string @@ -42,8 +42,14 @@ contentPrivateApi.patch('/update/:id', async (req, res) => { } } } + // tslint:disable-next-line: no-console + console.log('calling for user channel') const userChannel = extractUserOrgData(req) + // tslint:disable-next-line: no-console + console.log('user channel '+userChannel) const hierarchySource = getHierarchyDetails(userToken, id) + // tslint:disable-next-line: no-console + console.log('hierarchy source '+hierarchySource) if (userChannel !== hierarchySource) { res.status(400).send({ msg: res.status(400).send({ diff --git a/src/utils/requestExtract.ts b/src/utils/requestExtract.ts index c6367653..8143eb58 100644 --- a/src/utils/requestExtract.ts +++ b/src/utils/requestExtract.ts @@ -1,6 +1,6 @@ import { Request } from 'express' -import uuid from 'uuid' import _ from 'lodash' +import uuid from 'uuid' export interface IAuthorizedRequest extends Request { kauth?: { grant: { @@ -78,7 +78,4 @@ export const extractUserOrgData = (req: Request) => { return (_.get(req, 'session.orgs')) ? _.get(req, 'session.orgs') : [] } - - - export const getUUID = () => uuid.v1() From 49fb5311da6543a6cf27c1534b9892af1b2e5e44 Mon Sep 17 00:00:00 2001 From: amit-kumaryadav Date: Thu, 9 Sep 2021 17:16:07 +0530 Subject: [PATCH 4/6] Logs ...... --- src/protectedApi_v8/contentprivate.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/protectedApi_v8/contentprivate.ts b/src/protectedApi_v8/contentprivate.ts index 2994685c..fa52ea0b 100644 --- a/src/protectedApi_v8/contentprivate.ts +++ b/src/protectedApi_v8/contentprivate.ts @@ -3,7 +3,7 @@ import { Router } from 'express' import { axiosRequestConfig } from '../configs/request.config' import { CONSTANTS } from '../utils/env' -import { logError } from '../utils/logger' +import { logInfo, logError } from '../utils/logger' import { ERROR } from '../utils/message' import { extractUserId, extractUserOrgData, extractUserToken } from '../utils/requestExtract' @@ -45,11 +45,11 @@ contentPrivateApi.patch('/update/:id', async (req, res) => { // tslint:disable-next-line: no-console console.log('calling for user channel') const userChannel = extractUserOrgData(req) - // tslint:disable-next-line: no-console - console.log('user channel '+userChannel) + logInfo("============== user channel") + logInfo(userChannel) const hierarchySource = getHierarchyDetails(userToken, id) // tslint:disable-next-line: no-console - console.log('hierarchy source '+hierarchySource) + console.log('hierarchy source ' + hierarchySource) if (userChannel !== hierarchySource) { res.status(400).send({ msg: res.status(400).send({ @@ -91,7 +91,12 @@ export async function getHierarchyDetails(token: string, id: string) { }, }) const hierarchyResult = response.data.result.content + const bodyData = JSON.stringify(hierarchyResult) + // tslint:disable-next-line: no-console + console.log('body data=====>', bodyData) if (typeof hierarchyResult !== 'undefined' && hierarchyResult != null) { + logInfo("============== hierarchy source") + logInfo(hierarchyResult.source) return hierarchyResult.source } } catch (error) { From d490efc26b42af69e9e97b271b4ba585d68755d2 Mon Sep 17 00:00:00 2001 From: amit-kumaryadav Date: Thu, 9 Sep 2021 18:45:17 +0530 Subject: [PATCH 5/6] await issue --- src/protectedApi_v8/contentprivate.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/protectedApi_v8/contentprivate.ts b/src/protectedApi_v8/contentprivate.ts index fa52ea0b..c7143e0b 100644 --- a/src/protectedApi_v8/contentprivate.ts +++ b/src/protectedApi_v8/contentprivate.ts @@ -3,7 +3,7 @@ import { Router } from 'express' import { axiosRequestConfig } from '../configs/request.config' import { CONSTANTS } from '../utils/env' -import { logInfo, logError } from '../utils/logger' +import { logError, logInfo } from '../utils/logger' import { ERROR } from '../utils/message' import { extractUserId, extractUserOrgData, extractUserToken } from '../utils/requestExtract' @@ -45,9 +45,10 @@ contentPrivateApi.patch('/update/:id', async (req, res) => { // tslint:disable-next-line: no-console console.log('calling for user channel') const userChannel = extractUserOrgData(req) - logInfo("============== user channel") - logInfo(userChannel) - const hierarchySource = getHierarchyDetails(userToken, id) + const channelData = JSON.stringify(userChannel) + // tslint:disable-next-line: no-console + console.log('channelData=====>', channelData) + const hierarchySource = await getHierarchyDetails(userToken, id) // tslint:disable-next-line: no-console console.log('hierarchy source ' + hierarchySource) if (userChannel !== hierarchySource) { @@ -91,13 +92,8 @@ export async function getHierarchyDetails(token: string, id: string) { }, }) const hierarchyResult = response.data.result.content - const bodyData = JSON.stringify(hierarchyResult) - // tslint:disable-next-line: no-console - console.log('body data=====>', bodyData) - if (typeof hierarchyResult !== 'undefined' && hierarchyResult != null) { - logInfo("============== hierarchy source") - logInfo(hierarchyResult.source) - return hierarchyResult.source + if (typeof hierarchyResult !== 'undefined' && hierarchyResult != null) { + return hierarchyResult.source } } catch (error) { logError('ERROR WHILE FETCHING THE Hierarchy DETAILS --> ', error) From b994cac26dad09b5ea4cfdb634e341558d4da3ac Mon Sep 17 00:00:00 2001 From: amit-kumaryadav Date: Thu, 9 Sep 2021 18:47:22 +0530 Subject: [PATCH 6/6] await issue --- src/protectedApi_v8/contentprivate.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/protectedApi_v8/contentprivate.ts b/src/protectedApi_v8/contentprivate.ts index c7143e0b..b7d9dfea 100644 --- a/src/protectedApi_v8/contentprivate.ts +++ b/src/protectedApi_v8/contentprivate.ts @@ -3,7 +3,7 @@ import { Router } from 'express' import { axiosRequestConfig } from '../configs/request.config' import { CONSTANTS } from '../utils/env' -import { logError, logInfo } from '../utils/logger' +import { logError} from '../utils/logger' import { ERROR } from '../utils/message' import { extractUserId, extractUserOrgData, extractUserToken } from '../utils/requestExtract' @@ -47,7 +47,7 @@ contentPrivateApi.patch('/update/:id', async (req, res) => { const userChannel = extractUserOrgData(req) const channelData = JSON.stringify(userChannel) // tslint:disable-next-line: no-console - console.log('channelData=====>', channelData) + console.log('channelData=====>', channelData) const hierarchySource = await getHierarchyDetails(userToken, id) // tslint:disable-next-line: no-console console.log('hierarchy source ' + hierarchySource) @@ -92,7 +92,7 @@ export async function getHierarchyDetails(token: string, id: string) { }, }) const hierarchyResult = response.data.result.content - if (typeof hierarchyResult !== 'undefined' && hierarchyResult != null) { + if (typeof hierarchyResult !== 'undefined' && hierarchyResult != null) { return hierarchyResult.source } } catch (error) {