diff --git a/packages/nodes-base/credentials/StrapiTokenApi.credentials.ts b/packages/nodes-base/credentials/StrapiTokenApi.credentials.ts new file mode 100644 index 0000000000000..07b689884be20 --- /dev/null +++ b/packages/nodes-base/credentials/StrapiTokenApi.credentials.ts @@ -0,0 +1,77 @@ +import type { + IAuthenticateGeneric, + ICredentialTestRequest, + ICredentialType, + INodeProperties, +} from 'n8n-workflow'; + +export class StrapiTokenApi implements ICredentialType { + name = 'strapiTokenApi'; + + displayName = 'Strapi API Token'; + + documentationUrl = 'strapi'; + + properties: INodeProperties[] = [ + { + displayName: 'API Token', + name: 'apiToken', + type: 'string', + typeOptions: { password: true }, + default: '', + }, + { + displayName: 'URL', + name: 'url', + type: 'string', + default: '', + placeholder: 'https://api.example.com', + }, + { + displayName: 'API Version', + name: 'apiVersion', + default: 'v3', + type: 'options', + description: 'The version of api to be used', + options: [ + { + name: 'Version 4', + value: 'v4', + description: 'API version supported by Strapi 4', + }, + { + name: 'Version 3', + value: 'v3', + description: 'API version supported by Strapi 3', + }, + ], + }, + ]; + + authenticate: IAuthenticateGeneric = { + type: 'generic', + properties: { + headers: { + Authorization: '=Bearer {{$credentials.apiToken}}', + }, + }, + }; + + test: ICredentialTestRequest = { + request: { + baseURL: '={{$credentials.url}}', + url: '={{$credentials.apiVersion === "v3" ? "/users/count" : "/api/users/count"}}', + ignoreHttpStatusErrors: true, + }, + rules: [ + { + type: 'responseSuccessBody', + properties: { + key: 'error.name', + value: 'UnauthorizedError', + message: 'Invalid API token', + }, + }, + ], + }; +} diff --git a/packages/nodes-base/nodes/Strapi/GenericFunctions.ts b/packages/nodes-base/nodes/Strapi/GenericFunctions.ts index d5b0aa1834faf..a2b1e0fb4ef7c 100644 --- a/packages/nodes-base/nodes/Strapi/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Strapi/GenericFunctions.ts @@ -1,6 +1,7 @@ import type { OptionsWithUri } from 'request'; import type { + ICredentialDataDecryptedObject, IDataObject, IExecuteFunctions, IHookFunctions, @@ -26,7 +27,14 @@ export async function strapiApiRequest( uri?: string, headers: IDataObject = {}, ) { - const credentials = await this.getCredentials('strapiApi'); + const authenticationMethod = this.getNodeParameter('authentication', 0); + let credentials: ICredentialDataDecryptedObject; + + if (authenticationMethod === 'password') { + credentials = await this.getCredentials('strapiApi'); + } else { + credentials = await this.getCredentials('strapiTokenApi'); + } const url = removeTrailingSlash(credentials.url as string); @@ -49,7 +57,11 @@ export async function strapiApiRequest( delete options.body; } - return await this.helpers?.request(options); + return await this.helpers.requestWithAuthentication.call( + this, + authenticationMethod === 'password' ? 'strapiApi' : 'strapiTokenApi', + options, + ); } catch (error) { throw new NodeApiError(this.getNode(), error as JsonObject); } @@ -57,7 +69,7 @@ export async function strapiApiRequest( export async function getToken( this: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions | IWebhookFunctions, -): Promise { +): Promise<{ jwt: string }> { const credentials = await this.getCredentials('strapiApi'); const url = removeTrailingSlash(credentials.url as string); @@ -75,7 +87,7 @@ export async function getToken( uri: credentials.apiVersion === 'v4' ? `${url}/api/auth/local` : `${url}/auth/local`, json: true, }; - return this.helpers.request(options); + return this.helpers.request(options) as Promise<{ jwt: string }>; } export async function strapiApiRequestAllItems( @@ -85,9 +97,9 @@ export async function strapiApiRequestAllItems( body: IDataObject = {}, query: IDataObject = {}, headers: IDataObject = {}, + apiVersion: string = 'v3', ) { const returnData: IDataObject[] = []; - const { apiVersion } = await this.getCredentials('strapiApi'); let responseData; if (apiVersion === 'v4') { diff --git a/packages/nodes-base/nodes/Strapi/Strapi.node.ts b/packages/nodes-base/nodes/Strapi/Strapi.node.ts index b4f5250aa2832..ae610b0470f47 100644 --- a/packages/nodes-base/nodes/Strapi/Strapi.node.ts +++ b/packages/nodes-base/nodes/Strapi/Strapi.node.ts @@ -41,9 +41,39 @@ export class Strapi implements INodeType { name: 'strapiApi', required: true, testedBy: 'strapiApiTest', + displayOptions: { + show: { + authentication: ['password'], + }, + }, + }, + { + name: 'strapiTokenApi', + required: true, + displayOptions: { + show: { + authentication: ['token'], + }, + }, }, ], properties: [ + { + displayName: 'Authentication', + name: 'authentication', + type: 'options', + options: [ + { + name: 'Username & Password', + value: 'password', + }, + { + name: 'API Token', + value: 'token', + }, + ], + default: 'password', + }, { displayName: 'Resource', name: 'resource', @@ -112,10 +142,18 @@ export class Strapi implements INodeType { const resource = this.getNodeParameter('resource', 0); const operation = this.getNodeParameter('operation', 0); - const { apiVersion } = await this.getCredentials('strapiApi'); - const { jwt } = await getToken.call(this); + const authenticationMethod = this.getNodeParameter('authentication', 0); + + let apiVersion: string; + + if (authenticationMethod === 'password') { + const { jwt } = await getToken.call(this); + apiVersion = (await this.getCredentials('strapiApi')).apiVersion as string; + headers.Authorization = `Bearer ${jwt}`; + } else { + apiVersion = (await this.getCredentials('strapiTokenApi')).apiVersion as string; + } - headers.Authorization = `Bearer ${jwt}`; for (let i = 0; i < length; i++) { try { if (resource === 'entry') { @@ -213,6 +251,7 @@ export class Strapi implements INodeType { {}, qs, headers, + apiVersion, ); } else { qs['pagination[pageSize]'] = this.getNodeParameter('limit', i); @@ -256,6 +295,7 @@ export class Strapi implements INodeType { {}, qs, headers, + apiVersion, ); } else { qs._limit = this.getNodeParameter('limit', i); diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index f3e85eb95a285..987856ab5a6be 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -319,6 +319,7 @@ "dist/credentials/StoryblokContentApi.credentials.js", "dist/credentials/StoryblokManagementApi.credentials.js", "dist/credentials/StrapiApi.credentials.js", + "dist/credentials/StrapiTokenApi.credentials.js", "dist/credentials/StravaOAuth2Api.credentials.js", "dist/credentials/StripeApi.credentials.js", "dist/credentials/SupabaseApi.credentials.js",