@cgignite/ignite-salesforce
Version:
A set of Node-RED nodes to interact with Salesforce and Force.com.
130 lines (113 loc) • 3.98 kB
JavaScript
const nforce8 = require('nforce8');
// Uncomment when nforce8 2.0.8 is available
//const API_VERSION = nforce8.API_VERSION;
const API_VERSION = 'v45.0';
const oAuthMap = {}; // Capture oauth info for reuse
const getOAuth = (orgConfig) => {
const curUser = orgConfig.userName;
return oAuthMap[curUser];
};
const setOAuth = (oauth, orgConfig) => {
const curUser = orgConfig.userName;
oAuthMap[curUser] = oauth;
};
/**
*
* @param {configOptions} configOptionsRaw from setup node
* @param {msg} msg incoming message that might have overwrites
* @returns {org} SFDC Org to be able to authenticate
*
*/
const prepareConnection = (configOptionsRaw, msg) => {
// Update configOptions from msg if there's incoming credentials
const configOptions = mergeConfigOptionsWithMsg(configOptionsRaw, msg);
// Now build the options we use to create the SFDC connection
const orgOptions = {
apiVersion: configOptions.apiversion || API_VERSION,
clientId: configOptions.consumerKey,
clientSecret: configOptions.consumerSecret,
environment: configOptions.environment,
mode: 'multi',
redirectUri: configOptions.callbackUrl
};
// Overwrite the endpoints eventually - access instance directly
if (configOptions.usePotUrl) {
orgOptions.authEndpoint = configOptions.poturl;
orgOptions.testAuthEndpoint = configOptions.poturl;
}
// Callout to SFDC, getting org object back
const sfdcOrg = nforce8.createConnection(orgOptions);
const result = {
org: sfdcOrg,
config: configOptions
};
return result;
};
/**
* wrapper around the org.authenticate function
* @param {org} org SFDC Org ready to authenticat
* @param {configOptions} configOptions from config and msg
*/
const authenticate = (org, configOptions, oAuthCandidate) => {
// Don't reauthenticate if we are still good
if (oAuthCandidate && isValidOAuth(oAuthCandidate)) {
return Promise.resolve(oAuthCandidate);
}
const authOptions = {
username: configOptions.userName,
password: configOptions.passWord
};
// Returns a promise
return org.authenticate(authOptions);
};
// eslint-disable-next-line no-unused-vars
const isValidOAuth = (candidate) => {
// TODO: How to check OAuth
return false;
};
/**
* Define config options from msg object
* @param {configOptions} configOptions the current configuration settings
* @param {msg} msg the actual incoming message that might contain identity information
* @returns {configOptions} config options merged with what was found in the msg object
*/
const mergeConfigOptionsWithMsg = (configOptions, msg) => {
const connectionOptionResult = { ...configOptions };
// Credentials from the msg object will always overwrite the stored
// properties if the configuration allows that. We copy ALL properties
// from the sf object
if (connectionOptionResult.allowMsgCredentials && msg && msg.sf) {
const sfProperties = msg.sf;
for (let prop in sfProperties) {
// We need to check for username/password separate
// since they are camelCase starting v0.7
if (prop.toLowerCase() === 'username') {
connectionOptionResult.userName = sfProperties[prop];
} else if (prop.toLowerCase() === 'password') {
connectionOptionResult.passWord = sfProperties[prop];
} else if (sfProperties.hasOwnProperty(prop)) {
connectionOptionResult[prop] = sfProperties[prop];
}
}
}
return connectionOptionResult;
};
/**
* Checks for Salesforce headers in msg object to send back to SF
* @param {*} payload - the data to be posted
* @param {*} msg - the incoming message
*/
const extractHeaders = (payload, msg) => {
if (payload && msg && msg.sf && msg.sf.headers) {
payload.headers = msg.sf.headers;
}
};
module.exports = {
createConnection: prepareConnection,
authenticate: authenticate,
force: nforce8,
getOAuth: getOAuth,
setOAuth: setOAuth,
extractHeaders: extractHeaders,
API_VERSION: API_VERSION
};