diff --git a/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue b/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue index 7eac3f344..fd539fed7 100644 --- a/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue +++ b/packages/editor-ui/src/components/CredentialEdit/CredentialEdit.vue @@ -751,6 +751,12 @@ async function testCredential(credentialDetails: ICredentialsDecrypted) { scrollToTop(); } +function usesExternalSecrets(data: Record): boolean { + return Object.entries(data).some( + ([, value]) => typeof value !== 'object' && /=.*\{\{[^}]*\$secrets\.[^}]+}}.*/.test(`${value}`), + ); +} + async function saveCredential(): Promise { if (!requiredPropertiesFilled.value) { showValidationWarning.value = true; @@ -844,18 +850,13 @@ async function saveCredential(): Promise { testedSuccessfully.value = false; } - const usesExternalSecrets = Object.entries(credentialDetails.data ?? {}).some( - ([, value]) => - typeof value !== 'object' && /=.*\{\{[^}]*\$secrets\.[^}]+}}.*/.test(`${value}`), - ); - const trackProperties: ITelemetryTrackProperties = { credential_type: credentialDetails.type, workflow_id: workflowsStore.workflowId, credential_id: credential.id, is_complete: !!requiredPropertiesFilled.value, is_new: isNewCredential, - uses_external_secrets: usesExternalSecrets, + uses_external_secrets: usesExternalSecrets(credentialDetails.data ?? {}), }; if (isOAuthType.value) { @@ -872,7 +873,15 @@ async function saveCredential(): Promise { trackProperties.authError = authError.value; } - telemetry.track('User saved credentials', trackProperties); + /** + * For non-OAuth credentials we track saving on clicking the `Save` button, but for + * OAuth credentials we track saving at the end of the flow (BroastcastChannel event) + * so that the `is_valid` property is correct. + */ + if (!isOAuthType.value) { + telemetry.track('User saved credentials', trackProperties); + } + await externalHooks.run('credentialEdit.saveCredential', trackProperties); } @@ -1050,7 +1059,25 @@ async function oAuthCredentialAuthorize() { const oauthChannel = new BroadcastChannel('oauth-callback'); const receiveMessage = (event: MessageEvent) => { - if (event.data === 'success') { + const successfullyConnected = event.data === 'success'; + + const trackProperties: ITelemetryTrackProperties = { + credential_type: credentialTypeName.value, + workflow_id: workflowsStore.workflowId, + credential_id: credentialId.value, + is_complete: !!requiredPropertiesFilled.value, + is_new: props.mode === 'new' && !credentialId.value, + is_valid: successfullyConnected, + uses_external_secrets: usesExternalSecrets(credentialData.value), + }; + + if (ndvStore.activeNode) { + trackProperties.node_type = ndvStore.activeNode.type; + } + + telemetry.track('User saved credentials', trackProperties); + + if (successfullyConnected) { oauthChannel.removeEventListener('message', receiveMessage); // Set some kind of data that status changes.