Skip to content

Commit 9b806d5

Browse files
committed
fix(quickbooks): close final review gaps
1 parent aeb6fb8 commit 9b806d5

29 files changed

Lines changed: 714 additions & 125 deletions

File tree

‎apps/docs/openapi-v2-resources.json‎

Lines changed: 123 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7972,60 +7972,145 @@
79727972
"CreateCredentialConnectionBody": {
79737973
"anyOf": [
79747974
{
7975-
"type": "object",
7976-
"properties": {
7977-
"workspaceId": {
7978-
"type": "string",
7979-
"minLength": 1,
7980-
"maxLength": 128,
7981-
"description": "Workspace that will own the credential."
7982-
},
7983-
"providerId": {
7984-
"type": "string",
7985-
"minLength": 1,
7986-
"maxLength": 255,
7987-
"description": "Exact OAuth provider ID returned by credential-provider discovery."
7988-
},
7989-
"displayName": {
7990-
"type": "string",
7991-
"minLength": 1,
7992-
"maxLength": 255,
7993-
"description": "Name shown for the new credential in Sim."
7994-
},
7995-
"oauthClientConfig": {
7996-
"description": "Write-only OAuth app configuration when required by the provider.",
7975+
"anyOf": [
7976+
{
79977977
"type": "object",
79987978
"properties": {
7999-
"clientId": {
7979+
"workspaceId": {
80007980
"type": "string",
80017981
"minLength": 1,
8002-
"maxLength": 255,
8003-
"description": "Client ID for the caller-managed Intuit OAuth application."
7982+
"maxLength": 128,
7983+
"description": "Workspace that will own the credential."
80047984
},
8005-
"clientSecret": {
7985+
"displayName": {
80067986
"type": "string",
80077987
"minLength": 1,
8008-
"maxLength": 512,
8009-
"description": "Write-only client secret for the caller-managed Intuit OAuth application."
7988+
"maxLength": 255,
7989+
"description": "Name shown for the new credential in Sim."
80107990
},
8011-
"environment": {
7991+
"providerId": {
80127992
"type": "string",
8013-
"enum": ["sandbox", "production"],
8014-
"description": "Intuit company environment used for authorization and API requests."
7993+
"const": "quickbooks",
7994+
"description": "QuickBooks OAuth provider ID returned by credential-provider discovery."
80157995
},
8016-
"webhookVerifierToken": {
7996+
"oauthClientConfig": {
7997+
"type": "object",
7998+
"properties": {
7999+
"clientId": {
8000+
"type": "string",
8001+
"minLength": 1,
8002+
"maxLength": 255,
8003+
"description": "Client ID for the caller-managed Intuit OAuth application."
8004+
},
8005+
"clientSecret": {
8006+
"type": "string",
8007+
"minLength": 1,
8008+
"maxLength": 512,
8009+
"description": "Write-only client secret for the caller-managed Intuit OAuth application."
8010+
},
8011+
"environment": {
8012+
"type": "string",
8013+
"enum": ["sandbox", "production"],
8014+
"description": "Intuit company environment used for authorization and API requests."
8015+
},
8016+
"webhookVerifierToken": {
8017+
"type": "string",
8018+
"minLength": 1,
8019+
"maxLength": 512,
8020+
"description": "Write-only verifier token for webhook signatures from the caller-managed app."
8021+
}
8022+
},
8023+
"required": ["clientId", "clientSecret", "environment", "webhookVerifierToken"],
8024+
"additionalProperties": false,
8025+
"description": "Write-only caller-managed Intuit OAuth app configuration."
8026+
}
8027+
},
8028+
"required": ["workspaceId", "displayName", "providerId", "oauthClientConfig"],
8029+
"additionalProperties": false
8030+
},
8031+
{
8032+
"type": "object",
8033+
"properties": {
8034+
"workspaceId": {
80178035
"type": "string",
80188036
"minLength": 1,
8019-
"maxLength": 512,
8020-
"description": "Write-only verifier token for webhook signatures from the caller-managed app."
8037+
"maxLength": 128,
8038+
"description": "Workspace that will own the credential."
8039+
},
8040+
"displayName": {
8041+
"type": "string",
8042+
"minLength": 1,
8043+
"maxLength": 255,
8044+
"description": "Name shown for the new credential in Sim."
8045+
},
8046+
"providerId": {
8047+
"type": "string",
8048+
"enum": [
8049+
"google-email",
8050+
"google-drive",
8051+
"google-docs",
8052+
"google-sheets",
8053+
"google-forms",
8054+
"google-calendar",
8055+
"google-contacts",
8056+
"google-ads",
8057+
"google-bigquery",
8058+
"google-tasks",
8059+
"google-vault",
8060+
"google-groups",
8061+
"google-chat",
8062+
"google-meet",
8063+
"vertex-ai",
8064+
"microsoft-ad",
8065+
"microsoft-dataverse",
8066+
"microsoft-excel",
8067+
"microsoft-planner",
8068+
"microsoft-teams",
8069+
"microsoft-word",
8070+
"outlook",
8071+
"onedrive",
8072+
"sharepoint",
8073+
"x",
8074+
"tiktok",
8075+
"confluence",
8076+
"jira",
8077+
"airtable",
8078+
"bitbucket",
8079+
"notion",
8080+
"clickup",
8081+
"linear",
8082+
"manageengine-sdp",
8083+
"monday",
8084+
"box",
8085+
"dropbox",
8086+
"shopify",
8087+
"slack",
8088+
"reddit",
8089+
"wealthbox",
8090+
"webflow",
8091+
"trello",
8092+
"asana",
8093+
"attio",
8094+
"calcom",
8095+
"docusign",
8096+
"pipedrive",
8097+
"hubspot",
8098+
"linkedin",
8099+
"instagram",
8100+
"salesforce",
8101+
"salesforce-sandbox",
8102+
"zoho-desk",
8103+
"zoom",
8104+
"wordpress",
8105+
"spotify"
8106+
],
8107+
"description": "Exact OAuth provider ID returned by credential-provider discovery."
80218108
}
80228109
},
8023-
"required": ["clientId", "clientSecret", "environment", "webhookVerifierToken"],
8110+
"required": ["workspaceId", "displayName", "providerId"],
80248111
"additionalProperties": false
80258112
}
8026-
},
8027-
"required": ["workspaceId", "providerId", "displayName"],
8028-
"additionalProperties": false
8113+
]
80298114
},
80308115
{
80318116
"type": "object",

‎apps/sim/.env.example‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ CRON_SECRET=your_cron_secret # Use `openssl rand -hex 32` to generate. Authentic
153153
# TIKTOK_CLIENT_ID=
154154
# TIKTOK_CLIENT_SECRET=
155155

156-
# Azure Blob Storage takes precedence over S3 if both are configured
156+
# Azure Blob Storage
157157
# AZURE_ACCOUNT_NAME= # Azure storage account name
158158
# AZURE_ACCOUNT_KEY= # Azure storage account key
159159
# AZURE_CONNECTION_STRING= # Alternative to account name/key

‎apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/short-input/short-input.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ export const ShortInput = memo(function ShortInput({
339339
}) => {
340340
const actualValue = wandHook.isStreaming
341341
? localContent
342-
: useWebhookUrl && webhookManagement.webhookUrl
342+
: (useWebhookUrl || config.providerWebhookUrl) && webhookManagement.webhookUrl
343343
? webhookManagement.webhookUrl
344344
: ctrlValue
345345
const actualValueString = actualValue ?? ''

‎apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@ function SubBlockComponent({
485485
triggerId: undefined,
486486
isPreview,
487487
useWebhookUrl: config.useWebhookUrl,
488+
providerWebhookUrl: config.providerWebhookUrl,
488489
})
489490

490491
const handleMouseDown = (e: MouseEvent<HTMLDivElement>): void => {

‎apps/sim/hooks/use-oauth-return.test.ts‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ vi.mock('@/hooks/queries/utils/fetch-workspace-credentials', () => ({
2121
}))
2222

2323
import type { OAuthReturnContext } from '@/lib/credentials/client-state'
24-
import { resolveOAuthCallbackError, resolveOAuthMessage } from '@/hooks/use-oauth-return'
24+
import {
25+
buildKnowledgeBaseOAuthReturnUrl,
26+
resolveOAuthCallbackError,
27+
resolveOAuthMessage,
28+
} from '@/hooks/use-oauth-return'
2529

2630
const context: OAuthReturnContext = {
2731
origin: 'integrations',
@@ -120,3 +124,11 @@ describe('resolveOAuthCallbackError', () => {
120124
).toBeNull()
121125
})
122126
})
127+
128+
describe('buildKnowledgeBaseOAuthReturnUrl', () => {
129+
it('preserves the connector picker on both successful and failed OAuth returns', () => {
130+
expect(buildKnowledgeBaseOAuthReturnUrl('workspace-1', 'kb-1', 'google_drive')).toBe(
131+
'/workspace/workspace-1/knowledge/kb-1?addConnector=google_drive'
132+
)
133+
})
134+
})

‎apps/sim/hooks/use-oauth-return.ts‎

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,9 @@ export function useOAuthReturnRouter() {
251251
if (ctx.origin === 'workflow') {
252252
router.replace(`/workspace/${workspaceId}/w/${ctx.workflowId}`)
253253
} else if (ctx.origin === 'kb-connectors') {
254-
router.replace(`/workspace/${workspaceId}/knowledge/${ctx.knowledgeBaseId}`)
254+
router.replace(
255+
buildKnowledgeBaseOAuthReturnUrl(workspaceId, ctx.knowledgeBaseId, ctx.connectorType)
256+
)
255257
}
256258
return
257259
}
@@ -278,16 +280,25 @@ export function useOAuthReturnRouter() {
278280
try {
279281
sessionStorage.removeItem(SETTINGS_RETURN_URL_KEY)
280282
} catch {}
281-
const kbUrl = `/workspace/${workspaceId}/knowledge/${ctx.knowledgeBaseId}`
282-
const connectorParam = ctx.connectorType
283-
? `?${ADD_CONNECTOR_SEARCH_PARAM}=${encodeURIComponent(ctx.connectorType)}`
284-
: ''
285-
router.replace(`${kbUrl}${connectorParam}`)
283+
router.replace(
284+
buildKnowledgeBaseOAuthReturnUrl(workspaceId, ctx.knowledgeBaseId, ctx.connectorType)
285+
)
286286
return
287287
}
288288
}, [queryClient, router, workspaceId])
289289
}
290290

291+
export function buildKnowledgeBaseOAuthReturnUrl(
292+
workspaceId: string,
293+
knowledgeBaseId: string,
294+
connectorType?: string
295+
): string {
296+
const kbUrl = `/workspace/${workspaceId}/knowledge/${knowledgeBaseId}`
297+
return connectorType
298+
? `${kbUrl}?${ADD_CONNECTOR_SEARCH_PARAM}=${encodeURIComponent(connectorType)}`
299+
: kbUrl
300+
}
301+
291302
/**
292303
* Post-OAuth handler for workflow pages.
293304
* Consumes the return context and shows a workflow-scoped notification.

‎apps/sim/lib/api/contracts/v2/credentials.test.ts‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
* @vitest-environment node
33
*/
44
import { describe, expect, it } from 'vitest'
5-
import { v2CreateCredentialConnectionBodySchema } from '@/lib/api/contracts/v2/credentials'
5+
import {
6+
V2_OAUTH_CONNECTION_PROVIDER_IDS,
7+
v2CreateCredentialConnectionBodySchema,
8+
} from '@/lib/api/contracts/v2/credentials'
9+
import { getAllOAuthServices } from '@/lib/oauth/utils'
610

711
const WORKSPACE_ID = '11111111-2222-4333-8444-555555555555'
812
const QUICKBOOKS_CONFIG = {
@@ -13,6 +17,14 @@ const QUICKBOOKS_CONFIG = {
1317
}
1418

1519
describe('v2CreateCredentialConnectionBodySchema', () => {
20+
it('keeps the documented provider enum in sync with provider discovery', () => {
21+
const discoveredProviderIds = getAllOAuthServices()
22+
.filter((service) => service.authType === 'oauth')
23+
.flatMap((service) => [service.providerId, ...(service.additionalProviderIds ?? [])])
24+
25+
expect(V2_OAUTH_CONNECTION_PROVIDER_IDS).toEqual(discoveredProviderIds)
26+
})
27+
1628
it('requires app credentials for a new QuickBooks connection', () => {
1729
expect(
1830
v2CreateCredentialConnectionBodySchema.safeParse({

0 commit comments

Comments
 (0)