Skip to content

Commit

Permalink
fix(zendesk): remove endpoint global variable (#1746)
Browse files Browse the repository at this point in the history
* fix(zendesk): remove endpoint global variable

* feat: code optimization

* feat: addressing review comments

* refactor: error message

* feat: addressing review comments

* fix: using optional chaining instead of a lot of conditionals

* test: add router testcases

* fix: remove two declarations of getBaseEndpoint function

* fix: add name with errors

Co-authored-by: Sai Sankeerth <sanpj2292@github.com>
Co-authored-by: ItsSudip <sudip.paul1997@gmail.com>
Co-authored-by: Sudip Paul <67197965+ItsSudip@users.noreply.github.com>
  • Loading branch information
4 people committed Jan 10, 2023
1 parent 8d55c24 commit 836c37e
Show file tree
Hide file tree
Showing 7 changed files with 342 additions and 60 deletions.
11 changes: 6 additions & 5 deletions src/v0/destinations/zendesk/config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
const { getMappingConfig } = require("../../util");

const getBaseEndpoint = domain => {
return `https://${domain}.zendesk.com/api/v2/`;
};
const NAME = "zendesk";
const ConfigCategory = {
IDENTIFY: {
name: "ZDIdentifyConfig",
Expand Down Expand Up @@ -44,16 +48,13 @@ 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,
ZENDESK_MARKET_PLACE_NAME,
ZENDESK_MARKET_PLACE_ORG_ID,
ZENDESK_MARKET_PLACE_APP_ID
ZENDESK_MARKET_PLACE_APP_ID,
NAME
};
139 changes: 86 additions & 53 deletions src/v0/destinations/zendesk/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const {
ZENDESK_MARKET_PLACE_NAME,
ZENDESK_MARKET_PLACE_ORG_ID,
ZENDESK_MARKET_PLACE_APP_ID,
NAME,
getBaseEndpoint
} = require("./config");
const {
Expand All @@ -27,8 +28,11 @@ const logger = require("../../../logger");
const { httpGET } = require("../../../adapters/network");
const {
NetworkInstrumentationError,
InstrumentationError
InstrumentationError,
NetworkError
} = require("../../util/errorTypes");
const { getDynamicErrorType } = require("../../../adapters/utils/networkUtils");
const tags = require("../../util/tags");

function responseBuilder(message, headers, payload, endpoint) {
const response = defaultRequestConfig();
Expand Down Expand Up @@ -121,9 +125,12 @@ const payloadBuilderforUpdatingEmail = async (
}
}
}
logger.debug("Failed in fetching Identity details");
logger.debug(`${NAME}:: Failed in fetching Identity details`);
} catch (error) {
logger.debug("Error :", error.response ? error.response.data : error);
logger.debug(
`${NAME}:: Error :`,
error.response ? error.response.data : error
);
}
return {};
};
Expand All @@ -146,11 +153,11 @@ async function createUserFields(url, config, newFields, fieldJson) {
try {
const response = await axios.post(url, fieldData, config);
if (response.status !== 201) {
logger.debug("Failed to create User Field : ", field);
logger.debug(`${NAME}:: Failed to create User Field : `, field);
}
} catch (error) {
if (error.response && error.response.status !== 422) {
logger.debug("Cannot create User field ", field, error);
logger.debug(`${NAME}:: Cannot create User field `, field, error);
}
}
});
Expand Down Expand Up @@ -187,7 +194,10 @@ async function checkAndCreateUserFields(
}
}
} catch (error) {
logger.debug("Error :", error.response ? error.response.data : error);
logger.debug(
`${NAME}:: Error :`,
error.response ? error.response.data : error
);
}
}

