🔀 Merge parent branch

This commit is contained in:
Iván Ovejero 2022-05-05 16:04:17 +02:00
commit d8de1cf85d
7 changed files with 182 additions and 29 deletions

View file

@ -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]"
@ -93,7 +98,16 @@ export default mixins(
computed: {
...mapGetters('credentials', {
credentialOptions: 'allCredentialsByType',
getCredentialTypeByName: 'getCredentialTypeByName',
}),
isProxyAuth(): boolean {
return this.isHttpRequestNodeV2(this.node) &&
this.node.parameters.authenticateWith === 'nodeCredential';
},
isGenericAuth(): boolean {
return this.isHttpRequestNodeV2(this.node) &&
this.node.parameters.authenticateWith === 'genericAuth';
},
credentialTypesNode (): string[] {
return this.credentialTypesNodeDescription
.map((credentialTypeDescription) => credentialTypeDescription.name);
@ -111,6 +125,18 @@ export default mixins(
this.$emit('newHttpRequestNodeCredentialType', this.node.parameters.nodeCredentialType);
}
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;
@ -300,7 +326,7 @@ export default mixins(
<style lang="scss" module>
.container {
margin: var(--spacing-xs) 0;
margin: 0;
> * {
margin-bottom: var(--spacing-xs);

View file

@ -37,16 +37,24 @@
},
)"
/>
<node-credentials
<node-webhooks
:node="node"
@credentialSelected="credentialSelected"
@newHttpRequestNodeCredentialType="loadScopesNoticeData"
:nodeType="nodeType"
/>
<node-webhooks :node="node" :nodeType="nodeType" />
<parameter-input-list :parameters="parametersNoneSetting" :hideDelete="true" :nodeValues="nodeValues" path="parameters" @valueChanged="valueChanged" />
<parameter-input-list
:parameters="parametersNoneSetting"
:hideDelete="true"
:nodeValues="nodeValues" path="parameters" @valueChanged="valueChanged"
@newHttpRequestNodeCredentialType="loadScopesNoticeData"
>
<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>
</div>

View file

@ -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">
<slot v-if="indexToShowSlotAt === index" />
<div
v-if="multipleValues(parameter) === true && parameter.type !== 'fixedCollection'"
class="parameter-item"
@ -129,6 +131,11 @@ export default mixins(
node (): INodeUi {
return this.$store.getters.activeNode;
},
indexToShowSlotAt (): number {
if (this.isHttpRequestNodeV2(this.node)) return 2;
return 0;
},
},
methods: {
multipleValues (parameter: INodeProperties): boolean {
@ -260,7 +267,12 @@ export default mixins(
</script>
<style lang="scss">
.paramter-input-list-wrapper {
.parameter-input-list-wrapper {
div:first-child > .node-credentials {
padding-top: var(--spacing-xs);
}
.delete-option {
display: none;
position: absolute;

View file

@ -1,4 +1,5 @@
import {
HTTP_REQUEST_NODE_TYPE,
PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
} from '@/constants';
@ -32,12 +33,19 @@ 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: {
isHttpRequestNodeV2 (node: INodeUi): boolean {
return node.type === HTTP_REQUEST_NODE_TYPE && node.typeVersion === 2;
},
// Returns the parameter value
getParameterValue (nodeValues: INodeParameters, parameterName: string, path: string) {
@ -116,6 +124,23 @@ export const nodeHelpers = mixins(
return false;
},
reportUnsetCredential(credentialType: ICredentialType) {
return {
credentials: {
[credentialType.name]: [
this.$locale.baseText(
'nodeHelpers.credentialsUnset',
{
interpolate: {
credentialType: credentialType.displayName,
},
},
),
],
},
};
},
// Updates the execution issues.
updateNodesExecutionIssues () {
const nodes = this.$store.getters.allNodes;
@ -198,6 +223,46 @@ export const nodeHelpers = mixins(
let credentialType: ICredentialType | null;
let credentialDisplayName: string;
let selectedCredentials: INodeCredentialsDetails;
const {
authenticateWith,
genericAuthType,
nodeCredentialType,
} = node.parameters as HttpRequestNode.V2.AuthParams;
if (
this.isHttpRequestNodeV2(node) &&
authenticateWith === 'genericAuth' &&
selectedCredsAreUnusable(node, genericAuthType)
) {
const credential = this.getCredentialTypeByName(genericAuthType);
return this.reportUnsetCredential(credential);
}
if (
this.isHttpRequestNodeV2(node) &&
authenticateWith === 'nodeCredential' &&
nodeCredentialType !== '' &&
node.credentials !== undefined
) {
const stored = this.getCredentialsByType(nodeCredentialType);
if (selectedCredsDoNotExist(node, nodeCredentialType, stored)) {
const credential = this.getCredentialTypeByName(nodeCredentialType);
return this.reportUnsetCredential(credential);
}
}
if (
this.isHttpRequestNodeV2(node) &&
authenticateWith === 'nodeCredential' &&
nodeCredentialType !== '' &&
selectedCredsAreUnusable(node, nodeCredentialType)
) {
const credential = this.getCredentialTypeByName(nodeCredentialType);
return this.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 +459,39 @@ export const nodeHelpers = mixins(
},
},
});
/**
* 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 selectedCredsDoNotExist(
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);
}
declare namespace HttpRequestNode {
namespace V2 {
type AuthParams = {
authenticateWith: 'none' | 'genericAuth' | 'nodeCredential';
genericAuthType: string;
nodeCredentialType: string;
};
}
}

View file

@ -330,6 +330,11 @@ export const workflowHelpers = mixins(
if (node.credentials !== undefined && nodeType.credentials !== undefined) {
const saveCredenetials: INodeCredentials = {};
for (const nodeCredentialTypeName of Object.keys(node.credentials)) {
if (this.isHttpRequestNodeV2(node)) {
saveCredenetials[nodeCredentialTypeName] = node.credentials[nodeCredentialTypeName];
continue;
}
const credentialTypeDescription = nodeType.credentials
.find((credentialTypeDescription) => credentialTypeDescription.name === nodeCredentialTypeName);

View file

@ -387,6 +387,7 @@
"nodeErrorView.stack": "Stack",
"nodeErrorView.theErrorCauseIsTooLargeToBeDisplayed": "The error cause is too large to be displayed",
"nodeErrorView.time": "Time",
"nodeHelpers.credentialsUnset": "Credentials for '{credentialType}' are not set.",
"nodeSettings.alwaysOutputData.description": "If active, will output a single, empty item when the output would have been empty. Use to prevent the workflow finishing on this node.",
"nodeSettings.alwaysOutputData.displayName": "Always Output Data",
"nodeSettings.clickOnTheQuestionMarkIcon": "Click the '?' icon to open this node on n8n.io",

View file

@ -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: [