chore: remove unnecessary comments and improve requests handling

master
adriano 2024-09-24 09:10:18 -03:00
parent 0524aef1b0
commit 75659672bf
25 changed files with 573 additions and 412 deletions

3
.gitignore vendored
View File

@ -7,5 +7,8 @@
**/backend/public/jsonfiles **/backend/public/jsonfiles
**/backend/public/uploads **/backend/public/uploads
**/backend/build
**/frontend/dist
/node_modules /node_modules

View File

@ -64,7 +64,7 @@ app.use('/api-docs', swaggerUI.serve, swaggerUI.setup(swaggerDocument))
app.use('/api/v1/crm', crmRouter) app.use('/api/v1/crm', crmRouter)
app.use(notFoundMiddlware) app.use(notFoundMiddlware)
app.use(errorHandlerMiddleware) // app.use(errorHandlerMiddleware)
const port = process.env.PORT || 3000 const port = process.env.PORT || 3000

View File

@ -33,10 +33,14 @@ const contactCreate = async (req, res) => {
const deleteCrm = async (req, res) => { const deleteCrm = async (req, res) => {
const { companyId, crmBaseURL } = req.body let { companyId, crmBaseURL } = req.body
mustContainProperties(req, ['companyId', 'crmBaseURL',]) mustContainProperties(req, ['companyId', 'crmBaseURL',])
if (!crmBaseURL.startsWith('http://') && !crmBaseURL.startsWith('https://')) {
crmBaseURL = `https://${crmBaseURL.trim()}`
}
const crm = await CRM.findOne({ const crm = await CRM.findOne({
companyId, crmBaseURL: new URL(crmBaseURL.trim()).hostname companyId, crmBaseURL: new URL(crmBaseURL.trim()).hostname
}) })
@ -61,9 +65,18 @@ const deleteCompany = async (req, res) => {
const callJournaling = async (req, res) => { const callJournaling = async (req, res) => {
const { companyId, operation, crmPhone, crmAgent, crmCallDuration, crmFirstName, operationStatus } = req.body let { companyId, operation, crmPhone, crmAgent, crmCallDuration, crmFirstName, operationStatus } = req.body
console.log('REQ.BODY CRM TEST: ', JSON.stringify(req.body, null, 6)) console.log('REQ.BODY CRM TESTe: ', JSON.stringify(req.body, null, 6))
// return res.status(StatusCodes.OK).send()
crmPhone = '55' + crmPhone
console.log('========> CRMPHONE: ', crmPhone)
console.log('========> COMPANY ID before: ', companyId)
companyId = '40'
console.log('========> COMPANY ID after: ', companyId)
mustContainProperties(req, ['companyId', 'operation', 'crmPhone', 'crmAgent',]) mustContainProperties(req, ['companyId', 'operation', 'crmPhone', 'crmAgent',])
@ -72,9 +85,15 @@ const callJournaling = async (req, res) => {
// if (operation == 'outboundAsweredCall' && !crmCallDuration) // if (operation == 'outboundAsweredCall' && !crmCallDuration)
// throw new CustomError.BadRequestError(`The crmCallDuration property must be provided when operation is outboundAsweredCall`) // throw new CustomError.BadRequestError(`The crmCallDuration property must be provided when operation is outboundAsweredCall`)
if (!crmCallDuration || crmCallDuration.trim() == "")
crmCallDuration = "300"
if (operationStatus == "hangup") if (operationStatus == "hangup")
await journaling(companyId, operation, crmPhone, crmAgent, crmCallDuration, crmFirstName) await journaling(companyId, operation, crmPhone, crmAgent, crmCallDuration, crmFirstName)
else if (operationStatus == "update-answer") { else if (operationStatus == "update-answer") {
console.log('update-answer')
await ticketCRM(companyId, crmPhone, crmAgent, crmFirstName) await ticketCRM(companyId, crmPhone, crmAgent, crmFirstName)
} }
@ -85,6 +104,8 @@ const install = async (req, res) => {
const { authUrl, companyId } = req.query const { authUrl, companyId } = req.query
console.log('--------> authUrl: ', authUrl)
// Store the authUrl in the session // Store the authUrl in the session
req.session.authUrl = authUrl req.session.authUrl = authUrl
@ -98,6 +119,8 @@ const oauthCallBack = async (req, res) => {
// Retrieve the stored authUrl from the session // Retrieve the stored authUrl from the session
const storedAuthUrl = req.session.authUrl const storedAuthUrl = req.session.authUrl
console.log('xxxxxxxxxx storedAuthUrl: ', storedAuthUrl)
const parsedUrl = new URL(storedAuthUrl) const parsedUrl = new URL(storedAuthUrl)
const clientId = parsedUrl.searchParams.get('client_id') const clientId = parsedUrl.searchParams.get('client_id')
@ -105,12 +128,20 @@ const oauthCallBack = async (req, res) => {
let crmOauth = await CRM.findOne({ 'crm.authentication.crmClientId': clientId }) let crmOauth = await CRM.findOne({ 'crm.authentication.crmClientId': clientId })
crmOauth = crmOauth.toObject() crmOauth = crmOauth.toObject()
const authCodeProof = { let authCodeProof = {
grant_type: 'authorization_code', grant_type: 'authorization_code',
client_id: crmOauth.crm.authentication.crmClientId, client_id: crmOauth.crm.authentication.crmClientId,
client_secret: crmOauth.crm.authentication.crmClientSecret, client_secret: crmOauth.crm.authentication.crmClientSecret,
redirect_uri: process.env.URL_OAUTH_CALLBACK, redirect_uri: process.env.URL_OAUTH_CALLBACK,
code
//remove this
// refactor this. To salesforce only when using oauth2
code_verifier: `gwkPueV2GSzkFvGFiHbNjpRuq_XBEGBsihM59pMaiFalZrOQ_7J4hgtBR8GIbLHutcuUwba2k0xeKhD8ELjWEswE3xv-H2e6Jh8EOwOccj2i_rYPUlMGdPDqpuRs8D3w`,
code: `${code.split('%')[0]}`
//
//enable this
// code
} }
// Exchange the authorization code for an access token and refresh token // Exchange the authorization code for an access token and refresh token
@ -137,7 +168,6 @@ const testTemplate = async (req, res) => {
crmOauth = crmOauth.toObject() crmOauth = crmOauth.toObject()
const { crmPhoneTest } = crmOauth.crm.authentication const { crmPhoneTest } = crmOauth.crm.authentication
await templateValidator(crmPhoneTest, crmOauth.crm, companyId) await templateValidator(crmPhoneTest, crmOauth.crm, companyId)
crmOauth = await CRM.findOne({ 'crm.authentication.crmClientId': clientId }) crmOauth = await CRM.findOne({ 'crm.authentication.crmClientId': clientId })
@ -206,7 +236,7 @@ const uploadCrmConfig = async (req, res) => {
.replace('crmRedirectURI', process.env.URL_OAUTH_CALLBACK) .replace('crmRedirectURI', process.env.URL_OAUTH_CALLBACK)
const authUrl = `http://localhost:6001/api/v1/crm/install?authUrl=${encodeURIComponent(url)}&companyId=${encodeURIComponent(companyId)}` const authUrl = `https://api-integracao-crm.hitmanager.app.br/api/v1/crm/install?authUrl=${encodeURIComponent(url)}&companyId=${encodeURIComponent(companyId)}`
console.log('--------> authUrl: ', authUrl) console.log('--------> authUrl: ', authUrl)
return res.status(StatusCodes.OK).json({ url: authUrl }) return res.status(StatusCodes.OK).json({ url: authUrl })
@ -223,6 +253,18 @@ const uploadCrmConfig = async (req, res) => {
res.status(StatusCodes.OK).send() res.status(StatusCodes.OK).send()
} }
const getCrms = async (req, res) => {
const { companyId, } = req.params
if (!companyId)
throw new CustomError.BadRequestError(`The companyId must be provided in the URL`)
const crms = await CRM.find({ companyId }, { _id: 1, crmBaseURL: 1, createdAt: 1, companyId: 1, enabled: 1 })
res.status(StatusCodes.OK).send(crms)
}
module.exports = { module.exports = {
contactCreate, contactCreate,
uploadCrmConfig, uploadCrmConfig,
@ -231,7 +273,8 @@ module.exports = {
install, install,
deleteCrm, deleteCrm,
deleteCompany, deleteCompany,
testTemplate testTemplate,
getCrms
} }

View File

@ -2,19 +2,21 @@ const CustomError = require('../errors')
const authorization = async (req, res, next) => { const authorization = async (req, res, next) => {
// next()
const authHeader = req.headers.authorization const authHeader = req.headers.authorization
if (!authHeader) { if (!authHeader) {
throw new CustomError.BadRequestError('Authorization not found into header!') throw new CustomError.BadRequestError('Authorization not found into header!')
} }
const [, token] = authHeader.split(" "); const [, token] = authHeader.split(" ")
if (!token) { if (!token) {
throw new CustomError.BadRequestError('Authorization token not found into header!') throw new CustomError.BadRequestError('Authorization token not found into header!')
} }
if (token != process.env.TOKEN){ if (token != process.env.TOKEN) {
throw new CustomError.UnauthorizedError('Authorization token Invalid') throw new CustomError.UnauthorizedError('Authorization token Invalid')
} }

View File

@ -3449,7 +3449,8 @@
"express-async-errors": { "express-async-errors": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz", "resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz",
"integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==" "integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==",
"requires": {}
}, },
"express-rate-limit": { "express-rate-limit": {
"version": "5.5.1", "version": "5.5.1",
@ -4791,7 +4792,8 @@
"ws": { "ws": {
"version": "8.11.0", "version": "8.11.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==" "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
"requires": {}
}, },
"xdg-basedir": { "xdg-basedir": {
"version": "4.0.0", "version": "4.0.0",

View File

@ -1,7 +1,7 @@
const express = require('express') const express = require('express')
const router = express.Router() const router = express.Router()
const { authorization, } = require('../middleware/authentication') const { authorization, } = require('../middleware/authentication')
const { contactCreate, testTemplate, uploadCrmConfig, callJournaling, oauthCallBack, install, deleteCrm, deleteCompany } = require('../controllers/crmController') const { contactCreate, testTemplate, uploadCrmConfig, callJournaling, oauthCallBack, install, deleteCrm, deleteCompany, getCrms } = require('../controllers/crmController')
const { fileUpload } = require("../utils") const { fileUpload } = require("../utils")
router.route('/create-contact').post(authorization, contactCreate) router.route('/create-contact').post(authorization, contactCreate)
@ -12,5 +12,6 @@ router.route('/delete-company').post(authorization, deleteCompany)
router.route('/oauth-callback').get(oauthCallBack) router.route('/oauth-callback').get(oauthCallBack)
router.route('/install').get(install) router.route('/install').get(install)
router.route('/test').post(testTemplate) router.route('/test').post(testTemplate)
router.route('/:companyId').get(authorization, getCrms)
module.exports = router module.exports = router

View File

@ -49,6 +49,10 @@ async function createContact(companyId, rest, authentication, crmPhone, crmFirst
sendMessageSocket({ companyId, status: 'processing', data: { request: config, msg } }) sendMessageSocket({ companyId, status: 'processing', data: { request: config, msg } })
} }
console.log('#####################')
console.log('CREATE CONTACT PAYLOAD: ', JSON.stringify(config, null, 6))
console.log('#####################')
let { data } = await axios(config) let { data } = await axios(config)
data = flatten(data) data = flatten(data)

View File

@ -49,6 +49,20 @@ function getPastDateTimeFromSeconds(currentTime, secondsToSubtract) {
return formattedPastDateTime return formattedPastDateTime
} }
function currentYearMonthDay() {
const originalDate = 'YYYY-MM-DD'
const parsedDate = new Date(originalDate)
const today = new Date()
parsedDate.setFullYear(today.getFullYear())
parsedDate.setMonth(today.getMonth())
parsedDate.setDate(today.getDate())
return parsedDate.toISOString().split('T')[0]
}
module.exports = { dateTime, secondsFormat, getPastDateTimeFromSeconds }
module.exports = { dateTime, secondsFormat, getPastDateTimeFromSeconds, currentYearMonthDay }

View File

@ -0,0 +1,17 @@
function get75PercentTimeInSeconds(issuedAt) {
const twoHoursInSeconds = 2 * 60 * 60
const seventyFivePercent = twoHoursInSeconds * 0.75
const currentTimeInSeconds = Math.floor(Date.now() / 1000)
const issuedAtInSeconds = Math.floor(issuedAt / 1000)
const elapsedTimeInSeconds = currentTimeInSeconds - issuedAtInSeconds
const remainingTimeInSeconds = seventyFivePercent - elapsedTimeInSeconds
if (remainingTimeInSeconds <= 0) {
return 0
}
return Math.round(remainingTimeInSeconds)
}
module.exports = get75PercentTimeInSeconds

View File

@ -25,9 +25,10 @@ const socketIO = require('./socketIO')
const sendMessageSocket = require('./sendMessageSocket') const sendMessageSocket = require('./sendMessageSocket')
const templateValidator = require('./templateValidator') const templateValidator = require('./templateValidator')
const ticketCRM = require('./ticketCRM') const ticketCRM = require('./ticketCRM')
const get75PercentTimeInSeconds = require('./get75PercentTimeInSeconds')
module.exports = { module.exports = {
get75PercentTimeInSeconds,
fileUpload, fileUpload,
loadCRM, loadCRM,
crmCompany, crmCompany,

View File

@ -1,4 +1,4 @@
const { dateTime, secondsFormat, getPastDateTimeFromSeconds } = require('./dateTime') const { dateTime, secondsFormat, getPastDateTimeFromSeconds, currentYearMonthDay } = require('./dateTime')
const requestConfigHeader = require('./requestConfigHeader') const requestConfigHeader = require('./requestConfigHeader')
const flatten = require('flat') const flatten = require('flat')
const unflatten = require('flat').unflatten const unflatten = require('flat').unflatten
@ -10,6 +10,9 @@ const sendMessageSocket = require('./sendMessageSocket')
async function journalingRequest(request, body, crmCallDuration, contact, crmAgent, crmPhone, authentication, test = {}) { async function journalingRequest(request, body, crmCallDuration, contact, crmAgent, crmPhone, authentication, test = {}) {
const { requestContentType, requestEncoding, requestType, responseType, url } = request const { requestContentType, requestEncoding, requestType, responseType, url } = request
console.log('----------> crmCallDuration: ', crmCallDuration)
console.log('----------> url: ', url)
body = flatten(body) body = flatten(body)
let ignore = [] let ignore = []
@ -90,12 +93,27 @@ async function journalingRequest(request, body, crmCallDuration, contact, crmAge
case 'crmCallDuration': case 'crmCallDuration':
body[key] = crmCallDuration body[key] = crmCallDuration
break break
case 'YYYY-MM-DD':
body[key] = currentYearMonthDay()
break
} }
} }
const data = unflatten(body) const data = unflatten(body)
// Refactor this. Some times the crmCallDuration is comming with the value like 'crmCallDuration' instead of number when
// creating call journaling for salesforce
if (url.includes('salesforce')) {
for (let key in data) {
if (data[key] == 'crmCallDuration') {
data[key] = 300
}
}
}
const { type, userName, passWord, token, crmClientId } = authentication const { type, userName, passWord, token, crmClientId } = authentication
const config = await requestConfigHeader(url, crmPhone, requestType, requestContentType, type, userName, passWord, token, crmClientId, data) const config = await requestConfigHeader(url, crmPhone, requestType, requestContentType, type, userName, passWord, token, crmClientId, data)
@ -103,9 +121,18 @@ async function journalingRequest(request, body, crmCallDuration, contact, crmAge
if (test?.testing && test?.companyId && test?.msg) { if (test?.testing && test?.companyId && test?.msg) {
sendMessageSocket({ companyId: test.companyId, status: 'processing', data: { request: config, msg: test.msg } }) sendMessageSocket({ companyId: test.companyId, status: 'processing', data: { request: config, msg: test.msg } })
} }
// console.log('JOURNALING CONFIG: ', config)
console.log('#####################')
console.log('CONFIG CALL JOURNALING: ', JSON.stringify(config, null, 6))
console.log('#####################')
try {
const res = await axios(config) const res = await axios(config)
} catch (error) {
console.log(`CALL JOURNALING ERROR: `, error)
}
} }
module.exports = journalingRequest module.exports = journalingRequest

View File

@ -4,6 +4,7 @@ const findProperty = require('./findProperty')
const CRM = require('../models/CRM') const CRM = require('../models/CRM')
const { set, get, del } = require('./redisClient') const { set, get, del } = require('./redisClient')
const get75PercentTimeInSeconds = require('./get75PercentTimeInSeconds')
const exchangeForTokens = async (crmOauth, exchangeProof) => { const exchangeForTokens = async (crmOauth, exchangeProof) => {
@ -25,10 +26,19 @@ const exchangeForTokens = async (crmOauth, exchangeProof) => {
} }
} }
console.log('CONFIG: ', config)
const { data } = await axios(config) const { data } = await axios(config)
const { refresh_token, access_token, token_type, expires_in } = data const { refresh_token, access_token, token_type, expires_in, issued_at } = data
console.log('===========> refresh_token: ', refresh_token)
console.log('===========> access_token: ', access_token)
// salesforce case
if (issued_at)
await set(crmOauth.crm.authentication.crmClientId, access_token, get75PercentTimeInSeconds(issued_at))
else
await set(crmOauth.crm.authentication.crmClientId, access_token, Math.round(expires_in * 0.75)) await set(crmOauth.crm.authentication.crmClientId, access_token, Math.round(expires_in * 0.75))
crmOauth = await CRM.findOne({ 'crm.authentication.crmClientId': crmOauth.crm.authentication.crmClientId }) crmOauth = await CRM.findOne({ 'crm.authentication.crmClientId': crmOauth.crm.authentication.crmClientId })

View File

@ -59,8 +59,9 @@ const initIO = (httpServer) => {
io = SocketIO(httpServer, { io = SocketIO(httpServer, {
cors: { cors: {
origin: IS_DEV ? "*" : [process.env.URL_OAUTH_FRONTEND_SUCCESS_REDIRECT, process.env.URL_HITPHONE_FRONTEND] origin: IS_DEV ? "*" : [process.env.URL_OAUTH_FRONTEND_SUCCESS_REDIRECT, 'https://integracao-crm.hitmanager.app.br', process.env.URL_HITPHONE_FRONTEND]
}, },
maxHttpBufferSize: 1e8 maxHttpBufferSize: 1e8
}) })
@ -74,12 +75,28 @@ const initIO = (httpServer) => {
*/ */
io.on("connection", onConnectionHitphoneWebClient) io.on("connection", onConnectionHitphoneWebClient)
/**
* CRM template frontend test
*/
io.on("connection", socket => {
console.log('CLIENT CONNECTED')
socket.on("companySession", (companyId) => {
console.log(`A client joined a companySession channel: ${companyId}`)
socket.join(`company_${companyId}`)
})
socket.on("disconnect", (data) => {
console.log(`Client disconnected socket: ${data}`)
})
})
return io return io
} }
const getIO = () => { const getIO = () => {
if (!io) { if (!io) {
throw new AppError("Socket IO not initialized") console.log("Socket IO not initialized")
} }
return io return io
} }

View File

@ -14,6 +14,8 @@ async function ticketCRM(companyId, crmPhone, crmAgent, crmFirstName = 'unnamed'
const crmFiles = await loadCRM(companyId) const crmFiles = await loadCRM(companyId)
// console.log('xxxxxxxx crmFiles: ', JSON.stringify(crmFiles, null, 6))
for (const crmConfig of crmFiles) { for (const crmConfig of crmFiles) {
const { crmRest: rest, authentication } = crmConfig.crm const { crmRest: rest, authentication } = crmConfig.crm

View File

@ -1,13 +1,13 @@
{ {
"files": { "files": {
"main.css": "/static/css/main.ae60ab08.css", "main.css": "/static/css/main.ae60ab08.css",
"main.js": "/static/js/main.f5640aba.js", "main.js": "/static/js/main.0f480c22.js",
"index.html": "/index.html", "index.html": "/index.html",
"main.ae60ab08.css.map": "/static/css/main.ae60ab08.css.map", "main.ae60ab08.css.map": "/static/css/main.ae60ab08.css.map",
"main.f5640aba.js.map": "/static/js/main.f5640aba.js.map" "main.0f480c22.js.map": "/static/js/main.0f480c22.js.map"
}, },
"entrypoints": [ "entrypoints": [
"static/css/main.ae60ab08.css", "static/css/main.ae60ab08.css",
"static/js/main.f5640aba.js" "static/js/main.0f480c22.js"
] ]
} }

View File

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.f5640aba.js"></script><link href="/static/css/main.ae60ab08.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html> <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.0f480c22.js"></script><link href="/static/css/main.ae60ab08.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -75,8 +75,6 @@ const UploadFile = () => {
console.log('process.env.REACT_APP_COMPANY_ID: ', process.env.REACT_APP_COMPANY_ID) console.log('process.env.REACT_APP_COMPANY_ID: ', process.env.REACT_APP_COMPANY_ID)
const socket = socketIOClient(process.env.REACT_APP_URL_API)
const currentURL = window.location.href const currentURL = window.location.href
const urlObject = new URL(currentURL) const urlObject = new URL(currentURL)
const clientId = urlObject.searchParams.get('clientId') const clientId = urlObject.searchParams.get('clientId')
@ -92,7 +90,7 @@ const UploadFile = () => {
}) })
} catch (error) { } catch (error) {
setStatus('error') setStatus('error')
console.error('-----> Error:', error) console.log('-----> Error:', error)
console.log('TEST: ', error.response.data.msg) console.log('TEST: ', error.response.data.msg)
setErrorResponse(error.response.data.msg) setErrorResponse(error.response.data.msg)
} }
@ -102,6 +100,8 @@ const UploadFile = () => {
} }
const socket = socketIOClient(process.env.REACT_APP_URL_API)
socket.emit('companySession', process.env.REACT_APP_COMPANY_ID) socket.emit('companySession', process.env.REACT_APP_COMPANY_ID)
socket.on('crm_upload', (data) => { socket.on('crm_upload', (data) => {