Skip to content

Commit

Permalink
Merge pull request #1757 from rudderlabs/fix/zendesk-global-var
Browse files Browse the repository at this point in the history
fix(zendesk): get rid of global variable
  • Loading branch information
sanpj2292 authored Jan 6, 2023
2 parents 21b624f + d06f69e commit 532ca19
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 47 deletions.
5 changes: 5 additions & 0 deletions src/v0/destinations/zendesk/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@ const ZENDESK_MARKET_PLACE_NAME = "RudderStack";
const ZENDESK_MARKET_PLACE_ORG_ID = "3339";
const ZENDESK_MARKET_PLACE_APP_ID = "263241";

const getBaseEndpoint = domain => {
return `https://${domain}.zendesk.com/api/v2/`;
};

module.exports = {
getBaseEndpoint,
ConfigCategory,
mappingConfig,
defaultFields,
Expand Down
124 changes: 77 additions & 47 deletions src/v0/destinations/zendesk/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const {
defaultFields,
ZENDESK_MARKET_PLACE_NAME,
ZENDESK_MARKET_PLACE_ORG_ID,
ZENDESK_MARKET_PLACE_APP_ID
ZENDESK_MARKET_PLACE_APP_ID,
getBaseEndpoint
} = require("./config");
const {
removeUndefinedValues,
Expand All @@ -27,8 +28,6 @@ const {
const logger = require("../../../logger");
const { httpGET } = require("../../../adapters/network");

let endPoint;

function responseBuilder(message, headers, payload, endpoint) {
const response = defaultRequestConfig();

Expand Down Expand Up @@ -60,7 +59,8 @@ const responseBuilderToUpdatePrimaryAccount = (
userIdentityId,
userId,
headers,
email
email,
baseEndpoint
) => {
const response = defaultRequestConfig();
const updatedHeaders = {
Expand All @@ -69,7 +69,7 @@ const responseBuilderToUpdatePrimaryAccount = (
"X-Zendesk-Marketplace-Organization-Id": ZENDESK_MARKET_PLACE_ORG_ID,
"X-Zendesk-Marketplace-App-Id": ZENDESK_MARKET_PLACE_APP_ID
};
response.endpoint = `${endPoint}users/${userId}/identities/${userIdentityId}`;
response.endpoint = `${baseEndpoint}users/${userId}/identities/${userIdentityId}`;
response.method = defaultPutRequestConfig.requestMethod;
response.headers = updatedHeaders;
response.body.JSON = {
Expand All @@ -89,9 +89,14 @@ const responseBuilderToUpdatePrimaryAccount = (
* @param {*} headers -> Authorizations for API's call
* @returns it return payloadbuilder for updating email
*/
const payloadBuilderforUpdatingEmail = async (userId, headers, userEmail) => {
const payloadBuilderforUpdatingEmail = async (
userId,
headers,
userEmail,
baseEndpoint
) => {
// url for list all identities of user
const url = `${endPoint}users/${userId}/identities`;
const url = `${baseEndpoint}users/${userId}/identities`;
const config = { headers };
try {
const res = await httpGET(url, config);
Expand All @@ -108,7 +113,8 @@ const payloadBuilderforUpdatingEmail = async (userId, headers, userEmail) => {
identitiesDetails.id,
userId,
headers,
userEmail
userEmail,
baseEndpoint
);
}
}
Expand Down Expand Up @@ -152,11 +158,12 @@ async function checkAndCreateUserFields(
traits,
categoryEndpoint,
fieldJson,
headers
headers,
baseEndpoint
) {
let newFields = [];

const url = endPoint + categoryEndpoint;
const url = baseEndpoint + categoryEndpoint;
const config = { headers };

try {
Expand Down Expand Up @@ -225,13 +232,13 @@ function getIdentifyPayload(message, category, destinationConfig, type) {
* @param {*} headers headers for authorizations
* @returns
*/
const getUserIdByExternalId = async (message, headers) => {
const getUserIdByExternalId = async (message, headers, baseEndpoint) => {
const externalId = getFieldValueFromMessage(message, "userIdOnly");
if (!externalId) {
logger.debug("externalId is required for getting zenuserId");
return undefined;
}
const url = `${endPoint}users/search.json?query=${externalId}`;
const url = `${baseEndpoint}users/search.json?query=${externalId}`;
const config = { headers };

try {
Expand All @@ -251,7 +258,7 @@ const getUserIdByExternalId = async (message, headers) => {
}
};

async function getUserId(message, headers, type) {
async function getUserId(message, headers, baseEndpoint, type) {
const traits =
type === "group"
? get(message, "context.traits")
Expand All @@ -261,8 +268,7 @@ async function getUserId(message, headers, type) {
logger.debug("Email ID is required for getting zenuserId");
return undefined;
}
const url = `${endPoint}users/search.json?query=${userEmail}`;
// let url = endPoint + `users/search.json?external_id=${externalId}`;
const url = `${baseEndpoint}users/search.json?query=${userEmail}`;
const config = { headers };

try {
Expand All @@ -283,8 +289,8 @@ async function getUserId(message, headers, type) {
}
}

async function isUserAlreadyAssociated(userId, orgId, headers) {
const url = `${endPoint}/users/${userId}/organization_memberships.json`;
async function isUserAlreadyAssociated(userId, orgId, headers, baseEndpoint) {
const url = `${baseEndpoint}/users/${userId}/organization_memberships.json`;
const config = { headers };
const response = await axios.get(url, config);
if (
Expand All @@ -297,7 +303,13 @@ async function isUserAlreadyAssociated(userId, orgId, headers) {
return false;
}

async function createUser(message, headers, destinationConfig, type) {
async function createUser(
message,
headers,
destinationConfig,
baseEndpoint,
type
) {
const traits =
type === "group"
? get(message, "context.traits")
Expand All @@ -310,7 +322,7 @@ async function createUser(message, headers, destinationConfig, type) {
userObject.verified = true;
}
const category = ConfigCategory.IDENTIFY;
const url = endPoint + category.createOrUpdateUserEndpoint;
const url = baseEndpoint + category.createOrUpdateUserEndpoint;
const config = { headers };
const payload = { user: userObject };

Expand Down Expand Up @@ -339,17 +351,19 @@ async function getUserMembershipPayload(
message,
headers,
orgId,
destinationConfig
destinationConfig,
baseEndpoint
) {
// let zendeskUserID = await getUserId(message.userId, headers);
let zendeskUserID = await getUserId(message, headers, "group");
let zendeskUserID = await getUserId(message, headers, baseEndpoint, "group");
const traits = get(message, "context.traits");
if (!zendeskUserID) {
if (traits && traits.name && traits.email) {
const { zendeskUserId } = await createUser(
message,
headers,
destinationConfig,
baseEndpoint,
"group"
);
zendeskUserID = zendeskUserId;
Expand All @@ -371,13 +385,15 @@ async function createOrganization(
message,
category,
headers,
destinationConfig
destinationConfig,
baseEndpoint
) {
await checkAndCreateUserFields(
message.traits,
category.organizationFieldsEndpoint,
category.organizationFieldsJson,
headers
headers,
baseEndpoint
);
const mappingJson = mappingConfig[category.name];
const payload = constructPayload(message, mappingJson);
Expand Down Expand Up @@ -409,7 +425,7 @@ async function createOrganization(
return payload;
}

const url = endPoint + category.createEndpoint;
const url = baseEndpoint + category.createEndpoint;
const config = { headers };

try {
Expand Down Expand Up @@ -437,7 +453,12 @@ function validateUserId(message) {
}
}

async function processIdentify(message, destinationConfig, headers) {
async function processIdentify(
message,
destinationConfig,
headers,
baseEndpoint
) {
validateUserId(message);
const category = ConfigCategory.IDENTIFY;
const traits = getFieldValueFromMessage(message, "traits");
Expand All @@ -447,7 +468,8 @@ async function processIdentify(message, destinationConfig, headers) {
getFieldValueFromMessage(message, "traits"),
category.userFieldsEndpoint,
category.userFieldsJson,
headers
headers,
baseEndpoint
);

const payload = getIdentifyPayload(
Expand All @@ -456,17 +478,22 @@ async function processIdentify(message, destinationConfig, headers) {
destinationConfig,
"identify"
);
const url = endPoint + category.createOrUpdateUserEndpoint;
const url = baseEndpoint + category.createOrUpdateUserEndpoint;
const returnList = [];

if (destinationConfig.searchByExternalId) {
const userIdByExternalId = await getUserIdByExternalId(message, headers);
const userIdByExternalId = await getUserIdByExternalId(
message,
headers,
baseEndpoint
);
const userEmail = traits?.email;
if (userIdByExternalId && userEmail) {
const payloadForUpdatingEmail = await payloadBuilderforUpdatingEmail(
userIdByExternalId,
headers,
userEmail
userEmail,
baseEndpoint
);
if (!isEmptyObject(payloadForUpdatingEmail))
returnList.push(payloadForUpdatingEmail);
Expand All @@ -480,9 +507,9 @@ async function processIdentify(message, destinationConfig, headers) {
traits.company.id
) {
const orgId = traits.company.id;
const userId = await getUserId(message, headers);
const userId = await getUserId(message, headers, baseEndpoint);
if (userId) {
const membershipUrl = `${endPoint}users/${userId}/organization_memberships.json`;
const membershipUrl = `${baseEndpoint}users/${userId}/organization_memberships.json`;
try {
const config = { headers };
const response = await axios.get(membershipUrl, config);
Expand All @@ -497,7 +524,7 @@ async function processIdentify(message, destinationConfig, headers) {
const membershipId = response.data.organization_memberships[0].id;
const deleteResponse = defaultRequestConfig();

deleteResponse.endpoint = `${endPoint}users/${userId}/organization_memberships/${membershipId}.json`;
deleteResponse.endpoint = `${baseEndpoint}users/${userId}/organization_memberships/${membershipId}.json`;
deleteResponse.method = defaultDeleteRequestConfig.requestMethod;
deleteResponse.headers = {
...headers,
Expand All @@ -519,7 +546,7 @@ async function processIdentify(message, destinationConfig, headers) {
return returnList;
}

async function processTrack(message, destinationConfig, headers) {
async function processTrack(message, destinationConfig, headers, baseEndpoint) {
validateUserId(message);
const traits = getFieldValueFromMessage(message, "traits");
let userEmail;
Expand All @@ -531,14 +558,15 @@ async function processTrack(message, destinationConfig, headers) {
}
let zendeskUserID;

let url = `${endPoint}users/search.json?query=${userEmail}`;
let url = `${baseEndpoint}users/search.json?query=${userEmail}`;
const config = { headers };
const userResponse = await axios.get(url, config);
if (!get(userResponse, "data.users.0.id") || userResponse.data.count === 0) {
const { zendeskUserId, email } = await createUser(
message,
headers,
destinationConfig
destinationConfig,
baseEndpoint
);
if (!zendeskUserId) {
throw new CustomError("user not found", 400);
Expand All @@ -563,13 +591,13 @@ async function processTrack(message, destinationConfig, headers) {
profileObject.identifiers = [{ type: "email", value: userEmail }];

const eventPayload = { event: eventObject, profile: profileObject };
url = `${endPoint}users/${zendeskUserID}/events`;
url = `${baseEndpoint}users/${zendeskUserID}/events`;

const response = responseBuilder(message, headers, eventPayload, url);
return response;
}

async function processGroup(message, destinationConfig, headers) {
async function processGroup(message, destinationConfig, headers, baseEndpoint) {
const category = ConfigCategory.GROUP;
let payload;
let url;
Expand All @@ -581,14 +609,15 @@ async function processGroup(message, destinationConfig, headers) {
headers,
destinationConfig
);
url = endPoint + category.createEndpoint;
url = baseEndpoint + category.createEndpoint;
} else {
validateUserId(message);
const orgId = await createOrganization(
message,
category,
headers,
destinationConfig
destinationConfig,
baseEndpoint
);
if (!orgId) {
throw new CustomError(
Expand All @@ -602,12 +631,13 @@ async function processGroup(message, destinationConfig, headers) {
message,
headers,
orgId,
destinationConfig
destinationConfig,
baseEndpoint
);
url = endPoint + category.userMembershipEndpoint;
url = baseEndpoint + category.userMembershipEndpoint;

const userId = payload.organization_membership.user_id;
if (await isUserAlreadyAssociated(userId, orgId, headers)) {
if (await isUserAlreadyAssociated(userId, orgId, headers, baseEndpoint)) {
throw new CustomError(
"user is already associated with organization",
400
Expand All @@ -621,7 +651,7 @@ async function processGroup(message, destinationConfig, headers) {
// category = ConfigCategory.IDENTIFY;
// payload = getIdentifyPayload(message, category, destinationConfig, "group");
// payload.user.organization_id = orgId;
// url = endPoint + category.createOrUpdateUserEndpoint;
// url = baseEndpoint + category.createOrUpdateUserEndpoint;
// return responseBuilder(message, headers, payload, url);

return responseBuilder(message, headers, payload, url);
Expand All @@ -632,6 +662,7 @@ async function processSingleMessage(event) {
const destinationConfig = event.destination.Config;
const messageType = message.type.toLowerCase();
const unencodedBase64Str = `${destinationConfig.email}/token:${destinationConfig.apiToken}`;
const baseEndpoint = getBaseEndpoint(destinationConfig.domain);
const headers = {
Authorization: `Basic ${Buffer.from(unencodedBase64Str).toString(
"base64"
Expand All @@ -641,18 +672,17 @@ async function processSingleMessage(event) {

switch (messageType) {
case EventType.IDENTIFY:
return processIdentify(message, destinationConfig, headers);
return processIdentify(message, destinationConfig, headers, baseEndpoint);
case EventType.GROUP:
return processGroup(message, destinationConfig, headers);
return processGroup(message, destinationConfig, headers, baseEndpoint);
case EventType.TRACK:
return processTrack(message, destinationConfig, headers);
return processTrack(message, destinationConfig, headers, baseEndpoint);
default:
throw new CustomError("Message type not supported", 400);
}
}

async function process(event) {
endPoint = `https://${event.destination.Config.domain}.zendesk.com/api/v2/`;
const resp = await processSingleMessage(event);
return resp;
}
Expand Down

0 comments on commit 532ca19

Please sign in to comment.