diff --git a/connectors/src/connectors/zendesk/lib/cli.ts b/connectors/src/connectors/zendesk/lib/cli.ts new file mode 100644 index 000000000000..43a66efc4715 --- /dev/null +++ b/connectors/src/connectors/zendesk/lib/cli.ts @@ -0,0 +1,39 @@ +import type { ZendeskCommandType } from "@dust-tt/types"; +import type { ZendeskCheckIsAdminResponseType } from "@dust-tt/types/src"; + +import { getZendeskSubdomainAndAccessToken } from "@connectors/connectors/zendesk/lib/zendesk_access_token"; +import { fetchZendeskCurrentUser } from "@connectors/connectors/zendesk/lib/zendesk_api"; +import { default as topLogger } from "@connectors/logger/logger"; +import { ConnectorResource } from "@connectors/resources/connector_resource"; + +export const zendesk = async ({ + command, + args, +}: ZendeskCommandType): Promise => { + const logger = topLogger.child({ majorCommand: "zendesk", command, args }); + + const connectorId = args.connectorId ? args.connectorId.toString() : null; + const connector = connectorId + ? await ConnectorResource.fetchById(connectorId) + : null; + if (connector && connector.type !== "zendesk") { + throw new Error(`Connector ${args.connectorId} is not of type zendesk`); + } + + switch (command) { + case "check-is-admin": { + if (!connector) { + throw new Error(`Connector ${connectorId} not found`); + } + const user = await fetchZendeskCurrentUser( + await getZendeskSubdomainAndAccessToken(connector.connectionId) + ); + logger.info({ user }, "User returned by /users/me"); + return { + userActive: user.active, + userRole: user.role, + userIsAdmin: user.role === "admin" && user.active, + }; + } + } +}; diff --git a/connectors/src/connectors/zendesk/lib/zendesk_api.ts b/connectors/src/connectors/zendesk/lib/zendesk_api.ts index 26378630b24f..421e9f2aa7b9 100644 --- a/connectors/src/connectors/zendesk/lib/zendesk_api.ts +++ b/connectors/src/connectors/zendesk/lib/zendesk_api.ts @@ -6,6 +6,7 @@ import type { ZendeskFetchedArticle, ZendeskFetchedCategory, ZendeskFetchedTicket, + ZendeskFetchedUser, } from "@connectors/@types/node-zendesk"; import { ExternalOAuthTokenError } from "@connectors/lib/error"; import logger from "@connectors/logger/logger"; @@ -349,3 +350,21 @@ export async function fetchZendeskTicketsInBrand({ } : { tickets: [], meta: { has_more: false, after_cursor: "" } }; } + +/** + * Fetches the current user through a call to `/users/me`. + */ +export async function fetchZendeskCurrentUser({ + subdomain, + accessToken, +}: { + subdomain: string; + accessToken: string; +}): Promise { + const response = await fetch( + `https://${subdomain}.zendesk.com/api/v2/users/me`, + { headers: { Authorization: `Bearer ${accessToken}` } } + ); + const data = await response.json(); + return data.user; +} diff --git a/connectors/src/lib/cli.ts b/connectors/src/lib/cli.ts index 8791d4df59bc..e871b0661ad0 100644 --- a/connectors/src/lib/cli.ts +++ b/connectors/src/lib/cli.ts @@ -23,6 +23,7 @@ import { microsoft } from "@connectors/connectors/microsoft/lib/cli"; import { notion } from "@connectors/connectors/notion/lib/cli"; import { slack } from "@connectors/connectors/slack/lib/cli"; import { launchCrawlWebsiteSchedulerWorkflow } from "@connectors/connectors/webcrawler/temporal/client"; +import { zendesk } from "@connectors/connectors/zendesk/lib/cli"; import { getTemporalClient } from "@connectors/lib/temporal"; import { default as topLogger } from "@connectors/logger/logger"; import { ConnectorModel } from "@connectors/resources/storage/models/connector_model"; @@ -51,6 +52,8 @@ export async function runCommand(adminCommand: AdminCommandType) { return intercom(adminCommand); case "microsoft": return microsoft(adminCommand); + case "zendesk": + return zendesk(adminCommand); default: assertNever(adminCommand); } diff --git a/types/src/connectors/admin/cli.ts b/types/src/connectors/admin/cli.ts index 342c1bafd389..228c113aacca 100644 --- a/types/src/connectors/admin/cli.ts +++ b/types/src/connectors/admin/cli.ts @@ -214,6 +214,30 @@ export type IntercomForceResyncArticlesResponseType = t.TypeOf< * */ +/** + * + */ +export const ZendeskCommandSchema = t.type({ + majorCommand: t.literal("zendesk"), + command: t.literal("check-is-admin"), + args: t.type({ + connectorId: t.union([t.number, t.undefined]), + }), +}); + +export type ZendeskCommandType = t.TypeOf; +export const ZendeskCheckIsAdminResponseSchema = t.type({ + userRole: t.string, + userActive: t.boolean, + userIsAdmin: t.boolean, +}); +export type ZendeskCheckIsAdminResponseType = t.TypeOf< + typeof ZendeskCheckIsAdminResponseSchema +>; +/** + * + */ + export const MicrosoftCommandSchema = t.type({ majorCommand: t.literal("microsoft"), command: t.union([ @@ -243,6 +267,7 @@ export const AdminCommandSchema = t.union([ SlackCommandSchema, TemporalCommandSchema, WebcrawlerCommandSchema, + ZendeskCommandSchema, ]); export type AdminCommandType = t.TypeOf;