Expand Down Expand Up @@ -237,7 +247,7 @@ function getIdentifyPayload(message, category, destinationConfig, type) {
const getUserIdByExternalId = async (message, headers, baseEndpoint) => {
const externalId = getFieldValueFromMessage(message, "userIdOnly");
if (!externalId) {
logger.debug("externalId is required for getting zenuserId");
logger.debug(`${NAME}:: externalId is required for getting zenuserId`);
return undefined;
}
const url = `${baseEndpoint}users/search.json?query=${externalId}`;
Expand All @@ -250,10 +260,10 @@ const getUserIdByExternalId = async (message, headers, baseEndpoint) => {
const zendeskUserId = get(resp, "response.data.users.0.id");
return zendeskUserId;
}
logger.debug("Failed in fetching User details");
logger.debug(`${NAME}:: Failed in fetching User details`);
} catch (error) {
logger.debug(
`Cannot get userId for externalId : ${externalId}`,
`${NAME}:: Cannot get userId for externalId : ${externalId}`,
error.response
);
return undefined;
Expand All @@ -267,7 +277,7 @@ async function getUserId(message, headers, baseEndpoint, type) {
: getFieldValueFromMessage(message, "traits");
const userEmail = traits?.email || traits?.primaryEmail;
if (!userEmail) {
logger.debug("Email ID is required for getting zenuserId");
logger.debug(`${NAME}:: Email ID is required for getting zenuserId`);
return undefined;
}
const url = `${baseEndpoint}users/search.json?query=${userEmail}`;
Expand All @@ -276,11 +286,11 @@ async function getUserId(message, headers, baseEndpoint, type) {
try {
const resp = await axios.get(url, config);
if (!resp || !resp.data || resp.data.count === 0) {
logger.debug("User not found");
logger.debug(`${NAME}:: User not found`);
return undefined;
}

const zendeskUserId = resp.data.users[0].id;
const zendeskUserId = resp?.data?.users?.[0]?.id;
return zendeskUserId;
} catch (error) {
// logger.debug(
Expand All @@ -294,13 +304,16 @@ async function getUserId(message, headers, baseEndpoint, type) {
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 (
response.data &&
response.data.organization_memberships.length > 0 &&
response.data.organization_memberships[0].organization_id === orgId
) {
return true;
try {
const response = await axios.get(url, config);
if (
response?.data?.organization_memberships?.[0]?.organization_id === orgId
) {
return true;
}
} catch (error) {
logger.debug(`${NAME}:: Error :`);
logger.debug(error?.response?.data || error);
}
return false;
}
Expand Down Expand Up @@ -332,12 +345,12 @@ async function createUser(
const resp = await axios.post(url, payload, config);

if (!resp.data || !resp.data.user || !resp.data.user.id) {
logger.debug(`Couldn't create User: ${name}`);
logger.debug(`${NAME}:: Couldn't create User: ${name}`);
throw new NetworkInstrumentationError("user not found");
}

const userID = resp.data.user.id;
const userEmail = resp.data.user.email;
const userID = resp?.data?.user?.id;
const userEmail = resp?.data?.user.email;
return { zendeskUserId: userID, email: userEmail };
} catch (error) {
logger.debug(error);
Expand Down Expand Up @@ -431,14 +444,18 @@ async function createOrganization(
const resp = await axios.post(url, payload, config);

if (!resp.data || !resp.data.organization) {
logger.debug(`Couldn't create Organization: ${message.traits.name}`);
logger.debug(
`${NAME}:: Couldn't create Organization: ${message.traits.name}`
);
return undefined;
}

const orgId = resp.data.organization.id;
const orgId = resp?.data?.organization?.id;
return orgId;
} catch (error) {
logger.debug(`Couldn't create Organization: ${message.traits.name}`);
logger.debug(
`${NAME}:: Couldn't create Organization: ${message.traits.name}`
);
return undefined;
}
}
Expand Down Expand Up @@ -512,15 +529,11 @@ async function processIdentify(
try {
const config = { headers };
const response = await axios.get(membershipUrl, config);
if (
response.data &&
response.data.organization_memberships &&
response.data.organization_memberships.length > 0
) {
if (response?.data?.organization_memberships?.length > 0) {
if (
orgId === response.data.organization_memberships[0].organization_id
orgId === response.data.organization_memberships[0]?.organization_id
) {
const membershipId = response.data.organization_memberships[0].id;
const membershipId = response.data.organization_memberships[0]?.id;
const deleteResponse = defaultRequestConfig();

deleteResponse.endpoint = `${baseEndpoint}users/${userId}/organization_memberships/${membershipId}.json`;
Expand All @@ -536,7 +549,7 @@ async function processIdentify(
}
}
} catch (error) {
logger.debug(error);
logger.debug(`${NAME}:: ${error}`);
}
}
}
Expand All @@ -557,26 +570,40 @@ async function processTrack(message, destinationConfig, headers, baseEndpoint) {
}
let zendeskUserID;

let url = `${baseEndpoint}users/search.json?query=${userEmail}`;
const 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,
baseEndpoint
);
if (!zendeskUserId) {
throw new NetworkInstrumentationError("User not found");
}
if (!email) {
throw new NetworkInstrumentationError("User email not found", 400);
try {
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,
baseEndpoint
);
if (!zendeskUserId) {
throw new NetworkInstrumentationError("User not found");
}
if (!email) {
throw new NetworkInstrumentationError("User email not found", 400);
}
zendeskUserID = zendeskUserId;
userEmail = email;
}
zendeskUserID = zendeskUserId;
userEmail = email;
zendeskUserID = zendeskUserID || userResponse?.data?.users?.[0]?.id;
} catch (error) {
throw new NetworkError(
`Failed to fetch user with email: ${userEmail} due to ${error.message}`,
error.status,
{
[tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(error.status)
},
error?.response?.data || error?.response || error
);
}
zendeskUserID = zendeskUserID || userResponse.data.users[0].id;

const eventObject = {};
eventObject.description = message.event;
Expand All @@ -590,9 +617,14 @@ async function processTrack(message, destinationConfig, headers, baseEndpoint) {
profileObject.identifiers = [{ type: "email", value: userEmail }];

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

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

Expand All @@ -606,7 +638,8 @@ async function processGroup(message, destinationConfig, headers, baseEndpoint) {
message,
category,
headers,
destinationConfig
destinationConfig,
baseEndpoint
);
url = baseEndpoint + category.createEndpoint;
} else {
Expand Down
59 changes: 59 additions & 0 deletions test/__mocks__/data/zendesk/response.json
Original file line number Diff line number Diff line change
Expand Up @@ -286,5 +286,64 @@
"next_page": null,
"previous_page": null,
"count": 1
},
"https://rudderlabtest1.zendesk.com/api/v2/users/search.json?query=testemail1@email": {
"users": [],
"next_page": null,
"previous_page": null,
"count": 0
},
"https://rudderlabtest2.zendesk.com/api/v2/users/search.json?query=testemail2@email": {
"users": [],
"next_page": null,
"previous_page": null,
"count": 0
},
"https://rudderlabtest1.zendesk.com/api/v2/users/create_or_update.json": {
"user": {
"id": 900113780483,
"url": "https://rudderlabtest1.zendesk.com/api/v2/users/900113780483.json",
"name": "John Wick",
"email": "testemail1@email",
"created_at": "2020-03-17T10:21:15Z",
"updated_at": "2020-03-23T15:56:56Z",
"time_zone": "Eastern Time (US & Canada)",
"iana_time_zone": "America/New_York",
"phone": null,
"shared_phone_number": null,
"photo": null,
"locale_id": 1,
"locale": "en-US",
"organization_id": 900001329943,
"role": "end-user",
"verified": true,
"external_id": "exId-123",
"tags": [],
"alias": null,
"active": true,
"shared": false,
"shared_agent": false,
"last_login_at": null,
"two_factor_auth_enabled": false,
"signature": null,
"details": null,
"notes": null,
"role_type": null,
"custom_role_id": null,
"moderator": false,
"ticket_restriction": "requested",
"only_private_comments": false,
"restricted_agent": true,
"suspended": false,
"chat_only": false,
"default_group_id": null,
"report_csv": false,
"user_fields": {
"birthday": null
}
}
},
"https://rudderlabtest2.zendesk.com/api/v2/users/create_or_update.json": {
"user": {}
}
}
Loading

0 comments on commit 836c37e

Please sign in to comment.