diff --git a/apps/docs/content/docs/en/tools/onepassword.mdx b/apps/docs/content/docs/en/tools/onepassword.mdx index 8b90f8104..7d35c55b4 100644 --- a/apps/docs/content/docs/en/tools/onepassword.mdx +++ b/apps/docs/content/docs/en/tools/onepassword.mdx @@ -254,7 +254,7 @@ Resolve a secret reference (op://vault/item/field) to its value. Service Account | Parameter | Type | Description | | --------- | ---- | ----------- | -| `secret` | string | The resolved secret value | +| `value` | string | The resolved secret value | | `reference` | string | The original secret reference URI | diff --git a/apps/sim/app/api/tools/onepassword/create-item/route.ts b/apps/sim/app/api/tools/onepassword/create-item/route.ts index 25dd401e3..bd5ebfab8 100644 --- a/apps/sim/app/api/tools/onepassword/create-item/route.ts +++ b/apps/sim/app/api/tools/onepassword/create-item/route.ts @@ -54,7 +54,7 @@ export async function POST(request: NextRequest) { const parsedFields = params.fields ? (JSON.parse(params.fields) as Array>).map((f) => ({ - id: f.id || '', + id: f.id || randomUUID().slice(0, 8), title: f.label || f.title || '', fieldType: toSdkFieldType(f.type || 'STRING'), value: f.value || '', diff --git a/apps/sim/app/api/tools/onepassword/replace-item/route.ts b/apps/sim/app/api/tools/onepassword/replace-item/route.ts index 1dc735450..d45dac20b 100644 --- a/apps/sim/app/api/tools/onepassword/replace-item/route.ts +++ b/apps/sim/app/api/tools/onepassword/replace-item/route.ts @@ -46,37 +46,41 @@ export async function POST(request: NextRequest) { if (creds.mode === 'service_account') { const client = await createOnePasswordClient(creds.serviceAccountToken!) + const existing = await client.items.get(params.vaultId, params.itemId) + const sdkItem = { + ...existing, id: params.itemId, - title: itemData.title || '', - category: toSdkCategory(itemData.category || 'LOGIN'), + title: itemData.title || existing.title, + category: itemData.category ? toSdkCategory(itemData.category) : existing.category, vaultId: params.vaultId, - fields: (itemData.fields ?? []).map((f: Record) => ({ - id: f.id || '', - title: f.label || f.title || '', - fieldType: toSdkFieldType(f.type || 'STRING'), - value: f.value || '', - sectionId: f.section?.id ?? f.sectionId, - })), - sections: (itemData.sections ?? []).map((s: Record) => ({ - id: s.id || '', - title: s.label || s.title || '', - })), - notes: itemData.notes || '', - tags: itemData.tags ?? [], - websites: (itemData.urls ?? itemData.websites ?? []).map((u: Record) => ({ - url: u.href || u.url || '', - label: u.label || '', - autofillBehavior: 'AnywhereOnWebsite' as const, - })), - version: itemData.version ?? 0, - files: [], - createdAt: new Date(), - updatedAt: new Date(), + fields: itemData.fields + ? (itemData.fields as Array>).map((f) => ({ + id: f.id || randomUUID().slice(0, 8), + title: f.label || f.title || '', + fieldType: toSdkFieldType(f.type || 'STRING'), + value: f.value || '', + sectionId: f.section?.id ?? f.sectionId, + })) + : existing.fields, + sections: itemData.sections + ? (itemData.sections as Array>).map((s) => ({ + id: s.id || '', + title: s.label || s.title || '', + })) + : existing.sections, + notes: itemData.notes ?? existing.notes, + tags: itemData.tags ?? existing.tags, + websites: + itemData.urls || itemData.websites + ? (itemData.urls ?? itemData.websites ?? []).map((u: Record) => ({ + url: u.href || u.url || '', + label: u.label || '', + autofillBehavior: 'AnywhereOnWebsite' as const, + })) + : existing.websites, } - // Cast to any because toSdkCategory/toSdkFieldType return string literals - // that match SDK enum values but TypeScript can't verify this at compile time const result = await client.items.put(sdkItem as any) return NextResponse.json(normalizeSdkItem(result)) } diff --git a/apps/sim/app/api/tools/onepassword/resolve-secret/route.ts b/apps/sim/app/api/tools/onepassword/resolve-secret/route.ts index 8359416fc..408ac48c5 100644 --- a/apps/sim/app/api/tools/onepassword/resolve-secret/route.ts +++ b/apps/sim/app/api/tools/onepassword/resolve-secret/route.ts @@ -42,7 +42,7 @@ export async function POST(request: NextRequest) { const secret = await client.secrets.resolve(params.secretReference) return NextResponse.json({ - secret, + value: secret, reference: params.secretReference, }) } catch (error) { diff --git a/apps/sim/blocks/blocks/onepassword.ts b/apps/sim/blocks/blocks/onepassword.ts index 97687a378..e8000573e 100644 --- a/apps/sim/blocks/blocks/onepassword.ts +++ b/apps/sim/blocks/blocks/onepassword.ts @@ -71,7 +71,7 @@ export const OnePasswordBlock: BlockConfig = { id: 'secretReference', title: 'Secret Reference', type: 'short-input', - placeholder: 'op://vault-name/item-name/field-name', + placeholder: 'op://vault-name-or-id/item-name-or-id/field-name', required: { field: 'operation', value: 'resolve_secret' }, condition: { field: 'operation', value: 'resolve_secret' }, }, @@ -80,6 +80,7 @@ export const OnePasswordBlock: BlockConfig = { title: 'Vault ID', type: 'short-input', placeholder: 'Enter vault UUID', + password: true, required: { field: 'operation', value: [ @@ -154,7 +155,7 @@ export const OnePasswordBlock: BlockConfig = { }, { id: 'fields', - title: 'Fields (JSON)', + title: 'Fields', type: 'code', placeholder: '[\n {\n "label": "username",\n "value": "admin",\n "type": "STRING",\n "purpose": "USERNAME"\n }\n]', diff --git a/apps/sim/lib/workflows/sanitization/references.test.ts b/apps/sim/lib/workflows/sanitization/references.test.ts index 4aece4c77..83b861384 100644 --- a/apps/sim/lib/workflows/sanitization/references.test.ts +++ b/apps/sim/lib/workflows/sanitization/references.test.ts @@ -43,4 +43,13 @@ describe('isLikelyReferenceSegment', () => { it('should return false when leading content is not comparator characters', () => { expect(isLikelyReferenceSegment('')).toBe(false) }) + + it('should return true for references starting with a digit', () => { + expect(isLikelyReferenceSegment('<1password1>')).toBe(true) + expect(isLikelyReferenceSegment('<1password1.secret>')).toBe(true) + }) + + it('should return false for purely numeric references', () => { + expect(isLikelyReferenceSegment('<123>')).toBe(false) + }) }) diff --git a/apps/sim/lib/workflows/sanitization/references.ts b/apps/sim/lib/workflows/sanitization/references.ts index 2290f150f..8f30762df 100644 --- a/apps/sim/lib/workflows/sanitization/references.ts +++ b/apps/sim/lib/workflows/sanitization/references.ts @@ -70,7 +70,7 @@ export function isLikelyReferenceSegment(segment: string): boolean { if (INVALID_REFERENCE_CHARS.test(beforeDot) || INVALID_REFERENCE_CHARS.test(afterDot)) { return false } - } else if (INVALID_REFERENCE_CHARS.test(inner) || inner.match(/^\d/) || inner.match(/\s\d/)) { + } else if (INVALID_REFERENCE_CHARS.test(inner) || inner.match(/^\d+$/) || inner.match(/\s\d/)) { return false } diff --git a/apps/sim/tools/onepassword/resolve_secret.ts b/apps/sim/tools/onepassword/resolve_secret.ts index a2a3636fd..7b2820e07 100644 --- a/apps/sim/tools/onepassword/resolve_secret.ts +++ b/apps/sim/tools/onepassword/resolve_secret.ts @@ -49,19 +49,19 @@ export const resolveSecretTool: ToolConfig< transformResponse: async (response) => { const data = await response.json() if (data.error) { - return { success: false, output: { secret: '', reference: '' }, error: data.error } + return { success: false, output: { value: '', reference: '' }, error: data.error } } return { success: true, output: { - secret: data.secret ?? '', + value: data.value ?? '', reference: data.reference ?? '', }, } }, outputs: { - secret: { type: 'string', description: 'The resolved secret value' }, + value: { type: 'string', description: 'The resolved secret value' }, reference: { type: 'string', description: 'The original secret reference URI' }, }, } diff --git a/apps/sim/tools/onepassword/types.ts b/apps/sim/tools/onepassword/types.ts index 937acd35f..688a43953 100644 --- a/apps/sim/tools/onepassword/types.ts +++ b/apps/sim/tools/onepassword/types.ts @@ -153,7 +153,7 @@ export interface OnePasswordDeleteItemResponse extends ToolResponse { export interface OnePasswordResolveSecretResponse extends ToolResponse { output: { - secret: string + value: string reference: string } }