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

@@ -1,6 +1,6 @@
<template functional>
<div :class="$style.container">
<div :class="$style.heading">
<div :class="$style.heading" v-if="props.heading">
<component :is="$options.components.N8nHeading" size="xlarge" align="center">{{ props.heading }}</component>
</div>
<div :class="$style.description">

View File

@@ -25,7 +25,11 @@
:size="props.size"
/>
</span>
<span v-if="props.label">{{ props.label }}</span>
<span v-if="props.label || $slots.default">
<slot>
{{ props.label }}
</slot>
</span>
</component>
</template>

View File

@@ -0,0 +1,29 @@
/* tslint:disable:variable-name */
import N8nCard from './Card.vue';
import {StoryFn} from "@storybook/vue";
export default {
title: 'Atoms/Card',
component: N8nCard,
};
export const Default: StoryFn = (args, {argTypes}) => ({
props: Object.keys(argTypes),
components: {
N8nCard,
},
template: `<n8n-card v-bind="$props">This is a card.</n8n-card>`,
});
export const WithHeaderAndFooter: StoryFn = (args, {argTypes}) => ({
props: Object.keys(argTypes),
components: {
N8nCard,
},
template: `<n8n-card v-bind="$props">
<template #header>Header</template>
This is a card.
<template #footer>Footer</template>
</n8n-card>`,
});

View File

@@ -0,0 +1,49 @@
<template>
<div :class="['card', $style.card]" v-on="$listeners">
<div :class="$style.header" v-if="$slots.header">
<slot name="header" />
</div>
<div :class="$style.body" v-if="$slots.default">
<slot />
</div>
<div :class="$style.footer" v-if="$slots.footer">
<slot name="footer" />
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
name: 'n8n-card',
});
</script>
<style lang="scss" module>
.card {
border-radius: var(--border-radius-large);
border: var(--border-base);
background-color: var(--color-background-xlight);
padding: var(--spacing-s);
display: flex;
flex-direction: column;
justify-content: space-between;
}
.header,
.footer {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.body {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
</style>

View File

@@ -0,0 +1,26 @@
import {render} from '@testing-library/vue';
import N8nCard from "../Card.vue";
describe('components', () => {
describe('N8nCard', () => {
it('should render correctly', () => {
const wrapper = render(N8nCard, {
slots: {
default: 'This is a card.',
},
});
expect(wrapper.html()).toMatchSnapshot();
});
it('should render correctly with header and footer', () => {
const wrapper = render(N8nCard, {
slots: {
header: 'Header',
default: 'This is a card.',
footer: 'Footer',
},
});
expect(wrapper.html()).toMatchSnapshot();
});
});
});

View File

@@ -0,0 +1,3 @@
import N8nCard from './Card.vue';
export default N8nCard;

View File

@@ -1,7 +1,7 @@
<template>
<div :class="[$style[theme], $style[type]]">
<div :class="{[$style[theme]]: true, [$style[type]]: true, [$style.bold]: bold}">
<n8n-tooltip :placement="tooltipPlacement" :popper-class="$style.tooltipPopper" :disabled="type !== 'tooltip'">
<span>
<span :class="$style.iconText">
<n8n-icon :icon="theme.startsWith('info') ? 'info-circle': 'exclamation-triangle'" />
<span v-if="type === 'note'"><slot></slot></span>
</span>
@@ -33,6 +33,10 @@ export default {
validator: (value: string): boolean =>
['note', 'tooltip'].includes(value),
},
bold: {
type: Boolean,
default: true,
},
tooltipPlacement: {
type: String,
default: 'top',
@@ -44,7 +48,6 @@ export default {
<style lang="scss" module>
.base {
font-size: var(--font-size-2xs);
font-weight: var(--font-weight-bold);
line-height: var(--font-size-s);
word-break: normal;
display: flex;
@@ -55,6 +58,10 @@ export default {
}
}
.bold {
font-weight: var(--font-weight-bold);
}
.note {
composes: base;
@@ -68,6 +75,10 @@ export default {
display: inline-flex;
}
.iconText {
display: inline-flex;
}
.info-light {
color: var(--color-foreground-dark);
}

View File

@@ -38,6 +38,7 @@ import N8nActionToggle from './N8nActionToggle';
import N8nAvatar from './N8nAvatar';
import N8nBadge from './N8nBadge';
import N8nButton from './N8nButton';
import N8nCard from './N8nCard';
import N8nFormBox from './N8nFormBox';
import N8nFormInput from './N8nFormInput';
import N8nFormInputs from './N8nFormInputs';
@@ -76,6 +77,7 @@ export {
N8nAvatar,
N8nBadge,
N8nButton,
N8nCard,
N8nHeading,
N8nFormBox,
N8nFormInput,

View File

@@ -0,0 +1,67 @@
<template>
<div>
<div
v-for="size in ['5xs', '4xs', '3xs', '2xs', 'xs', 's', 'm', 'l', 'xl', '2xl', '3xl', '4xl', '5xl']"
class="spacing-group"
:key="size"
>
<div
class="spacing-example"
:class="`${property[0]}${side ? side[0] : ''}-${size}`"
>
<div class="spacing-box" />
<div class="label">
{{property[0]}}{{side ? side[0] : ''}}-{{size}}
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
name: 'SpacingPreview',
props: {
property: {
type: String,
default: 'padding',
},
side: {
type: String,
default: '',
},
},
});
</script>
<style lang="scss">
$box-size: 64px;
.spacing-group {
border: var(--border-base);
margin: var(--spacing-s);
display: inline-flex;
}
.spacing-example {
background: white;
position: relative;
background: hsla(var(--color-primary-h), var(--color-primary-s), var(--color-primary-l), 0.25);
}
.spacing-box {
width: $box-size;
height: $box-size;
display: block;
position: relative;
background: var(--color-primary);
}
.label {
position: absolute;
bottom: -1rem;
right: 0;
font-size: var(--font-size-s);
}
</style>

View File

@@ -0,0 +1,47 @@
/* tslint:disable:variable-name */
import {StoryFn} from "@storybook/vue";
import SpacingPreview from "../styleguide/SpacingPreview.vue";
export default {
title: 'Utilities/Spacing',
};
const Template: StoryFn = (args, {argTypes}) => ({
props: Object.keys(argTypes),
components: {
SpacingPreview,
},
template: `<spacing-preview v-bind="$props" />`,
});
export const Padding = Template.bind({});
Padding.args = { property: 'padding' };
export const PaddingTop = Template.bind({});
PaddingTop.args = { property: 'padding', side: 'top' };
export const PaddingRight = Template.bind({});
PaddingRight.args = { property: 'padding', side: 'right' };
export const PaddingBottom = Template.bind({});
PaddingBottom.args = { property: 'padding', side: 'bottom' };
export const PaddingLeft = Template.bind({});
PaddingLeft.args = { property: 'padding', side: 'left' };
export const Margin = Template.bind({});
Margin.args = { property: 'margin' };
export const MarginTop = Template.bind({});
MarginTop.args = { property: 'margin', side: 'top' };
export const MarginRight = Template.bind({});
MarginRight.args = { property: 'margin', side: 'right' };
export const MarginBottom = Template.bind({});
MarginBottom.args = { property: 'margin', side: 'bottom' };
export const MarginLeft = Template.bind({});
MarginLeft.args = { property: 'margin', side: 'left' };