mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
🔀 Merge parent branch
This commit is contained in:
commit
9bd62c7e1d
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -1,3 +1,21 @@
|
|||
# [0.175.0](https://github.com/n8n-io/n8n/compare/n8n@0.174.0...n8n@0.175.0) (2022-05-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- **core:** Do not applying auth if UM is disabled ([#3218](https://github.com/n8n-io/n8n/issues/3218)) ([4ceac38](https://github.com/n8n-io/n8n/commit/4ceac38e0397be91bfc1b50d8a06ebf20de8c32e))
|
||||
- **core:** Skip credential check of disabled nodes and improve error ([79ced8f](https://github.com/n8n-io/n8n/commit/79ced8f6774cc70d63369001d7c56d1d4a340261))
|
||||
- **editor:** Fix bug with touchscreens ([#3206](https://github.com/n8n-io/n8n/issues/3206)) ([8d9e05e](https://github.com/n8n-io/n8n/commit/8d9e05e3c3ef61cd5a65ec00d3d1474f1195f653))
|
||||
- **Hubspot Node:** Fix search operators ([#3208](https://github.com/n8n-io/n8n/issues/3208)) ([ea4a8b8](https://github.com/n8n-io/n8n/commit/ea4a8b88c9bbfde3304073070a430f2421477921))
|
||||
- **Sendgrid Node:** Fix issue sending attachments ([#3213](https://github.com/n8n-io/n8n/issues/3213)) ([2b00881](https://github.com/n8n-io/n8n/commit/2b008815cad82619a66d4b30d1f79630c82be978))
|
||||
- **Wise Node:** Respect time parameter on get: exchangeRate ([#3227](https://github.com/n8n-io/n8n/issues/3227)) ([c7d525a](https://github.com/n8n-io/n8n/commit/c7d525a60fda4aad653017cb90253426cce98b3b))
|
||||
|
||||
### Features
|
||||
|
||||
- **core:** Introduce simplified node versioning ([#3205](https://github.com/n8n-io/n8n/issues/3205)) ([d5b9b0c](https://github.com/n8n-io/n8n/commit/d5b9b0cb9596688b3bcad0010b65888428c297c6))
|
||||
- **Google Sheets Node:** Allow to use header names as JSON path ([#3165](https://github.com/n8n-io/n8n/issues/3165)) ([770c4fe](https://github.com/n8n-io/n8n/commit/770c4fe6ebe70c7a507ee5e57348508b98fda11d))
|
||||
- **Microsoft Dynamics CRM Node:** Add support for other regions than North America ([#3157](https://github.com/n8n-io/n8n/issues/3157)) ([4bdd607](https://github.com/n8n-io/n8n/commit/4bdd607fdf00f6c2155c9b3e3c9e74ac50e317f4))
|
||||
- **Telegram Node:** Allow querying chat administrators ([#3226](https://github.com/n8n-io/n8n/issues/3226)) ([c02d259](https://github.com/n8n-io/n8n/commit/c02d259453f2f5b444569f4c1e06fbfc95cd3305)), closes [#3157](https://github.com/n8n-io/n8n/issues/3157)
|
||||
|
||||
# [0.174.0](https://github.com/n8n-io/n8n/compare/n8n@0.173.1...n8n@0.174.0) (2022-04-25)
|
||||
|
||||
### Bug Fixes
|
||||
|
|
34909
package-lock.json
generated
34909
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n",
|
||||
"version": "0.174.0",
|
||||
"version": "0.175.0",
|
||||
"private": true,
|
||||
"homepage": "https://n8n.io",
|
||||
"scripts": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n",
|
||||
"version": "0.174.0",
|
||||
"version": "0.175.0",
|
||||
"description": "n8n Workflow Automation Tool",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
@ -125,10 +125,10 @@
|
|||
"lodash.get": "^4.4.2",
|
||||
"lodash.merge": "^4.6.2",
|
||||
"mysql2": "~2.3.0",
|
||||
"n8n-core": "~0.115.0",
|
||||
"n8n-editor-ui": "~0.141.0",
|
||||
"n8n-nodes-base": "~0.172.0",
|
||||
"n8n-workflow": "~0.97.0",
|
||||
"n8n-core": "~0.116.0",
|
||||
"n8n-editor-ui": "~0.142.0",
|
||||
"n8n-nodes-base": "~0.173.0",
|
||||
"n8n-workflow": "~0.98.0",
|
||||
"nodemailer": "^6.7.1",
|
||||
"oauth-1.0a": "^2.2.6",
|
||||
"open": "^7.0.0",
|
||||
|
|
|
@ -35,15 +35,12 @@ import { readFile } from 'fs/promises';
|
|||
import _, { cloneDeep } from 'lodash';
|
||||
import { dirname as pathDirname, join as pathJoin, resolve as pathResolve } from 'path';
|
||||
import {
|
||||
FindConditions,
|
||||
FindManyOptions,
|
||||
getConnection,
|
||||
getConnectionManager,
|
||||
In,
|
||||
IsNull,
|
||||
LessThan,
|
||||
LessThanOrEqual,
|
||||
MoreThan,
|
||||
Not,
|
||||
Raw,
|
||||
} from 'typeorm';
|
||||
|
@ -61,13 +58,7 @@ import { createHmac } from 'crypto';
|
|||
// tested with all possible systems like Windows, Alpine on ARM, FreeBSD, ...
|
||||
import { compare } from 'bcryptjs';
|
||||
|
||||
import {
|
||||
BinaryDataManager,
|
||||
Credentials,
|
||||
IBinaryDataConfig,
|
||||
LoadNodeParameterOptions,
|
||||
UserSettings,
|
||||
} from 'n8n-core';
|
||||
import { BinaryDataManager, Credentials, LoadNodeParameterOptions, UserSettings } from 'n8n-core';
|
||||
|
||||
import {
|
||||
ICredentialType,
|
||||
|
@ -154,14 +145,11 @@ import { WEBHOOK_METHODS } from './WebhookHelpers';
|
|||
import { userManagementRouter } from './UserManagement';
|
||||
import { resolveJwt } from './UserManagement/auth/jwt';
|
||||
import { User } from './databases/entities/User';
|
||||
import { CredentialsEntity } from './databases/entities/CredentialsEntity';
|
||||
import type {
|
||||
CredentialRequest,
|
||||
ExecutionRequest,
|
||||
WorkflowRequest,
|
||||
NodeParameterOptionsRequest,
|
||||
OAuthRequest,
|
||||
AuthenticatedRequest,
|
||||
TagsRequest,
|
||||
} from './requests';
|
||||
import { DEFAULT_EXECUTIONS_GET_ALL_LIMIT, validateEntity } from './GenericHelpers';
|
||||
|
@ -170,7 +158,11 @@ import { SharedWorkflow } from './databases/entities/SharedWorkflow';
|
|||
import { AUTH_COOKIE_NAME, RESPONSE_ERROR_MESSAGES } from './constants';
|
||||
import { credentialsController } from './api/credentials.api';
|
||||
import { oauth2CredentialController } from './api/oauth2Credential.api';
|
||||
import { getInstanceBaseUrl, isEmailSetUp } from './UserManagement/UserManagementHelper';
|
||||
import {
|
||||
getInstanceBaseUrl,
|
||||
isEmailSetUp,
|
||||
isUserManagementEnabled,
|
||||
} from './UserManagement/UserManagementHelper';
|
||||
|
||||
require('body-parser-xml')(bodyParser);
|
||||
|
||||
|
@ -312,9 +304,7 @@ class App {
|
|||
config.getEnv('personalization.enabled') && config.getEnv('diagnostics.enabled'),
|
||||
defaultLocale: config.getEnv('defaultLocale'),
|
||||
userManagement: {
|
||||
enabled:
|
||||
config.getEnv('userManagement.disabled') === false ||
|
||||
config.getEnv('userManagement.isInstanceOwnerSetUp') === true,
|
||||
enabled: isUserManagementEnabled(),
|
||||
showSetupOnFirstLoad:
|
||||
config.getEnv('userManagement.disabled') === false &&
|
||||
config.getEnv('userManagement.isInstanceOwnerSetUp') === false &&
|
||||
|
@ -347,9 +337,7 @@ class App {
|
|||
getSettingsForFrontend(): IN8nUISettings {
|
||||
// refresh user management status
|
||||
Object.assign(this.frontendSettings.userManagement, {
|
||||
enabled:
|
||||
config.getEnv('userManagement.disabled') === false ||
|
||||
config.getEnv('userManagement.isInstanceOwnerSetUp') === true,
|
||||
enabled: isUserManagementEnabled(),
|
||||
showSetupOnFirstLoad:
|
||||
config.getEnv('userManagement.disabled') === false &&
|
||||
config.getEnv('userManagement.isInstanceOwnerSetUp') === false &&
|
||||
|
@ -568,12 +556,14 @@ class App {
|
|||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const authCookie = req.cookies?.[AUTH_COOKIE_NAME] ?? '';
|
||||
await resolveJwt(authCookie);
|
||||
} catch (error) {
|
||||
res.status(401).send('Unauthorized');
|
||||
return;
|
||||
if (isUserManagementEnabled()) {
|
||||
try {
|
||||
const authCookie = req.cookies?.[AUTH_COOKIE_NAME] ?? '';
|
||||
await resolveJwt(authCookie);
|
||||
} catch (error) {
|
||||
res.status(401).send('Unauthorized');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.push.add(req.query.sessionId as string, req, res);
|
||||
|
@ -3044,9 +3034,7 @@ export async function start(): Promise<void> {
|
|||
},
|
||||
deploymentType: config.getEnv('deployment.type'),
|
||||
binaryDataMode: binarDataConfig.mode,
|
||||
n8n_multi_user_allowed:
|
||||
config.getEnv('userManagement.disabled') === false ||
|
||||
config.getEnv('userManagement.isInstanceOwnerSetUp') === true,
|
||||
n8n_multi_user_allowed: isUserManagementEnabled(),
|
||||
smtp_set_up: config.getEnv('userManagement.emails.mode') === 'smtp',
|
||||
};
|
||||
|
||||
|
|
|
@ -32,6 +32,20 @@ export function isEmailSetUp(): boolean {
|
|||
return smtp && host && user && pass;
|
||||
}
|
||||
|
||||
export function isUserManagementEnabled(): boolean {
|
||||
return (
|
||||
!config.getEnv('userManagement.disabled') ||
|
||||
config.getEnv('userManagement.isInstanceOwnerSetUp')
|
||||
);
|
||||
}
|
||||
|
||||
export function isUserManagementDisabled(): boolean {
|
||||
return (
|
||||
config.getEnv('userManagement.disabled') &&
|
||||
!config.getEnv('userManagement.isInstanceOwnerSetUp')
|
||||
);
|
||||
}
|
||||
|
||||
async function getInstanceOwnerRole(): Promise<Role> {
|
||||
const ownerRole = await Db.collections.Role.findOneOrFail({
|
||||
where: {
|
||||
|
|
|
@ -19,7 +19,13 @@ import { usersNamespace } from './users';
|
|||
import { passwordResetNamespace } from './passwordReset';
|
||||
import { AuthenticatedRequest } from '../../requests';
|
||||
import { ownerNamespace } from './owner';
|
||||
import { isAuthExcluded, isPostUsersId, isAuthenticatedRequest } from '../UserManagementHelper';
|
||||
import {
|
||||
isAuthExcluded,
|
||||
isPostUsersId,
|
||||
isAuthenticatedRequest,
|
||||
isUserManagementDisabled,
|
||||
} from '../UserManagementHelper';
|
||||
import { Db } from '../..';
|
||||
|
||||
export function addRoutes(this: N8nApp, ignoredEndpoints: string[], restEndpoint: string): void {
|
||||
// needed for testing; not adding overhead since it directly returns if req.cookies exists
|
||||
|
@ -47,7 +53,7 @@ export function addRoutes(this: N8nApp, ignoredEndpoints: string[], restEndpoint
|
|||
|
||||
this.app.use(passport.initialize());
|
||||
|
||||
this.app.use((req: Request, res: Response, next: NextFunction) => {
|
||||
this.app.use(async (req: Request, res: Response, next: NextFunction) => {
|
||||
if (
|
||||
// TODO: refactor me!!!
|
||||
// skip authentication for preflight requests
|
||||
|
@ -73,6 +79,17 @@ export function addRoutes(this: N8nApp, ignoredEndpoints: string[], restEndpoint
|
|||
return next();
|
||||
}
|
||||
|
||||
// skip authentication if user management is disabled
|
||||
if (isUserManagementDisabled()) {
|
||||
req.user = await Db.collections.User.findOneOrFail(
|
||||
{},
|
||||
{
|
||||
relations: ['globalRole'],
|
||||
},
|
||||
);
|
||||
return next();
|
||||
}
|
||||
|
||||
return passport.authenticate('jwt', { session: false })(req, res, next);
|
||||
});
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
getInstanceBaseUrl,
|
||||
hashPassword,
|
||||
isEmailSetUp,
|
||||
isUserManagementDisabled,
|
||||
sanitizeUser,
|
||||
validatePassword,
|
||||
} from '../UserManagementHelper';
|
||||
|
@ -55,7 +56,7 @@ export function usersNamespace(this: N8nApp): void {
|
|||
}
|
||||
|
||||
// TODO: this should be checked in the middleware rather than here
|
||||
if (config.getEnv('userManagement.disabled')) {
|
||||
if (isUserManagementDisabled()) {
|
||||
Logger.debug(
|
||||
'Request to send email invite(s) to user(s) failed because user management is disabled',
|
||||
);
|
||||
|
|
|
@ -6,6 +6,7 @@ import { RESPONSE_ERROR_MESSAGES } from '../../src/constants';
|
|||
|
||||
import type { Role } from '../../src/databases/entities/Role';
|
||||
import { CredentialTypes, LoadNodesAndCredentials } from '../../src';
|
||||
import { LOAD_NODES_AND_CREDS_TEST_TIMEOUT } from './shared/constants';
|
||||
|
||||
const SCOPES_ENDPOINT = '/oauth2-credential/scopes';
|
||||
|
||||
|
@ -14,7 +15,10 @@ let testDbName = '';
|
|||
let globalOwnerRole: Role;
|
||||
|
||||
beforeAll(async () => {
|
||||
app = utils.initTestServer({ endpointGroups: ['oauth2-credential'], applyAuth: true });
|
||||
app = utils.initTestServer({
|
||||
endpointGroups: ['oauth2-credential'],
|
||||
applyAuth: true,
|
||||
});
|
||||
const initResult = await testDb.init();
|
||||
testDbName = initResult.testDbName;
|
||||
|
||||
|
@ -28,7 +32,7 @@ beforeAll(async () => {
|
|||
|
||||
const credentialTypes = CredentialTypes();
|
||||
await credentialTypes.init(loadNodesAndCredentials.credentialTypes);
|
||||
});
|
||||
}, LOAD_NODES_AND_CREDS_TEST_TIMEOUT);
|
||||
|
||||
afterAll(async () => {
|
||||
await testDb.terminate(testDbName);
|
||||
|
|
|
@ -62,3 +62,8 @@ export const BOOTSTRAP_MYSQL_CONNECTION_NAME: Readonly<string> = 'n8n_bs_mysql';
|
|||
* Timeout (in milliseconds) to account for fake SMTP service being slow to respond.
|
||||
*/
|
||||
export const SMTP_TEST_TIMEOUT = 30_000;
|
||||
|
||||
/**
|
||||
* Timeout (in milliseconds) to account for `LoadNodesAndCredentials()` being slow to run on CI/CD server.
|
||||
*/
|
||||
export const LOAD_NODES_AND_CREDS_TEST_TIMEOUT = 30_000;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-core",
|
||||
"version": "0.115.0",
|
||||
"version": "0.116.0",
|
||||
"description": "Core functionality of n8n",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
@ -52,7 +52,7 @@
|
|||
"form-data": "^4.0.0",
|
||||
"lodash.get": "^4.4.2",
|
||||
"mime-types": "^2.1.27",
|
||||
"n8n-workflow": "~0.97.0",
|
||||
"n8n-workflow": "~0.98.0",
|
||||
"oauth-1.0a": "^2.2.6",
|
||||
"p-cancelable": "^2.0.0",
|
||||
"qs": "^6.10.1",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-design-system",
|
||||
"version": "0.18.0",
|
||||
"version": "0.19.0",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
"author": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-editor-ui",
|
||||
"version": "0.141.0",
|
||||
"version": "0.142.0",
|
||||
"description": "Workflow Editor UI for n8n",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
@ -28,7 +28,7 @@
|
|||
"@fortawesome/free-regular-svg-icons": "^6.1.1",
|
||||
"luxon": "^2.3.0",
|
||||
"monaco-editor": "^0.29.1",
|
||||
"n8n-design-system": "~0.18.0",
|
||||
"n8n-design-system": "~0.19.0",
|
||||
"timeago.js": "^4.0.2",
|
||||
"v-click-outside": "^3.1.2",
|
||||
"vue-fragment": "^1.5.2",
|
||||
|
@ -78,7 +78,7 @@
|
|||
"lodash.debounce": "^4.0.8",
|
||||
"lodash.get": "^4.4.2",
|
||||
"lodash.set": "^4.3.2",
|
||||
"n8n-workflow": "~0.97.0",
|
||||
"n8n-workflow": "~0.98.0",
|
||||
"monaco-editor-webpack-plugin": "^5.0.0",
|
||||
"normalize-wheel": "^1.0.1",
|
||||
"prismjs": "^1.17.1",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div v-if="credentialTypesNodeDescriptionDisplayed.length" :class="$style.container">
|
||||
<div v-if="credentialTypesNodeDescriptionDisplayed.length" :class="['node-credentials', $style.container]">
|
||||
<div v-for="credentialTypeDescription in credentialTypesNodeDescriptionDisplayed" :key="credentialTypeDescription.name">
|
||||
<n8n-input-label
|
||||
:label="$locale.baseText(
|
||||
|
@ -11,15 +11,20 @@
|
|||
}
|
||||
)"
|
||||
:bold="false"
|
||||
size="small"
|
||||
|
||||
:set="issues = getIssues(credentialTypeDescription.name)"
|
||||
size="small"
|
||||
>
|
||||
<div v-if="isReadOnly">
|
||||
<n8n-input disabled :value="selected && selected[credentialTypeDescription.name] && selected[credentialTypeDescription.name].name" size="small" />
|
||||
<n8n-input
|
||||
:value="selected && selected[credentialTypeDescription.name] && selected[credentialTypeDescription.name].name"
|
||||
disabled
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div :class="issues.length ? $style.hasIssues : $style.input" v-else >
|
||||
<div
|
||||
v-else
|
||||
:class="issues.length ? $style.hasIssues : $style.input"
|
||||
>
|
||||
<n8n-select :value="getSelectedId(credentialTypeDescription.name)" @change="(value) => onCredentialSelected(credentialTypeDescription.name, value)" :placeholder="$locale.baseText('nodeCredentials.selectCredential')" size="small">
|
||||
<n8n-option
|
||||
v-for="(item) in credentialOptions[credentialTypeDescription.name]"
|
||||
|
@ -72,6 +77,7 @@ import { showMessage } from '@/components/mixins/showMessage';
|
|||
import { mapGetters } from "vuex";
|
||||
|
||||
import mixins from 'vue-typed-mixins';
|
||||
import { HTTP_REQUEST_NODE_TYPE } from '@/constants';
|
||||
|
||||
export default mixins(
|
||||
genericHelpers,
|
||||
|
@ -92,7 +98,18 @@ export default mixins(
|
|||
computed: {
|
||||
...mapGetters('credentials', {
|
||||
credentialOptions: 'allCredentialsByType',
|
||||
getCredentialTypeByName: 'getCredentialTypeByName',
|
||||
}),
|
||||
isProxyAuth(): boolean {
|
||||
return this.node.type === HTTP_REQUEST_NODE_TYPE
|
||||
&& this.node.typeVersion === 2
|
||||
&& this.node.parameters.authenticateWith === 'nodeCredential';
|
||||
},
|
||||
isGenericAuth(): boolean {
|
||||
return this.node.type === HTTP_REQUEST_NODE_TYPE
|
||||
&& this.node.typeVersion === 2
|
||||
&& this.node.parameters.authenticateWith === 'genericAuth';
|
||||
},
|
||||
credentialTypesNode (): string[] {
|
||||
return this.credentialTypesNodeDescription
|
||||
.map((credentialTypeDescription) => credentialTypeDescription.name);
|
||||
|
@ -106,6 +123,18 @@ export default mixins(
|
|||
credentialTypesNodeDescription (): INodeCredentialDescription[] {
|
||||
const node = this.node as INodeUi;
|
||||
|
||||
if (this.isGenericAuth) {
|
||||
const { genericAuthType } = this.node.parameters as { genericAuthType: string };
|
||||
|
||||
return [this.getCredentialTypeByName(genericAuthType)];
|
||||
}
|
||||
|
||||
if (this.isProxyAuth) {
|
||||
const { nodeCredentialType } = this.node.parameters as { nodeCredentialType?: string };
|
||||
|
||||
if (nodeCredentialType) return [this.getCredentialTypeByName(nodeCredentialType)];
|
||||
}
|
||||
|
||||
const activeNodeType = this.$store.getters.nodeType(node.type, node.typeVersion) as INodeTypeDescription | null;
|
||||
if (activeNodeType && activeNodeType.credentials) {
|
||||
return activeNodeType.credentials;
|
||||
|
@ -295,7 +324,7 @@ export default mixins(
|
|||
|
||||
<style lang="scss" module>
|
||||
.container {
|
||||
margin: var(--spacing-xs) 0;
|
||||
margin: 0;
|
||||
|
||||
> * {
|
||||
margin-bottom: var(--spacing-xs);
|
||||
|
|
|
@ -23,12 +23,23 @@
|
|||
</div>
|
||||
<div class="node-parameters-wrapper" v-if="node && nodeValid">
|
||||
<div v-show="openPanel === 'params'">
|
||||
<node-credentials :node="node" @credentialSelected="credentialSelected"></node-credentials>
|
||||
<node-webhooks :node="node" :nodeType="nodeType" />
|
||||
<parameter-input-list :parameters="parametersNoneSetting" :hideDelete="true" :nodeValues="nodeValues" path="parameters" @valueChanged="valueChanged" />
|
||||
<node-webhooks
|
||||
:node="node"
|
||||
:nodeType="nodeType"
|
||||
/>
|
||||
<parameter-input-list
|
||||
:parameters="parametersNoneSetting"
|
||||
:hideDelete="true"
|
||||
:nodeValues="nodeValues" path="parameters" @valueChanged="valueChanged"
|
||||
>
|
||||
<node-credentials
|
||||
:node="node"
|
||||
@credentialSelected="credentialSelected"
|
||||
/>
|
||||
</parameter-input-list>
|
||||
<div v-if="parametersNoneSetting.length === 0" class="no-parameters">
|
||||
<n8n-text>
|
||||
{{ $locale.baseText('nodeSettings.thisNodeDoesNotHaveAnyParameters') }}
|
||||
{{ $locale.baseText('nodeSettings.thisNodeDoesNotHaveAnyParameters') }}
|
||||
</n8n-text>
|
||||
</div>
|
||||
|
||||
|
@ -85,6 +96,8 @@ import { nodeHelpers } from '@/components/mixins/nodeHelpers';
|
|||
import mixins from 'vue-typed-mixins';
|
||||
import NodeExecuteButton from './NodeExecuteButton.vue';
|
||||
|
||||
import { HTTP_REQUEST_NODE_TYPE } from '@/constants';
|
||||
|
||||
export default mixins(
|
||||
externalHooks,
|
||||
genericHelpers,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<template>
|
||||
<div class="paramter-input-list-wrapper">
|
||||
<div v-for="parameter in filteredParameters" :key="parameter.name" :class="{indent}">
|
||||
<div class="parameter-input-list-wrapper">
|
||||
<div v-for="(parameter, index) in filteredParameters" :key="parameter.name" :class="{indent}">
|
||||
<slot v-if="indexToShowSlotAt === index" />
|
||||
|
||||
<div
|
||||
v-if="multipleValues(parameter) === true && parameter.type !== 'fixedCollection'"
|
||||
class="parameter-item"
|
||||
|
@ -86,6 +88,7 @@
|
|||
<script lang="ts">
|
||||
|
||||
import {
|
||||
INode,
|
||||
INodeParameters,
|
||||
INodeProperties,
|
||||
NodeParameterValue,
|
||||
|
@ -101,6 +104,7 @@ import ParameterInputFull from '@/components/ParameterInputFull.vue';
|
|||
import { get, set } from 'lodash';
|
||||
|
||||
import mixins from 'vue-typed-mixins';
|
||||
import { HTTP_REQUEST_NODE_TYPE } from '@/constants';
|
||||
|
||||
export default mixins(
|
||||
genericHelpers,
|
||||
|
@ -129,6 +133,13 @@ export default mixins(
|
|||
node (): INodeUi {
|
||||
return this.$store.getters.activeNode;
|
||||
},
|
||||
indexToShowSlotAt (): number {
|
||||
if (this.node.type === HTTP_REQUEST_NODE_TYPE && this.node.typeVersion === 2) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
multipleValues (parameter: INodeProperties): boolean {
|
||||
|
@ -260,7 +271,11 @@ export default mixins(
|
|||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.paramter-input-list-wrapper {
|
||||
.parameter-input-list-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: var(--spacing-xs);
|
||||
|
||||
.delete-option {
|
||||
display: none;
|
||||
position: absolute;
|
||||
|
@ -293,7 +308,7 @@ export default mixins(
|
|||
|
||||
.parameter-item {
|
||||
position: relative;
|
||||
margin: var(--spacing-xs) 0;
|
||||
margin: 0 0 var(--spacing-xs);
|
||||
|
||||
>.delete-option {
|
||||
top: var(--spacing-5xs);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {
|
||||
HTTP_REQUEST_NODE_TYPE,
|
||||
PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
||||
} from '@/constants';
|
||||
|
||||
|
@ -32,11 +33,15 @@ import { restApi } from '@/components/mixins/restApi';
|
|||
import { get } from 'lodash';
|
||||
|
||||
import mixins from 'vue-typed-mixins';
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
export const nodeHelpers = mixins(
|
||||
restApi,
|
||||
)
|
||||
.extend({
|
||||
computed: {
|
||||
...mapGetters('credentials', [ 'getCredentialTypeByName', 'getCredentialsByType' ]),
|
||||
},
|
||||
methods: {
|
||||
|
||||
// Returns the parameter value
|
||||
|
@ -198,6 +203,46 @@ export const nodeHelpers = mixins(
|
|||
let credentialType: ICredentialType | null;
|
||||
let credentialDisplayName: string;
|
||||
let selectedCredentials: INodeCredentialsDetails;
|
||||
|
||||
const { authenticateWith, genericAuthType, nodeCredentialType } = node.parameters as {
|
||||
authenticateWith: 'none' | 'genericAuth' | 'nodeCredential';
|
||||
genericAuthType: string;
|
||||
nodeCredentialType: string;
|
||||
};
|
||||
|
||||
if (
|
||||
isHttpRequestNodeV2(node) &&
|
||||
authenticateWith === 'genericAuth' &&
|
||||
selectedCredsAreUnusable(node, genericAuthType)
|
||||
) {
|
||||
const credential = this.getCredentialTypeByName(genericAuthType);
|
||||
return reportUnsetCredential(credential);
|
||||
}
|
||||
|
||||
if (
|
||||
isHttpRequestNodeV2(node) &&
|
||||
authenticateWith === 'nodeCredential' &&
|
||||
nodeCredentialType !== '' &&
|
||||
node.credentials !== undefined
|
||||
) {
|
||||
const stored = this.getCredentialsByType(nodeCredentialType);
|
||||
|
||||
if (selectedCredsWereDeleted(node, nodeCredentialType, stored)) {
|
||||
const credential = this.getCredentialTypeByName(nodeCredentialType);
|
||||
return reportUnsetCredential(credential);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
isHttpRequestNodeV2(node) &&
|
||||
authenticateWith === 'nodeCredential' &&
|
||||
nodeCredentialType !== '' &&
|
||||
selectedCredsAreUnusable(node, nodeCredentialType)
|
||||
) {
|
||||
const credential = this.getCredentialTypeByName(nodeCredentialType);
|
||||
return reportUnsetCredential(credential);
|
||||
}
|
||||
|
||||
for (const credentialTypeDescription of nodeType!.credentials!) {
|
||||
// Check if credentials should be displayed else ignore
|
||||
if (this.displayParameter(node.parameters, credentialTypeDescription, '', node) !== true) {
|
||||
|
@ -394,3 +439,41 @@ export const nodeHelpers = mixins(
|
|||
},
|
||||
},
|
||||
});
|
||||
|
||||
function isHttpRequestNodeV2(node: INodeUi) {
|
||||
return node.type === HTTP_REQUEST_NODE_TYPE && node.typeVersion === 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the node has no selected credentials, or none of the node's
|
||||
* selected credentials are of the specified type.
|
||||
*/
|
||||
function selectedCredsAreUnusable(node: INodeUi, credentialType: string) {
|
||||
return node.credentials === undefined || Object.keys(node.credentials).includes(credentialType) === false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the node's selected credentials of the specified type
|
||||
* can no longer be found in the database.
|
||||
*/
|
||||
function selectedCredsWereDeleted(
|
||||
node: INodeUi,
|
||||
nodeCredentialType: string,
|
||||
storedCredsByType: ICredentialsResponse[] | null,
|
||||
) {
|
||||
if (!node.credentials || !storedCredsByType) return false;
|
||||
|
||||
const selectedCredsByType = node.credentials[nodeCredentialType];
|
||||
|
||||
if (!selectedCredsByType) return false;
|
||||
|
||||
return !storedCredsByType.find((c) => c.id === selectedCredsByType.id);
|
||||
}
|
||||
|
||||
function reportUnsetCredential(credentialType: ICredentialType) {
|
||||
return {
|
||||
credentials: {
|
||||
[credentialType.name]: [`Credentials for "${credentialType.displayName}" are not set.`],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
START_NODE_TYPE,
|
||||
WEBHOOK_NODE_TYPE,
|
||||
VIEWS,
|
||||
HTTP_REQUEST_NODE_TYPE,
|
||||
} from '@/constants';
|
||||
|
||||
import {
|
||||
|
@ -326,10 +327,17 @@ export const workflowHelpers = mixins(
|
|||
const nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, false, false, node);
|
||||
nodeData.parameters = nodeParameters !== null ? nodeParameters : {};
|
||||
|
||||
const fullAccess = node.type === HTTP_REQUEST_NODE_TYPE && node.typeVersion === 2;
|
||||
|
||||
// Add the node credentials if there are some set and if they should be displayed
|
||||
if (node.credentials !== undefined && nodeType.credentials !== undefined) {
|
||||
const saveCredenetials: INodeCredentials = {};
|
||||
for (const nodeCredentialTypeName of Object.keys(node.credentials)) {
|
||||
if (fullAccess) {
|
||||
saveCredenetials[nodeCredentialTypeName] = node.credentials[nodeCredentialTypeName];
|
||||
continue;
|
||||
}
|
||||
|
||||
const credentialTypeDescription = nodeType.credentials
|
||||
.find((credentialTypeDescription) => credentialTypeDescription.name === nodeCredentialTypeName);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-node-dev",
|
||||
"version": "0.54.0",
|
||||
"version": "0.55.0",
|
||||
"description": "CLI to simplify n8n credentials/node development",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
@ -61,8 +61,8 @@
|
|||
"change-case": "^4.1.1",
|
||||
"copyfiles": "^2.1.1",
|
||||
"inquirer": "^7.0.1",
|
||||
"n8n-core": "~0.115.0",
|
||||
"n8n-workflow": "~0.97.0",
|
||||
"n8n-core": "~0.116.0",
|
||||
"n8n-workflow": "~0.98.0",
|
||||
"oauth-1.0a": "^2.2.6",
|
||||
"replace-in-file": "^6.0.0",
|
||||
"request": "^2.88.2",
|
||||
|
|
|
@ -52,7 +52,7 @@ export class HttpRequest implements INodeType {
|
|||
displayOptions: {
|
||||
show: {
|
||||
authenticateWith: [
|
||||
'basicAuth',
|
||||
'httpBasicAuth',
|
||||
],
|
||||
'@version': [
|
||||
2,
|
||||
|
@ -66,7 +66,7 @@ export class HttpRequest implements INodeType {
|
|||
displayOptions: {
|
||||
show: {
|
||||
authenticateWith: [
|
||||
'digestAuth',
|
||||
'httpDigestAuth',
|
||||
],
|
||||
'@version': [
|
||||
2,
|
||||
|
@ -80,7 +80,7 @@ export class HttpRequest implements INodeType {
|
|||
displayOptions: {
|
||||
show: {
|
||||
authenticateWith: [
|
||||
'headerAuth',
|
||||
'httpHeaderAuth',
|
||||
],
|
||||
'@version': [
|
||||
2,
|
||||
|
@ -94,7 +94,7 @@ export class HttpRequest implements INodeType {
|
|||
displayOptions: {
|
||||
show: {
|
||||
authenticateWith: [
|
||||
'queryAuth',
|
||||
'httpQueryAuth',
|
||||
],
|
||||
'@version': [
|
||||
2,
|
||||
|
@ -108,7 +108,7 @@ export class HttpRequest implements INodeType {
|
|||
displayOptions: {
|
||||
show: {
|
||||
authenticateWith: [
|
||||
'oAuth1',
|
||||
'oAuth1Api',
|
||||
],
|
||||
'@version': [
|
||||
2,
|
||||
|
@ -122,7 +122,7 @@ export class HttpRequest implements INodeType {
|
|||
displayOptions: {
|
||||
show: {
|
||||
authenticateWith: [
|
||||
'oAuth2',
|
||||
'oAuth2Api',
|
||||
],
|
||||
'@version': [
|
||||
2,
|
||||
|
@ -279,30 +279,30 @@ export class HttpRequest implements INodeType {
|
|||
options: [
|
||||
{
|
||||
name: 'Basic Auth',
|
||||
value: 'basicAuth',
|
||||
value: 'httpBasicAuth',
|
||||
},
|
||||
{
|
||||
name: 'Digest Auth',
|
||||
value: 'digestAuth',
|
||||
value: 'httpDigestAuth',
|
||||
},
|
||||
{
|
||||
name: 'Header Auth',
|
||||
value: 'headerAuth',
|
||||
value: 'httpHeaderAuth',
|
||||
},
|
||||
{
|
||||
name: 'Query Auth',
|
||||
value: 'queryAuth',
|
||||
value: 'httpQueryAuth',
|
||||
},
|
||||
{
|
||||
name: 'OAuth1',
|
||||
value: 'oAuth1',
|
||||
value: 'oAuth1Api',
|
||||
},
|
||||
{
|
||||
name: 'OAuth2',
|
||||
value: 'oAuth2',
|
||||
value: 'oAuth2Api',
|
||||
},
|
||||
],
|
||||
default: 'basicAuth',
|
||||
default: 'httpBasicAuth',
|
||||
displayOptions: {
|
||||
show: {
|
||||
authenticateWith: [
|
||||
|
|
|
@ -999,11 +999,11 @@ export const contactFields: INodeProperties[] = [
|
|||
},
|
||||
{
|
||||
name: 'Contains Exactly',
|
||||
value: 'CONSTAIN_TOKEN',
|
||||
value: 'CONTAINS_TOKEN',
|
||||
},
|
||||
{
|
||||
name: `Doesn't Contain Exactly`,
|
||||
value: 'NOT_CONSTAIN_TOKEN',
|
||||
value: 'NOT_CONTAINS_TOKEN',
|
||||
},
|
||||
],
|
||||
default: 'EQ',
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-nodes-base",
|
||||
"version": "0.172.0",
|
||||
"version": "0.173.0",
|
||||
"description": "Base nodes of n8n",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
@ -713,7 +713,7 @@
|
|||
"eslint-plugin-n8n-nodes-base": "^1.0.28",
|
||||
"gulp": "^4.0.0",
|
||||
"jest": "^27.4.7",
|
||||
"n8n-workflow": "~0.97.0",
|
||||
"n8n-workflow": "~0.98.0",
|
||||
"nodelinter": "^0.1.9",
|
||||
"ts-jest": "^27.1.3",
|
||||
"tslint": "^6.1.2",
|
||||
|
@ -755,7 +755,7 @@
|
|||
"mqtt": "4.2.6",
|
||||
"mssql": "^6.2.0",
|
||||
"mysql2": "~2.3.0",
|
||||
"n8n-core": "~0.115.0",
|
||||
"n8n-core": "~0.116.0",
|
||||
"node-html-markdown": "^1.1.3",
|
||||
"node-ssh": "^12.0.0",
|
||||
"nodemailer": "^6.5.0",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "n8n-workflow",
|
||||
"version": "0.97.0",
|
||||
"version": "0.98.0",
|
||||
"description": "Workflow base code of n8n",
|
||||
"license": "SEE LICENSE IN LICENSE.md",
|
||||
"homepage": "https://n8n.io",
|
||||
|
|
Loading…
Reference in a new issue