feat: Add n8n Public API (#3064)

*  Inicial setup

*  Add authentication handler

*  Add GET /users route

*  Improvements

* 👕 Fix linting issues

*  Add GET /users/:identifier endpoint

*  Add POST /users endpoint

*  Add DELETE /users/:identifier endpoint

*  Return error using express native functions

* 👕 Fix linting issue

*  Possibility to add custom middleware

*  Refactor POST /users

*  Refactor DELETE /users

*  Improve cleaning function

*  Refactor GET /users and /users/:identifier

*  Add API spec to route

*  Add raw option to response helper

* 🐛 Fix issue adding custom middleware

*  Enable includeRole parameter in GET /users/:identifier

*  Fix linting issues after merge

*  Add missing config variable

*  General improvements

 asasas

*  Add POST /users tests

* Debug public API tests

* Fix both sets of tests

*  Improvements

*  Load api versions dynamically

*  Add endpoints to UM to create/delete an API Key

*  Add index to apiKey column

* 👕 Fix linting issue

*  Clean open api spec

*  Improvements

*  Skip tests

* 🐛 Fix bug with test

*  Fix issue with the open api spec

*  Fix merge issue

*  Move token enpoints from /users to /me

*  Apply feedback to openapi.yml

*  Improvements to api-key endpoints

* 🐛 Fix test to suport API dynamic loading

*  Expose swagger ui in GET /{version}/docs

*  Allow to disable public api via env variable

*  Change handlers structure

* 🚧 WIP create credential, delete credential complete

* 🐛 fix route for creating api key

*  return api key of authenticated user

*  Expose public api activation to the settings

* ⬆️ Update package-lock.json file

*  Add execution resource

*  Fix linting issues

* 🛠 conditional public api endpoints excluding

* ️ create credential complete

*  Added n8n-card component. Added spacing utility classes.

* ♻️ Made use of n8n-card in existing components.

*  Added api key setup view.

*  Added api keys get/create/delete actions.

*  Added public api permissions handling.

* ♻️ Temporarily disabling card tests.

* ♻️ Changed translations. Storing api key only in component.

*  Added utilities storybook entry

* ♻️ Changed default value for generic copy input.

* 🧹 clean up createCredential

*  Add workflow resource to openapi spec

* 🐛 Fix naming with env variable

*  Allow multifile openapi spec

*  Add POST /workflows/:workflowId/activate

* fix up view, fix issues

* remove delete api key modal

* remove unused prop

* clean up store api

* remove getter

* remove unused dispatch

* fix component size to match

* use existing components

* match figma closely

* fix bug when um is disabled in sidebar

* set copy input color

* remove unused import

*  Remove css path

*  Add POST /workflows/:workflowId/desactivate

*  Add POST /workflows

* Revert " Remove css path"

a3d0a71719834ef37c88c23c83dfe662e96185aa

* attempt to fix docker image issue

* revert dockerfile test

* disable public api

* disable api differently

* Revert "disable api differently"

b70e29433e45934975e41ffdc32e288988aba9b0

* Revert "disable public api"

886e5164fb4135c164f77561bdb4427e5cd44ac1

* remove unused box

*  PUT /workflows/:workflowId

*  Refactor workflow endpoints

*  Refactor executions endpoints

*  Fix typo

*  add credentials tests

*  adjust users tests

* update text

* add try it out link

*  Add delete, getAll and get to the workflow resource

* address spacing comments

* ️ apply correct structure

*  Add missing test to user resource and fix some issues

*  Add workflow tests

*  Add missing workflow tests and fix some issues

*  Executions tests

*  finish execution tests

*  Validate credentials data depending on type

* ️ implement review comments

* 👕 fix lint issues

*  Add apiKey to sanatizeUser

*  Fix issues with spec and tests

*  Add new structure

*  Validate credentials type and properties

*  Make all endpoints except /users independent on UM

*  Add instance base path to swagger UI

*  Remove testing endpoints

*  Fix issue with openapi tags

*  Add endpoint GET /credentialTypes/:id/schema

* 🐛 Fix issue adding json middleware to public api

*  Add API playground path to FE

*  Add telemetry and external hooks

* 🐛 Fix issue with user tests

*  Move /credentialTypes under /credentials

*  Add test to GET /credentials/schema/:id

* 🛠 refactor schema naming

*  Add DB migrations
asas

*  add tests for crd apiKey

*  Added API View telemetry events.

*  Remove rsync from the building process as it is missing on alpine base image

*  add missing BE telemetry events

* 🐛 Fix credential tests

*  address outstanding feedback

* 🔨 Remove move:openapi script

* ⬆️ update dependency

* ⬆️ update package-lock.json

* 👕 Fix linting issue

* 🐛 Fix package.json issue

* 🐛 fix migrations and tests

* 🐛 fix typos + naming

* 🚧 WIP fixing tests

*  Add json schema validation

*  Add missing fields to node schema

*  Add limit max upper limit

*  Rename id paths

* 🐛 Fix tests

* Add package-lock.jsonto custom dockerfile

* ⬆️ Update package-lock.json

* 🐛 Fix issue with build

* ✏️ add beta label to api view

* 🔥 Remove user endpoints

*  Add schema examples to GET /credentials/schema/:id

* 🔥 Remove user endpoints tests

* 🐛 Fix tests

* 🎨 adapt points from design review

* 🔥 remove unnecessary text-align

* ️ update UI

* 🐛 Fix issue with executions filter

*  Add tags filter to GET /workflows

*  Add missing error messages

*  add and update public api tests

*  add tests for owner activiating/deactivating non-owned wfs

* 🧪 add tests for filter for tags

* 🧪 add tests for more filter params

* 🐛 fix inclusion of tags

* 🛠 enhance readability

* ️ small refactorings

* 💄 improving readability/naming

*  Set API latest version dinamically

* Add comments to toJsonSchema function

*  Fix issue

*  Make execution data usable

*  Fix validation issue

*  Rename data field and change parameter and options

* 🐛 Fix issue parameter "detailsFieldFormat" not resolving correctly

* Skip executions tests

* skip workflow failing test

* Rename details property to data

*  Add includeData parameter

* 🐛 Fix issue with openapi spec

* 🐛 Fix linting issue

*  Fix execution schema

Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
Co-authored-by: Ben Hesseldieck <b.hesseldieck@gmail.com>
Co-authored-by: Alex Grozav <alex@grozav.com>
Co-authored-by: Mutasem <mutdmour@gmail.com>
Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
This commit is contained in:
Ricardo Espinoza
2022-06-08 14:53:12 -04:00
committed by GitHub
parent 1999f4b066
commit a18081d749
112 changed files with 7182 additions and 139 deletions

View File

@@ -137,6 +137,10 @@ export class User {
this.updatedAt = new Date();
}
@Column({ type: String, nullable: true })
@Index({ unique: true })
apiKey?: string | null;
/**
* Whether the user is pending setup completion.
*/

View File

@@ -0,0 +1,29 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import config from '../../../../config';
export class AddAPIKeyColumn1652905585850 implements MigrationInterface {
name = 'AddAPIKeyColumn1652905585850';
public async up(queryRunner: QueryRunner): Promise<void> {
const tablePrefix = config.getEnv('database.tablePrefix');
await queryRunner.query(
'ALTER TABLE `' + tablePrefix + 'user` ADD COLUMN `apiKey` VARCHAR(255)',
);
await queryRunner.query(
'CREATE UNIQUE INDEX `UQ_' +
tablePrefix +
'ie0zomxves9w3p774drfrkxtj5` ON `' +
tablePrefix +
'user` (`apiKey`)',
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
const tablePrefix = config.get('database.tablePrefix');
await queryRunner.query(
'DROP INDEX `IDX_81fc04c8a17de15835713505e4` ON `' + tablePrefix + 'execution_entity`',
);
await queryRunner.query('ALTER TABLE `' + tablePrefix + 'user` DROP COLUMN `apiKey`');
}
}

View File

@@ -14,6 +14,7 @@ import { AddExecutionEntityIndexes1644424784709 } from './1644424784709-AddExecu
import { CreateUserManagement1646992772331 } from './1646992772331-CreateUserManagement';
import { LowerCaseUserEmail1648740597343 } from './1648740597343-LowerCaseUserEmail';
import { AddUserSettings1652367743993 } from './1652367743993-AddUserSettings';
import { AddAPIKeyColumn1652905585850 } from './1652905585850-AddAPIKeyColumn';
export const mysqlMigrations = [
InitialMigration1588157391238,
@@ -32,4 +33,5 @@ export const mysqlMigrations = [
CreateUserManagement1646992772331,
LowerCaseUserEmail1648740597343,
AddUserSettings1652367743993,
AddAPIKeyColumn1652905585850,
];

View File

@@ -0,0 +1,28 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import config from '../../../../config';
export class AddAPIKeyColumn1652905585850 implements MigrationInterface {
name = 'AddAPIKeyColumn1652905585850';
public async up(queryRunner: QueryRunner): Promise<void> {
let tablePrefix = config.getEnv('database.tablePrefix');
const schema = config.getEnv('database.postgresdb.schema');
if (schema) {
tablePrefix = schema + '.' + tablePrefix;
}
await queryRunner.query(`ALTER TABLE ${tablePrefix}user ADD COLUMN "apiKey" VARCHAR(255)`);
await queryRunner.query(
`CREATE UNIQUE INDEX "UQ_${tablePrefix}ie0zomxves9w3p774drfrkxtj5" ON ${tablePrefix}user ("apiKey")`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
let tablePrefix = config.getEnv('database.tablePrefix');
const schema = config.getEnv('database.postgresdb.schema');
if (schema) {
tablePrefix = schema + '.' + tablePrefix;
}
await queryRunner.query(`DROP INDEX "UQ_${tablePrefix}ie0zomxves9w3p774drfrkxtj5"`);
await queryRunner.query(`ALTER TABLE ${tablePrefix}user DROP COLUMN "apiKey"`);
}
}

View File

@@ -12,6 +12,7 @@ import { IncreaseTypeVarcharLimit1646834195327 } from './1646834195327-IncreaseT
import { CreateUserManagement1646992772331 } from './1646992772331-CreateUserManagement';
import { LowerCaseUserEmail1648740597343 } from './1648740597343-LowerCaseUserEmail';
import { AddUserSettings1652367743993 } from './1652367743993-AddUserSettings';
import { AddAPIKeyColumn1652905585850 } from './1652905585850-AddAPIKeyColumn';
export const postgresMigrations = [
InitialMigration1587669153312,
@@ -28,4 +29,5 @@ export const postgresMigrations = [
CreateUserManagement1646992772331,
LowerCaseUserEmail1648740597343,
AddUserSettings1652367743993,
AddAPIKeyColumn1652905585850,
];

View File

@@ -0,0 +1,54 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import * as config from '../../../../config';
import { logMigrationEnd, logMigrationStart } from '../../utils/migrationHelpers';
export class AddAPIKeyColumn1652905585850 implements MigrationInterface {
name = 'AddAPIKeyColumn1652905585850';
async up(queryRunner: QueryRunner): Promise<void> {
logMigrationStart(this.name);
const tablePrefix = config.getEnv('database.tablePrefix');
await queryRunner.query('PRAGMA foreign_keys=OFF');
await queryRunner.query(
`CREATE TABLE "temporary_user" ("id" varchar PRIMARY KEY NOT NULL, "email" varchar(255), "firstName" varchar(32), "lastName" varchar(32), "password" varchar, "resetPasswordToken" varchar, "resetPasswordTokenExpiration" integer DEFAULT NULL, "personalizationAnswers" text, "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "updatedAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "globalRoleId" integer NOT NULL, "settings" text, "apiKey" varchar, CONSTRAINT "FK_${tablePrefix}f0609be844f9200ff4365b1bb3d" FOREIGN KEY ("globalRoleId") REFERENCES "${tablePrefix}role" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`,
);
await queryRunner.query(
`INSERT INTO "temporary_user"("id", "email", "firstName", "lastName", "password", "resetPasswordToken", "resetPasswordTokenExpiration", "personalizationAnswers", "createdAt", "updatedAt", "globalRoleId", "settings") SELECT "id", "email", "firstName", "lastName", "password", "resetPasswordToken", "resetPasswordTokenExpiration", "personalizationAnswers", "createdAt", "updatedAt", "globalRoleId", "settings" FROM "${tablePrefix}user"`,
);
await queryRunner.query(`DROP TABLE "${tablePrefix}user"`);
await queryRunner.query(`ALTER TABLE "temporary_user" RENAME TO "${tablePrefix}user"`);
await queryRunner.query(
`CREATE UNIQUE INDEX "UQ_${tablePrefix}e12875dfb3b1d92d7d7c5377e2" ON "${tablePrefix}user" ("email")`,
);
await queryRunner.query(
`CREATE UNIQUE INDEX "UQ_${tablePrefix}ie0zomxves9w3p774drfrkxtj5" ON "${tablePrefix}user" ("apiKey")`,
);
await queryRunner.query('PRAGMA foreign_keys=ON');
logMigrationEnd(this.name);
}
async down(queryRunner: QueryRunner): Promise<void> {
const tablePrefix = config.getEnv('database.tablePrefix');
await queryRunner.query('PRAGMA foreign_keys=OFF');
await queryRunner.query(`ALTER TABLE "${tablePrefix}user" RENAME TO "temporary_user"`);
await queryRunner.query(
`CREATE TABLE "${tablePrefix}user" ("id" varchar PRIMARY KEY NOT NULL, "email" varchar(255), "firstName" varchar(32), "lastName" varchar(32), "password" varchar, "resetPasswordToken" varchar, "resetPasswordTokenExpiration" integer DEFAULT NULL, "personalizationAnswers" text, "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "updatedAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "globalRoleId" integer NOT NULL, "settings" text, CONSTRAINT "FK_${tablePrefix}f0609be844f9200ff4365b1bb3d" FOREIGN KEY ("globalRoleId") REFERENCES "${tablePrefix}role" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`,
);
await queryRunner.query(
`INSERT INTO "${tablePrefix}user"("id", "email", "firstName", "lastName", "password", "resetPasswordToken", "resetPasswordTokenExpiration", "personalizationAnswers", "createdAt", "updatedAt", "globalRoleId", "settings") SELECT "id", "email", "firstName", "lastName", "password", "resetPasswordToken", "resetPasswordTokenExpiration", "personalizationAnswers", "createdAt", "updatedAt", "globalRoleId", "settings" FROM "temporary_user"`,
);
await queryRunner.query(`DROP TABLE "temporary_user"`);
await queryRunner.query(
`CREATE UNIQUE INDEX "UQ_${tablePrefix}e12875dfb3b1d92d7d7c5377e2" ON "${tablePrefix}user" ("email")`,
);
await queryRunner.query('PRAGMA foreign_keys=ON');
}
}

View File

@@ -13,6 +13,7 @@ import { AddExecutionEntityIndexes1644421939510 } from './1644421939510-AddExecu
import { CreateUserManagement1646992772331 } from './1646992772331-CreateUserManagement';
import { LowerCaseUserEmail1648740597343 } from './1648740597343-LowerCaseUserEmail';
import { AddUserSettings1652367743993 } from './1652367743993-AddUserSettings';
import { AddAPIKeyColumn1652905585850 } from './1652905585850-AddAPIKeyColumn';
const sqliteMigrations = [
InitialMigration1588102412422,
@@ -28,6 +29,7 @@ const sqliteMigrations = [
CreateUserManagement1646992772331,
LowerCaseUserEmail1648740597343,
AddUserSettings1652367743993,
AddAPIKeyColumn1652905585850,
];
export { sqliteMigrations };