From fef7333ca7016ff980060faf36ef2479ea7bc52b Mon Sep 17 00:00:00 2001 From: Stephen Wright Date: Mon, 13 Jul 2026 12:02:38 +0100 Subject: [PATCH] feat(Microsoft SharePoint Node): Add v2 sign-in with person and app credentials (no-changelog) (#34057) --- .../SharePoint/MicrosoftSharePoint.node.ts | 8 +-- .../SharePoint/test/v2/authentication.test.ts | 48 +++++++++++++++++ .../v2/MicrosoftSharePointV2.node.ts | 53 +++++++++++++++++-- 3 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 packages/nodes-base/nodes/Microsoft/SharePoint/test/v2/authentication.test.ts diff --git a/packages/nodes-base/nodes/Microsoft/SharePoint/MicrosoftSharePoint.node.ts b/packages/nodes-base/nodes/Microsoft/SharePoint/MicrosoftSharePoint.node.ts index 268f9dbb2cf..6e9dab12a5d 100644 --- a/packages/nodes-base/nodes/Microsoft/SharePoint/MicrosoftSharePoint.node.ts +++ b/packages/nodes-base/nodes/Microsoft/SharePoint/MicrosoftSharePoint.node.ts @@ -21,10 +21,10 @@ export class MicrosoftSharePoint extends VersionedNodeType { const nodeVersions: IVersionedNodeType['nodeVersions'] = { 1: new MicrosoftSharePointV1(baseDescription), - // v2 is under construction (ENT-170). The editor and AI builder surface - // the highest registered version regardless of defaultVersion, so v2 - // must stay unregistered until launch (ENT-190). Uncomment locally to - // test v2 work. + // v2 is under construction. The editor and AI builder surface the + // highest registered version regardless of defaultVersion, so v2 must + // stay unregistered until the launch ticket flips the default. + // Uncomment locally to test v2 work. // 2: new MicrosoftSharePointV2(baseDescription), }; diff --git a/packages/nodes-base/nodes/Microsoft/SharePoint/test/v2/authentication.test.ts b/packages/nodes-base/nodes/Microsoft/SharePoint/test/v2/authentication.test.ts new file mode 100644 index 00000000000..94bb7abfc36 --- /dev/null +++ b/packages/nodes-base/nodes/Microsoft/SharePoint/test/v2/authentication.test.ts @@ -0,0 +1,48 @@ +import { versionDescription } from '../../v2/MicrosoftSharePointV2.node'; + +describe('Microsoft SharePoint v2 authentication selector', () => { + const properties = versionDescription.properties; + const credentials = versionDescription.credentials ?? []; + const authProperty = properties.find((property) => property.name === 'authentication'); + const optionValues = (authProperty?.options ?? []).map((option) => + 'value' in option ? option.value : undefined, + ); + + it('should expose an authentication options selector as the first property', () => { + expect(authProperty).toBeDefined(); + expect(authProperty?.type).toBe('options'); + expect(authProperty?.noDataExpression).toBe(true); + expect(properties[0]?.name).toBe('authentication'); + }); + + it('should offer exactly the generic Microsoft and Service Principal credentials', () => { + expect(optionValues).toEqual(['microsoftOAuth2Api', 'microsoftEntraServicePrincipalApi']); + }); + + it('should default to the generic Microsoft credential', () => { + expect(authProperty?.default).toBe('microsoftOAuth2Api'); + }); + + it('should gate each credential behind its matching authentication value', () => { + expect(credentials).toHaveLength(2); + for (const credential of credentials) { + expect(credential.required).toBe(true); + expect(credential.displayOptions?.show?.authentication).toEqual([credential.name]); + } + }); + + it('should not offer the legacy SharePoint credential', () => { + const credentialNames = credentials.map((credential) => credential.name); + + expect(optionValues).not.toContain('microsoftSharePointOAuth2Api'); + expect(credentialNames).not.toContain('microsoftSharePointOAuth2Api'); + }); + + it('should keep the default aligned with a gated credential', () => { + const credentialGatedByDefault = credentials.find((credential) => + credential.displayOptions?.show?.authentication?.includes(authProperty?.default as string), + ); + + expect(credentialGatedByDefault?.name).toBe('microsoftOAuth2Api'); + }); +}); diff --git a/packages/nodes-base/nodes/Microsoft/SharePoint/v2/MicrosoftSharePointV2.node.ts b/packages/nodes-base/nodes/Microsoft/SharePoint/v2/MicrosoftSharePointV2.node.ts index d0158bd5e86..eaca16a8aab 100644 --- a/packages/nodes-base/nodes/Microsoft/SharePoint/v2/MicrosoftSharePointV2.node.ts +++ b/packages/nodes-base/nodes/Microsoft/SharePoint/v2/MicrosoftSharePointV2.node.ts @@ -1,9 +1,9 @@ import type { INodeType, INodeTypeBaseDescription, INodeTypeDescription } from 'n8n-workflow'; import { NodeConnectionTypes } from 'n8n-workflow'; -// Blank shell for the Graph-based v2 rebuild; credentials, actions, and -// pickers arrive in follow-up tickets. Not registered yet — uncomment the -// registration in MicrosoftSharePoint.node.ts to test locally. +// Graph-based v2 rebuild in progress; actions, transport, and pickers arrive +// in follow-up tickets. Not registered yet — uncomment the registration in +// MicrosoftSharePoint.node.ts to test locally. export const versionDescription: INodeTypeDescription = { displayName: 'Microsoft SharePoint', name: 'microsoftSharePoint', @@ -19,7 +19,52 @@ export const versionDescription: INodeTypeDescription = { }, inputs: [NodeConnectionTypes.Main], outputs: [NodeConnectionTypes.Main], - properties: [], + // The v1 credential (microsoftSharePointOAuth2Api) is deliberately not + // offered: its tokens target the legacy {subdomain}.sharepoint.com/_api + // host and fail against Graph. + credentials: [ + { + name: 'microsoftOAuth2Api', + required: true, + displayOptions: { + show: { + authentication: ['microsoftOAuth2Api'], + }, + }, + }, + { + name: 'microsoftEntraServicePrincipalApi', + required: true, + displayOptions: { + show: { + authentication: ['microsoftEntraServicePrincipalApi'], + }, + }, + }, + ], + properties: [ + { + displayName: 'Authentication', + name: 'authentication', + type: 'options', + noDataExpression: true, + options: [ + { + name: 'Microsoft OAuth2 (Graph)', + value: 'microsoftOAuth2Api', + description: + 'Generic Microsoft Graph credential. Enable the scopes this node needs (e.g. Sites.ReadWrite.All) on the credential.', + }, + { + name: 'Microsoft Entra Service Principal (App-Only)', + value: 'microsoftEntraServicePrincipalApi', + description: + 'App-only access via a Microsoft Entra app registration with admin-consented SharePoint application permissions', + }, + ], + default: 'microsoftOAuth2Api', + }, + ], }; export class MicrosoftSharePointV2 implements INodeType {