From c9f8c94be28244b99809ae49802c2728d4b7d99a Mon Sep 17 00:00:00 2001 From: Ikraam Ghoor Date: Mon, 24 Mar 2025 19:05:44 +0000 Subject: [PATCH] Avail cred ui types and hide sensitive destination fields in UI --- libs/core-functions/src/lib/meta-types.ts | 48 +++++++++++ libs/core-functions/src/meta.ts | 79 ++++++++++++++----- webapps/console/lib/schema/destinations.tsx | 56 +++---------- .../pages/[workspaceId]/destinations.tsx | 2 +- webapps/console/pages/api/destinations.ts | 3 +- 5 files changed, 121 insertions(+), 67 deletions(-) create mode 100644 libs/core-functions/src/lib/meta-types.ts diff --git a/libs/core-functions/src/lib/meta-types.ts b/libs/core-functions/src/lib/meta-types.ts new file mode 100644 index 000000000..cfe71363d --- /dev/null +++ b/libs/core-functions/src/lib/meta-types.ts @@ -0,0 +1,48 @@ +/** + * UI for property + */ +export type PropertyUI = { + /** + * Optional human-friendly name of the field + */ + displayName?: string; + /** + * If string field should be treated as textarea (multiline input) + */ + textarea?: boolean; + /** + * If string field should be treated as password + */ + password?: boolean; + /** + * If the field should not be displayed. That field must have a default value + */ + hidden?: boolean | ((obj: any) => boolean); + /** + * If the field should be a constant + */ + constant?: any | ((obj: any) => any); + /** + * correction to field value. e.g: set default value for property that was missing before + */ + correction?: any | ((obj: any) => any); + + /** + * Documentation for the field + */ + documentation?: string; + /** + * Name of custom editor component. See getEditorComponent() function from `[workspaceId]/destinations.txt` + */ + editor?: + | "ArrayTextarea" + | "StringArrayEditor" + | "CodeEditor" + | "SnippedEditor" + | "MultiSelectWithCustomOptions" + | string; + /** + * Properties of an editor component (not implemented yet, reserved for the future) + */ + editorProps?: any; +}; diff --git a/libs/core-functions/src/meta.ts b/libs/core-functions/src/meta.ts index bafc19a87..a1579b671 100644 --- a/libs/core-functions/src/meta.ts +++ b/libs/core-functions/src/meta.ts @@ -1,8 +1,9 @@ import { z } from "zod"; +import { PropertyUI } from "./lib/meta-types"; const eventsParamDescription = ` -List of events to send, delimited by comma. Following page, screen, or any arbitrary event (name of track event). -Special values: empty string - send only track events, * - send all events useful if you want to filter events with Functions +List of events to send, delimited by comma. Following page, screen, or any arbitrary event (name of track event). +Special values: empty string - send only track events, * - send all events useful if you want to filter events with Functions `; export const FacebookConversionApiCredentials = z.object({ pixelId: z.string().describe("Facebook Pixel ID"), @@ -21,7 +22,7 @@ export const FacebookConversionApiCredentials = z.object({ ), }); -export const FacebookConversionApiCredentialsUi = { +export const FacebookConversionApiCredentialsUi: Partial> = { accessToken: { password: true, }, @@ -68,6 +69,14 @@ export const IntercomDestinationCredentials = z.object({ ), }); +export const IntercomDestinationCredentialsUi: Partial< + Record, PropertyUI> +> = { + accessToken: { + password: true, + }, +}; + export type IntercomDestinationCredentials = z.infer; export const MixpanelCredentials = z.object({ @@ -124,9 +133,7 @@ export const MixpanelCredentials = z.object({ }); export type MixpanelCredentials = z.infer; -export const MixpanelCredentialsUi: Partial< - Record -> = { +export const MixpanelCredentialsUi: Partial> = { serviceAccountPassword: { password: true, }, @@ -144,6 +151,13 @@ export const JuneCredentials = z.object({ .default(false) .describe("If enabled, anonymous users will be tracked in June"), }); + +export const JuneCredentialsUi: Partial> = { + apiKey: { + password: true, + }, +}; + export type JuneCredentials = z.infer; export const BrazeCredentials = z.object({ @@ -186,6 +200,13 @@ export const BrazeCredentials = z.object({ .default(false) .describe("Send page and screen events as Braze Custom Events"), }); + +export const BrazeCredentialsUi: Partial> = { + apiKey: { + password: true, + }, +}; + export type BrazeCredentials = z.infer; export const SegmentCredentials = z.object({ @@ -196,6 +217,13 @@ export const SegmentCredentials = z.object({ `To get an API Key you need to add the HTTP API source to your Segment workspace. Write Key can be found on the HTTP API source Overview page.` ), }); + +export const SegmentCredentialsUi: Partial> = { + writeKey: { + password: true, + }, +}; + export type SegmentCredentials = z.infer; export const POSTHOG_DEFAULT_HOST = "https://app.posthog.com"; @@ -235,9 +263,10 @@ export const PosthogDestinationConfig = z.object({ ), }); -export const PosthogDestinationConfigUi: Partial< - Record -> = { +export const PosthogDestinationConfigUi: Partial, PropertyUI>> = { + key: { + password: true, + }, sendAnonymousEvents: { // assumes value of this freshly added property from the value of the `enableAnonymousUserProfiles` property correction: obj => @@ -275,6 +304,13 @@ export const AmplitudeDestinationConfig = z.object({ dataResidency: z.enum(["US", "EU"]).optional().default("US"), sessionWindow: z.number().optional().default(30).describe("Session window in minutes"), }); +export const AmplitudeDestinationConfigUi: Partial< + Record, PropertyUI> +> = { + key: { + password: true, + }, +}; export type AmplitudeDestinationConfig = z.infer; @@ -298,17 +334,7 @@ export const MongodbDestinationConfig = z.object({ options: z.object({}).catchall(z.string().default("")).optional().describe("Additional MongoDB connection options."), }); -export const MongodbDestinationConfigUi: Partial< - Record< - keyof MongodbDestinationConfig, - { - documentation?: string; - editor?: string; - hidden?: boolean; - password?: boolean; - } - > -> = { +export const MongodbDestinationConfigUi: Partial> = { hosts: { editor: "StringArrayEditor", }, @@ -344,6 +370,13 @@ export const Ga4Credentials = z.object({ .default("https://www.google-analytics.com/mp/collect"), events: z.string().optional().default("").describe(eventsParamDescription), }); + +export const Ga4CredentialsUi: Partial, PropertyUI>> = { + apiSecret: { + password: true, + }, +}; + export type Ga4Credentials = z.infer; export const HubspotCredentials = z.object({ @@ -367,4 +400,10 @@ export const HubspotCredentials = z.object({ ), }); +export const HubspotCredentialsConfigUi: Partial, PropertyUI>> = { + accessToken: { + password: true, + }, +}; + export type HubspotCredentials = z.infer; diff --git a/webapps/console/lib/schema/destinations.tsx b/webapps/console/lib/schema/destinations.tsx index 328bbb7ce..69216ad20 100644 --- a/webapps/console/lib/schema/destinations.tsx +++ b/webapps/console/lib/schema/destinations.tsx @@ -1,6 +1,8 @@ import { SomeZodObject, z } from "zod"; import React, { ReactNode } from "react"; +import type { PropertyUI } from "@jitsu/core-functions/src/lib/meta-types"; + import amplitudeIcon from "./icons/amplitude"; import bigqueryIcon from "./icons/bigquery"; import ClickhouseIcon from "./icons/clickhouse"; @@ -28,7 +30,6 @@ import intercomIcon from "./icons/intercom"; import webhookIcon from "./icons/webhook"; import { branding } from "../branding"; import * as meta from "@jitsu/core-functions/src/meta"; -import { HubspotCredentials } from "@jitsu/core-functions/src/meta"; const s3Regions = [ "us-west-1", @@ -56,49 +57,6 @@ const s3Regions = [ "us-gov-west-1", ] as const; -/** - * UI for property - */ -export type PropertyUI = { - /** - * Optional human-friendly name of the field - */ - displayName?: string; - /** - * If string field should be treated as textarea (multiline input) - */ - textarea?: boolean; - /** - * If string field should be treated as password - */ - password?: boolean; - /** - * If the field should not be displayed. That field must have a default value - */ - hidden?: boolean | ((obj: any) => boolean); - /** - * If the field should be a constant - */ - constant?: any | ((obj: any) => any); - /** - * correction to field value. e.g: set default value for property that was missing before - */ - correction?: any | ((obj: any) => any); - - /** - * Documentation for the field - */ - documentation?: string; - /** - * Name of custom editor component. See getEditorComponent() function from `[workspaceId]/destinations.txt` - */ - editor?: string; - /** - * Properties of an editor component (not implemented yet, reserved for the future) - */ - editorProps?: any; -}; - export type SchemaUI = Record; export const FunctionsConnectionOptions = z.object({ @@ -790,6 +748,7 @@ export const coreDestinations: DestinationType[] = [ title: "Intercom", tags: "Product Analytics", credentials: meta.IntercomDestinationCredentials, + credentialsUi: meta.IntercomDestinationCredentialsUi, connectionOptions: CloudDestinationsConnectionOptions, description: ( <> @@ -815,6 +774,7 @@ export const coreDestinations: DestinationType[] = [ tags: "Product Analytics", connectionOptions: CloudDestinationsConnectionOptions, credentials: meta.JuneCredentials, + credentialsUi: meta.JuneCredentialsUi, description: "June.so is a product analytics platform that provides insights into user behavior.", }, { @@ -824,6 +784,7 @@ export const coreDestinations: DestinationType[] = [ tags: "Product Analytics", connectionOptions: CloudDestinationsConnectionOptions, credentials: meta.BrazeCredentials, + credentialsUi: meta.BrazeCredentialsUi, description: "Braze is a customer engagement platform used by businesses for multichannel marketing.", }, { @@ -844,6 +805,7 @@ export const coreDestinations: DestinationType[] = [ tags: "Product Analytics", connectionOptions: CloudDestinationsConnectionOptions, credentials: meta.Ga4Credentials, + credentialsUi: meta.Ga4CredentialsUi, description: "Google Analytics 4 is a service offered by Google that reports website traffic data and marketing trends.", }, @@ -854,6 +816,7 @@ export const coreDestinations: DestinationType[] = [ tags: "Product Analytics", connectionOptions: CloudDestinationsConnectionOptions, credentials: meta.PosthogDestinationConfig, + credentialsUi: meta.PosthogDestinationConfigUi, description: "Posthog is an open-source product analytics tool. Jitsu supports both self-hosted Posthog and Posthog Cloud.", }, @@ -864,6 +827,7 @@ export const coreDestinations: DestinationType[] = [ title: "Amplitude", tags: "Product Analytics", credentials: meta.AmplitudeDestinationConfig, + credentialsUi: meta.AmplitudeDestinationConfigUi, description: "Amplitude is a product analytics platform", }, { @@ -872,7 +836,8 @@ export const coreDestinations: DestinationType[] = [ connectionOptions: CloudDestinationsConnectionOptions, title: "Hubspot", tags: "CRM", - credentials: HubspotCredentials, + credentials: meta.HubspotCredentials, + credentialsUi: meta.HubspotCredentialsConfigUi, description: "Hubspot is a CRM. Jitsu sends data to Hubspot API and updates contacts and company records", documentation: ( <> @@ -921,6 +886,7 @@ export const coreDestinations: DestinationType[] = [ title: "Segment", tags: "Special", credentials: meta.SegmentCredentials, + credentialsUi: meta.SegmentCredentialsUi, description: ( <> Forward events for to Segment-compatible endpoint. It's useful if you want to use {branding.productName} for diff --git a/webapps/console/pages/[workspaceId]/destinations.tsx b/webapps/console/pages/[workspaceId]/destinations.tsx index 424c94aa3..483949974 100644 --- a/webapps/console/pages/[workspaceId]/destinations.tsx +++ b/webapps/console/pages/[workspaceId]/destinations.tsx @@ -8,8 +8,8 @@ import { coreDestinationsMap, DestinationType, getCoreDestinationType, - PropertyUI, } from "../../lib/schema/destinations"; +import type { PropertyUI } from "@jitsu/core-functions/src/lib/meta-types"; import { DestinationCatalog, getDestinationIcon } from "../../components/DestinationsCatalog/DestinationsCatalog"; import { useAppConfig, useWorkspace } from "../../lib/context"; import { useRouter } from "next/router"; diff --git a/webapps/console/pages/api/destinations.ts b/webapps/console/pages/api/destinations.ts index 7de182ed7..6ab69535f 100644 --- a/webapps/console/pages/api/destinations.ts +++ b/webapps/console/pages/api/destinations.ts @@ -1,5 +1,6 @@ import { createRoute } from "../../lib/api"; -import { coreDestinations, PropertyUI } from "../../lib/schema/destinations"; +import { coreDestinations } from "../../lib/schema/destinations"; +import { PropertyUI } from "@jitsu/core-functions/src/lib/meta-types"; import omit from "lodash/omit"; import { renderToStaticMarkup } from "react-dom/server"; import { createDisplayName } from "../../lib/zod";