feat(Strapi Node): Add token credentials (#7048)

Co-authored-by: Michael Kret <michael.k@radency.com>
This commit is contained in:
Elias Meire 2023-08-31 12:46:28 +02:00 committed by GitHub
parent d72f79ffb3
commit c01bca562b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 138 additions and 8 deletions

View file

@ -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',
},
},
],
};
}

View file

@ -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<any> {
): 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') {

View file

@ -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);

View file

@ -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",