From 2cb410d2eb92ad91d479e550c95c3126f2edd1e7 Mon Sep 17 00:00:00 2001 From: karthik-tarento Date: Mon, 26 Sep 2022 19:25:57 +0530 Subject: [PATCH] Added CSV file upload and other features from 4.8.0 --- src/protectedApi_v8/resource.ts | 8 +++- src/proxies_v8/proxies_v8.ts | 59 +++++++++++++++++++++++- src/publicApi_v8/googleauth.ts | 9 +++- src/publicApi_v8/parichayAuth.ts | 8 +++- src/publicApi_v8/ssoUserHelper.ts | 71 ++--------------------------- src/utils/custom-keycloak.ts | 13 ++++++ src/utils/proxyCreator.ts | 5 ++ src/utils/whitelistApis.ts | 76 +++++++++++++++++++++++++++++++ 8 files changed, 176 insertions(+), 73 deletions(-) diff --git a/src/protectedApi_v8/resource.ts b/src/protectedApi_v8/resource.ts index 36d283e0..7e1858ec 100644 --- a/src/protectedApi_v8/resource.ts +++ b/src/protectedApi_v8/resource.ts @@ -1,4 +1,5 @@ import { Router } from 'express' +import { logInfo } from '../utils/logger' const _ = require('lodash') export const userAuthKeyCloakApi = Router() userAuthKeyCloakApi.get('/', (req, res) => { @@ -7,9 +8,14 @@ userAuthKeyCloakApi.get('/', (req, res) => { let isLocal = 0 if (!_.isEmpty(req.query)) { queryParam = req.query.q - if (queryParam.includes('localhost')) { + if (queryParam && queryParam.includes('localhost')) { isLocal = 1 } + if (req.query.redirect_uri) { + logInfo('Received redirectUrl value : ' + req.query.redirect_uri) + res.redirect(req.query.redirect_uri) + return + } } let redirectUrl = '' if (isLocal) { diff --git a/src/proxies_v8/proxies_v8.ts b/src/proxies_v8/proxies_v8.ts index e5cfaf64..05d26f0e 100644 --- a/src/proxies_v8/proxies_v8.ts +++ b/src/proxies_v8/proxies_v8.ts @@ -32,6 +32,8 @@ const API_END_POINTS = { } export const proxiesV8 = express.Router() +const _ = require('lodash') +const FILE_NOT_FOUND_ERR = 'File not found in the request' proxiesV8.get('/', (_req, res) => { res.json({ @@ -57,6 +59,7 @@ proxiesV8.post('/upload/*', (req, res) => { rootorg: 'igot', // tslint:disable-next-line: all 'x-authenticated-user-token': extractUserToken(req), + // tslint:disable-next-line: all 'x-authenticated-userid': extractUserIdFromRequest(req), }, host: 'knowledge-mw-service', @@ -79,7 +82,7 @@ proxiesV8.post('/upload/*', (req, res) => { } ) } else { - res.send('File not found') + res.send(FILE_NOT_FOUND_ERR) } }) @@ -123,7 +126,7 @@ proxiesV8.post('/private/upload/*', (_req, _res) => { } ) } else { - _res.send('File not found') + _res.send(FILE_NOT_FOUND_ERR) } }) @@ -303,6 +306,53 @@ proxiesV8.use('/dashboard/*', proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) ) +proxiesV8.post('/user/v1/bulkupload', (req, res) => { + if (req.files && req.files.data) { + const url = removePrefix('/proxies/v8', req.originalUrl) + const file: UploadedFile = req.files.data as UploadedFile + const formData = new FormData() + formData.append('file', Buffer.from(file.data), { + contentType: file.mimetype, + filename: file.name, + }) + let rootOrgId = _.get(req, 'session.rootOrgId') + if (!rootOrgId) { + rootOrgId = '' + } + formData.submit( + { + headers: { + // tslint:disable-next-line:max-line-length + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-orgid': rootOrgId, + 'x-authenticated-user-token': extractUserToken(req), + 'x-authenticated-userid': extractUserIdFromRequest(req), + }, + host: 'kong', + path: url, + port: 8000, + }, + // tslint:disable-next-line: all + (err, response) => { + // tslint:disable-next-line: all + response.on('data', (data) => { + if (!err && (response.statusCode === 200 || response.statusCode === 201)) { + res.send(JSON.parse(data.toString('utf8'))) + } else { + res.send(data.toString('utf8')) + } + }) + if (err) { + res.send(err) + } + } + ) + } else { + res.send(FILE_NOT_FOUND_ERR) + } +}) + proxiesV8.use('/user/*', proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) ) @@ -424,6 +474,11 @@ proxiesV8.use('/ratings/*', proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) ) +proxiesV8.use('/moderatoradmin/*', + // tslint:disable-next-line: max-line-length + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + function removePrefix(prefix: string, s: string) { return s.substr(prefix.length) } diff --git a/src/publicApi_v8/googleauth.ts b/src/publicApi_v8/googleauth.ts index 0f48c183..5c67477a 100644 --- a/src/publicApi_v8/googleauth.ts +++ b/src/publicApi_v8/googleauth.ts @@ -35,9 +35,9 @@ googleAuth.get('/callback', async (req, res) => { const googleProfile = await getGoogleProfile(req) logInfo('Successfully got authenticated with google...') logInfo('Email: ' + googleProfile.emailId) - let result: { errMessage: string, userExist: boolean, } + let result: { errMessage: string, rootOrgId: string, userExist: boolean, } result = await fetchUserByEmailId(googleProfile.emailId) - logInfo('isUserExist ? ' + result.userExist + ', errorMessage ? ' + result.errMessage) + logInfo('isUserExist ? ' + result.userExist + 'rootOrgId: ? ' + result.rootOrgId + ', errorMessage ? ' + result.errMessage) let isFirstTimeUser = false if (result.errMessage === '') { let createResult: { errMessage: string, userCreated: boolean, userId: string } @@ -48,6 +48,11 @@ googleAuth.get('/callback', async (req, res) => { result.errMessage = createResult.errMessage } isFirstTimeUser = true + } else { + logInfo('result.rootOrgId = ' + result.rootOrgId + ', XChannelId = ' + CONSTANTS.X_Channel_Id) + if (result.rootOrgId !== '' && result.rootOrgId === CONSTANTS.X_Channel_Id) { + isFirstTimeUser = true + } } if (result.errMessage === '') { diff --git a/src/publicApi_v8/parichayAuth.ts b/src/publicApi_v8/parichayAuth.ts index 35992d5c..7432e887 100644 --- a/src/publicApi_v8/parichayAuth.ts +++ b/src/publicApi_v8/parichayAuth.ts @@ -58,7 +58,7 @@ parichayAuth.get('/callback', async (req, res) => { url: CONSTANTS.PARICHAY_USER_DETAILS_URL, }) - let result: { errMessage: string, userExist: boolean, } + let result: { errMessage: string, rootOrgId: string, userExist: boolean, } let isFirstTimeUser = false result = await fetchUserByEmailId(userDetailResponse.data.loginId) if (result.errMessage === '') { @@ -70,6 +70,12 @@ parichayAuth.get('/callback', async (req, res) => { if (createResult.errMessage !== '') { result.errMessage = createResult.errMessage } + isFirstTimeUser = true + } else { + logInfo('result.rootOrgId = ' + result.rootOrgId + ', XChannelId = ' + CONSTANTS.X_Channel_Id) + if (result.rootOrgId !== '' && result.rootOrgId === CONSTANTS.X_Channel_Id) { + isFirstTimeUser = true + } } if (result.errMessage === '') { let keycloakResult: { diff --git a/src/publicApi_v8/ssoUserHelper.ts b/src/publicApi_v8/ssoUserHelper.ts index b754daf6..68694b2a 100644 --- a/src/publicApi_v8/ssoUserHelper.ts +++ b/src/publicApi_v8/ssoUserHelper.ts @@ -5,10 +5,7 @@ import { logError, logInfo } from '../utils/logger' import { getKeyCloakClient } from './keycloakHelper' const API_END_POINTS = { - kongAssignRoleUser: `${CONSTANTS.KONG_API_BASE}/user/private/v1/assign/role`, - kongSignUpUser: `${CONSTANTS.KONG_API_BASE}/user/v2/signup`, - kongUpdateUser: `${CONSTANTS.KONG_API_BASE}/user/private/v1/update`, - kongUserRead: (userId: string) => `${CONSTANTS.KONG_API_BASE}/user/private/v1/read/${userId}`, + cbExtSignUpUser: `${CONSTANTS.KONG_API_BASE}/user/v1/ext/signup`, } export async function fetchUserByEmailId(emailId: string) { @@ -22,7 +19,7 @@ export async function fetchUserByEmailId(emailId: string) { url: CONSTANTS.LEARNER_SERVICE_API_BASE + '/private/user/v1/search', }) const result = { - errMessage : '', userExist : false, + errMessage : '', rootOrgId: '', userExist : false, } if (sbUserSearchRes.data.responseCode.toUpperCase() === 'OK') { @@ -35,6 +32,7 @@ export async function fetchUserByEmailId(emailId: string) { if (status === 1) { logInfo('user account enabled. returning true') result.userExist = true + result.rootOrgId = contentObj.rootOrgId } else { logInfo('user account is diabled. throwing error') result.errMessage = 'Account Disabled. Please contact Admin.' @@ -69,7 +67,7 @@ export async function createUserWithMailId(emailId: string, firstNameStr: string Authorization: CONSTANTS.SB_API_KEY, }, method: 'POST', - url: API_END_POINTS.kongSignUpUser, + url: API_END_POINTS.cbExtSignUpUser, }) statusString = signUpResponse.data.params.status if (statusString.toUpperCase() !== 'SUCCESS') { @@ -78,67 +76,6 @@ export async function createUserWithMailId(emailId: string, firstNameStr: string } result.userCreated = true result.userId = signUpResponse.data.result.userId - const sbUserReadResponse = await axios({ - ...axiosRequestConfig, - headers: { - Authorization: CONSTANTS.SB_API_KEY, - }, - method: 'GET', - url: API_END_POINTS.kongUserRead(result.userId), - }) - statusString = sbUserReadResponse.data.params.status - if (statusString.toUpperCase() !== 'SUCCESS') { - result.errMessage = signUpErr + 'FAILED_TO_READ_CREATED_USER' - return Promise.resolve(result) - } - const sbUserOrgId = sbUserReadResponse.data.result.response.rootOrgId - const sbProfileUpdateReq = { - profileDetails: { - employmentDetails: { - departmentName: sbUserReadResponse.data.result.response.channel, - }, - personalDetails: { - firstname: firstNameStr, - primaryEmail: emailId, - surname: lastNameStr, - }, - }, - userId: result.userId, - } - const sbUserProfileUpdateResp = await axios({ - ...axiosRequestConfig, - data: { request: sbProfileUpdateReq }, - headers: { - Authorization: CONSTANTS.SB_API_KEY, - }, - method: 'PATCH', - url: API_END_POINTS.kongUpdateUser, - }) - statusString = sbUserProfileUpdateResp.data.params.status - if (statusString.toUpperCase() !== 'SUCCESS') { - result.errMessage = signUpErr + 'FAILED_TO_UPDATE_USER' - return Promise.resolve(result) - } - const sbAssignRoleResp = await axios({ - ...axiosRequestConfig, - data: { - request: { - organisationId: sbUserOrgId, - roles: ['PUBLIC'], - userId: result.userId, - }, - }, - headers: { - Authorization: CONSTANTS.SB_API_KEY, - }, - method: 'POST', - url: API_END_POINTS.kongAssignRoleUser, - }) - statusString = sbAssignRoleResp.data.params.status - if (statusString.toUpperCase() !== 'SUCCESS') { - result.errMessage = signUpErr + 'FAILED_TO_UPDATE_USER' - return Promise.resolve(result) - } return Promise.resolve(result) } diff --git a/src/utils/custom-keycloak.ts b/src/utils/custom-keycloak.ts index 146b1a33..2f07feec 100644 --- a/src/utils/custom-keycloak.ts +++ b/src/utils/custom-keycloak.ts @@ -121,6 +121,19 @@ export class CustomKeycloak { Authorization: reqObj.session.parichayToken.access_token, }, url: CONSTANTS.PARICHAY_REVOKE_URL, + }, (err, res, body) => { + if (err) { + logError('Received error when calling Parichay logout... ') + logError(JSON.stringify(err)) + } + if (res) { + logInfo('Received response from Parichay logout... ') + logInfo(JSON.stringify(res.body)) + } + if (body) { + logInfo('Received body from Parichay logout...') + logInfo(JSON.stringify(body)) + } }) } catch (err) { // tslint:disable-next-line: no-console diff --git a/src/utils/proxyCreator.ts b/src/utils/proxyCreator.ts index 01fba08b..1015b07b 100644 --- a/src/utils/proxyCreator.ts +++ b/src/utils/proxyCreator.ts @@ -21,6 +21,11 @@ proxy.on('proxyReq', (proxyReq: any, req: any, _res: any, _options: any) => { proxyReq.setHeader('Authorization', CONSTANTS.SB_API_KEY) proxyReq.setHeader('x-authenticated-user-token', extractUserToken(req)) proxyReq.setHeader('x-authenticated-userid', extractUserIdFromRequest(req)) + let rootOrgId = '' + if (req.session.hasOwnProperty('rootOrgId')) { + rootOrgId = req.session.rootOrgId + } + proxyReq.setHeader('x-authenticated-user-orgid', rootOrgId) // condition has been added to set the session in nodebb req header /* tslint:disable-next-line */ diff --git a/src/utils/whitelistApis.ts b/src/utils/whitelistApis.ts index de5c7d89..8f66bbea 100644 --- a/src/utils/whitelistApis.ts +++ b/src/utils/whitelistApis.ts @@ -1798,6 +1798,72 @@ export const API_LIST = { ROLE.PUBLIC, ], }, + '/proxies/v8/forms/tagFormToCourse': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/forms/untagFormToCourse': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/forms/getAllApplications': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/forms/searchForms': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/moderatoradmin/feedback/persist/text/moderated': { + ROLE_CHECK: [ + ROLE.SPV_ADMIN, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/moderatoradmin/feedback/text/fetch': { + ROLE_CHECK: [ + ROLE.SPV_ADMIN, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/moderatoradmin/profanity/type/text': { + ROLE_CHECK: [ + ROLE.SPV_ADMIN, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/moderatoradmin/feedback/flag/values': { + ROLE_CHECK: [ + ROLE.SPV_ADMIN, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/user/v1/bulkupload': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, + '/proxies/v8/user/v1/bulkupload/:orgId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, }, URL_PATTERN: [ @@ -2036,5 +2102,15 @@ export const API_LIST = { '/proxies/v8/org/ext/v1/create', '/proxies/v8/user/basicInfo', '/proxies/v8/user/basicProfileUpdate', + '/proxies/v8/forms/getAllApplications', + '/proxies/v8/forms/tagFormToCourse', + '/proxies/v8/forms/untagFormToCourse', + '/proxies/v8/forms/searchForms', + '/proxies/v8/moderatoradmin/feedback/persist/text/moderated', + '/proxies/v8/moderatoradmin/feedback/text/fetch', + '/proxies/v8/moderatoradmin/profanity/type/text', + '/proxies/v8/moderatoradmin/feedback/flag/values', + '/proxies/v8/user/v1/bulkupload', + '/proxies/v8/user/v1/bulkupload/:orgId', ], }