2019-06-23 03:35:23 -07:00
|
|
|
<template>
|
2022-12-14 01:04:10 -08:00
|
|
|
<div
|
|
|
|
v-if="credentialTypesNodeDescriptionDisplayed.length"
|
|
|
|
:class="['node-credentials', $style.container]"
|
|
|
|
>
|
|
|
|
<div
|
|
|
|
v-for="credentialTypeDescription in credentialTypesNodeDescriptionDisplayed"
|
|
|
|
:key="credentialTypeDescription.name"
|
|
|
|
>
|
2021-10-27 12:55:37 -07:00
|
|
|
<n8n-input-label
|
2022-12-14 01:04:10 -08:00
|
|
|
:label="
|
|
|
|
$locale.baseText('nodeCredentials.credentialFor', {
|
2021-11-10 10:41:40 -08:00
|
|
|
interpolate: {
|
2022-12-14 01:04:10 -08:00
|
|
|
credentialType: credentialTypeNames[credentialTypeDescription.name],
|
|
|
|
},
|
|
|
|
})
|
|
|
|
"
|
2021-10-27 12:55:37 -07:00
|
|
|
:bold="false"
|
2022-12-14 01:04:10 -08:00
|
|
|
:set="(issues = getIssues(credentialTypeDescription.name))"
|
2022-05-24 02:36:19 -07:00
|
|
|
size="small"
|
2022-10-12 05:06:28 -07:00
|
|
|
color="text-dark"
|
2021-10-27 12:55:37 -07:00
|
|
|
>
|
2022-11-15 04:25:04 -08:00
|
|
|
<div v-if="readonly || isReadOnly">
|
2022-05-24 02:36:19 -07:00
|
|
|
<n8n-input
|
2022-12-12 04:46:10 -08:00
|
|
|
:value="getSelectedName(credentialTypeDescription.name)"
|
2022-05-24 02:36:19 -07:00
|
|
|
disabled
|
|
|
|
size="small"
|
|
|
|
/>
|
2021-10-27 12:55:37 -07:00
|
|
|
</div>
|
2022-12-14 01:04:10 -08:00
|
|
|
<div v-else :class="issues.length ? $style.hasIssues : $style.input">
|
2022-12-12 04:46:10 -08:00
|
|
|
<n8n-select
|
|
|
|
:value="getSelectedId(credentialTypeDescription.name)"
|
|
|
|
@change="(value) => onCredentialSelected(credentialTypeDescription.name, value)"
|
|
|
|
:placeholder="getSelectPlaceholder(credentialTypeDescription.name, issues)"
|
|
|
|
size="small"
|
|
|
|
>
|
2021-10-27 12:55:37 -07:00
|
|
|
<n8n-option
|
2022-12-14 01:04:10 -08:00
|
|
|
v-for="item in getCredentialOptions(credentialTypeDescription.name)"
|
2021-10-27 12:55:37 -07:00
|
|
|
:key="item.id"
|
|
|
|
:label="item.name"
|
2022-12-14 01:04:10 -08:00
|
|
|
:value="item.id"
|
|
|
|
>
|
2021-10-27 12:55:37 -07:00
|
|
|
</n8n-option>
|
|
|
|
<n8n-option
|
|
|
|
:key="NEW_CREDENTIALS_TEXT"
|
|
|
|
:value="NEW_CREDENTIALS_TEXT"
|
|
|
|
:label="NEW_CREDENTIALS_TEXT"
|
|
|
|
>
|
|
|
|
</n8n-option>
|
|
|
|
</n8n-select>
|
|
|
|
|
|
|
|
<div :class="$style.warning" v-if="issues.length">
|
2022-12-14 01:04:10 -08:00
|
|
|
<n8n-tooltip placement="top">
|
2022-11-18 05:59:31 -08:00
|
|
|
<template #content>
|
2022-12-14 01:04:10 -08:00
|
|
|
<titled-list
|
|
|
|
:title="`${$locale.baseText('nodeCredentials.issues')}:`"
|
|
|
|
:items="issues"
|
|
|
|
/>
|
2022-11-18 05:59:31 -08:00
|
|
|
</template>
|
2021-08-29 04:36:17 -07:00
|
|
|
<font-awesome-icon icon="exclamation-triangle" />
|
|
|
|
</n8n-tooltip>
|
2019-06-23 03:35:23 -07:00
|
|
|
</div>
|
|
|
|
|
2022-12-14 01:04:10 -08:00
|
|
|
<div
|
|
|
|
:class="$style.edit"
|
|
|
|
v-if="
|
|
|
|
selected[credentialTypeDescription.name] &&
|
|
|
|
isCredentialExisting(credentialTypeDescription.name)
|
|
|
|
"
|
|
|
|
>
|
|
|
|
<font-awesome-icon
|
|
|
|
icon="pen"
|
|
|
|
@click="editCredential(credentialTypeDescription.name)"
|
|
|
|
class="clickable"
|
|
|
|
:title="$locale.baseText('nodeCredentials.updateCredential')"
|
|
|
|
/>
|
2021-10-27 12:55:37 -07:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</n8n-input-label>
|
2019-06-23 03:35:23 -07:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
2022-11-23 04:41:53 -08:00
|
|
|
import { restApi } from '@/mixins/restApi';
|
2019-06-23 03:35:23 -07:00
|
|
|
import {
|
2021-10-13 15:21:00 -07:00
|
|
|
ICredentialsResponse,
|
2019-06-23 03:35:23 -07:00
|
|
|
INodeUi,
|
|
|
|
INodeUpdatePropertiesInformation,
|
2022-11-04 06:04:31 -07:00
|
|
|
IUser,
|
2019-06-23 03:35:23 -07:00
|
|
|
} from '@/Interface';
|
2022-12-14 01:04:10 -08:00
|
|
|
import { ICredentialType, INodeCredentialDescription, INodeCredentialsDetails } from 'n8n-workflow';
|
2019-06-23 03:35:23 -07:00
|
|
|
|
2022-11-23 04:41:53 -08:00
|
|
|
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
|
|
import { nodeHelpers } from '@/mixins/nodeHelpers';
|
|
|
|
import { showMessage } from '@/mixins/showMessage';
|
2019-06-23 03:35:23 -07:00
|
|
|
|
2022-09-05 07:36:22 -07:00
|
|
|
import TitledList from '@/components/TitledList.vue';
|
|
|
|
|
2019-06-23 03:35:23 -07:00
|
|
|
import mixins from 'vue-typed-mixins';
|
2022-12-14 01:04:10 -08:00
|
|
|
import { getCredentialPermissions } from '@/permissions';
|
2022-11-04 06:04:31 -07:00
|
|
|
import { mapStores } from 'pinia';
|
|
|
|
import { useUIStore } from '@/stores/ui';
|
|
|
|
import { useUsersStore } from '@/stores/users';
|
|
|
|
import { useWorkflowsStore } from '@/stores/workflows';
|
|
|
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
2022-11-09 01:01:50 -08:00
|
|
|
import { useCredentialsStore } from '@/stores/credentials';
|
2019-06-23 03:35:23 -07:00
|
|
|
|
2022-12-14 01:04:10 -08:00
|
|
|
export default mixins(genericHelpers, nodeHelpers, restApi, showMessage).extend({
|
2019-06-23 03:35:23 -07:00
|
|
|
name: 'NodeCredentials',
|
|
|
|
props: [
|
2022-11-15 04:25:04 -08:00
|
|
|
'readonly',
|
2019-06-23 03:35:23 -07:00
|
|
|
'node', // INodeUi
|
2022-05-24 02:36:19 -07:00
|
|
|
'overrideCredType', // cred type
|
2019-06-23 03:35:23 -07:00
|
|
|
],
|
2022-09-05 07:36:22 -07:00
|
|
|
components: {
|
|
|
|
TitledList,
|
|
|
|
},
|
2022-12-14 01:04:10 -08:00
|
|
|
data() {
|
2021-09-11 01:15:36 -07:00
|
|
|
return {
|
2021-12-15 04:16:53 -08:00
|
|
|
NEW_CREDENTIALS_TEXT: `- ${this.$locale.baseText('nodeCredentials.createNew')} -`,
|
2022-11-09 01:01:50 -08:00
|
|
|
subscribedToCredentialType: '',
|
2021-09-11 01:15:36 -07:00
|
|
|
};
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
2022-11-09 01:01:50 -08:00
|
|
|
mounted() {
|
|
|
|
this.listenForNewCredentials();
|
|
|
|
},
|
2019-06-23 03:35:23 -07:00
|
|
|
computed: {
|
2022-11-04 06:04:31 -07:00
|
|
|
...mapStores(
|
2022-11-09 01:01:50 -08:00
|
|
|
useCredentialsStore,
|
2022-11-04 06:04:31 -07:00
|
|
|
useNodeTypesStore,
|
|
|
|
useUIStore,
|
|
|
|
useUsersStore,
|
|
|
|
useWorkflowsStore,
|
|
|
|
),
|
2022-12-14 01:04:10 -08:00
|
|
|
allCredentialsByType(): { [type: string]: ICredentialsResponse[] } {
|
2022-11-09 01:01:50 -08:00
|
|
|
return this.credentialsStore.allCredentialsByType;
|
|
|
|
},
|
2022-12-14 01:04:10 -08:00
|
|
|
currentUser(): IUser {
|
|
|
|
return this.usersStore.currentUser || ({} as IUser);
|
2022-11-04 06:04:31 -07:00
|
|
|
},
|
2022-12-14 01:04:10 -08:00
|
|
|
credentialTypesNode(): string[] {
|
|
|
|
return this.credentialTypesNodeDescription.map(
|
|
|
|
(credentialTypeDescription) => credentialTypeDescription.name,
|
|
|
|
);
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
2022-12-14 01:04:10 -08:00
|
|
|
credentialTypesNodeDescriptionDisplayed(): INodeCredentialDescription[] {
|
|
|
|
return this.credentialTypesNodeDescription.filter((credentialTypeDescription) => {
|
|
|
|
return this.displayCredentials(credentialTypeDescription);
|
|
|
|
});
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
2022-12-14 01:04:10 -08:00
|
|
|
credentialTypesNodeDescription(): INodeCredentialDescription[] {
|
2019-06-23 03:35:23 -07:00
|
|
|
const node = this.node as INodeUi;
|
|
|
|
|
2022-11-09 01:01:50 -08:00
|
|
|
const credType = this.credentialsStore.getCredentialTypeByName(this.overrideCredType);
|
2022-05-24 02:36:19 -07:00
|
|
|
|
|
|
|
if (credType) return [credType];
|
|
|
|
|
2022-11-04 06:04:31 -07:00
|
|
|
const activeNodeType = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
|
2019-06-23 03:35:23 -07:00
|
|
|
if (activeNodeType && activeNodeType.credentials) {
|
|
|
|
return activeNodeType.credentials;
|
|
|
|
}
|
|
|
|
|
|
|
|
return [];
|
|
|
|
},
|
2022-12-14 01:04:10 -08:00
|
|
|
credentialTypeNames() {
|
2019-06-23 03:35:23 -07:00
|
|
|
const returnData: {
|
|
|
|
[key: string]: string;
|
|
|
|
} = {};
|
|
|
|
let credentialType: ICredentialType | null;
|
|
|
|
for (const credentialTypeName of this.credentialTypesNode) {
|
2022-11-09 01:01:50 -08:00
|
|
|
credentialType = this.credentialsStore.getCredentialTypeByName(credentialTypeName);
|
2022-12-14 01:04:10 -08:00
|
|
|
returnData[credentialTypeName] =
|
|
|
|
credentialType !== null ? credentialType.displayName : credentialTypeName;
|
2019-06-23 03:35:23 -07:00
|
|
|
}
|
|
|
|
return returnData;
|
|
|
|
},
|
2022-12-14 01:04:10 -08:00
|
|
|
selected(): { [type: string]: INodeCredentialsDetails } {
|
2021-09-11 01:15:36 -07:00
|
|
|
return this.node.credentials || {};
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
|
|
|
},
|
2022-10-17 04:39:42 -07:00
|
|
|
|
2019-06-23 03:35:23 -07:00
|
|
|
methods: {
|
2022-09-21 01:20:29 -07:00
|
|
|
getCredentialOptions(type: string): ICredentialsResponse[] {
|
2022-12-14 01:04:10 -08:00
|
|
|
return (this.allCredentialsByType as Record<string, ICredentialsResponse[]>)[type].filter(
|
|
|
|
(credential) => {
|
|
|
|
const permissions = getCredentialPermissions(this.currentUser, credential);
|
2022-09-21 01:20:29 -07:00
|
|
|
|
2022-12-14 01:04:10 -08:00
|
|
|
return permissions.use;
|
|
|
|
},
|
|
|
|
);
|
2022-09-21 01:20:29 -07:00
|
|
|
},
|
2021-10-13 15:21:00 -07:00
|
|
|
getSelectedId(type: string) {
|
|
|
|
if (this.isCredentialExisting(type)) {
|
|
|
|
return this.selected[type].id;
|
|
|
|
}
|
|
|
|
return undefined;
|
|
|
|
},
|
2022-12-12 04:46:10 -08:00
|
|
|
getSelectedName(type: string) {
|
|
|
|
return this.selected?.[type]?.name;
|
|
|
|
},
|
|
|
|
getSelectPlaceholder(type: string, issues: string[]) {
|
|
|
|
return issues.length && this.getSelectedName(type)
|
2022-12-14 01:04:10 -08:00
|
|
|
? this.$locale.baseText('nodeCredentials.selectedCredentialUnavailable', {
|
|
|
|
interpolate: { name: this.getSelectedName(type) },
|
|
|
|
})
|
2022-12-12 04:46:10 -08:00
|
|
|
: this.$locale.baseText('nodeCredentials.selectCredential');
|
|
|
|
},
|
2022-12-14 01:04:10 -08:00
|
|
|
credentialInputWrapperStyle(credentialType: string) {
|
2019-06-23 03:35:23 -07:00
|
|
|
let deductWidth = 0;
|
|
|
|
const styles = {
|
|
|
|
width: '100%',
|
|
|
|
};
|
|
|
|
if (this.getIssues(credentialType).length) {
|
|
|
|
deductWidth += 20;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (deductWidth !== 0) {
|
|
|
|
styles.width = `calc(100% - ${deductWidth}px)`;
|
|
|
|
}
|
|
|
|
|
|
|
|
return styles;
|
|
|
|
},
|
2022-11-09 01:01:50 -08:00
|
|
|
// TODO: Investigate if this can be solved using only the store data (storing selected flag in credentials objects, ...)
|
|
|
|
listenForNewCredentials() {
|
|
|
|
// Listen for credentials store changes so credential selection can be updated if creds are changed from the modal
|
|
|
|
this.credentialsStore.$subscribe((mutation, state) => {
|
|
|
|
// This data pro stores credential type that the component is currently interested in
|
|
|
|
const credentialType = this.subscribedToCredentialType;
|
2022-11-10 03:51:50 -08:00
|
|
|
let credentialsOfType = this.credentialsStore.allCredentialsByType[credentialType];
|
|
|
|
|
|
|
|
if (credentialsOfType) {
|
|
|
|
credentialsOfType = credentialsOfType.sort((a, b) => (a.id < b.id ? -1 : 1));
|
|
|
|
if (credentialsOfType.length > 0) {
|
|
|
|
// If nothing has been selected previously, select the first one (newly added)
|
|
|
|
if (!this.selected[credentialType]) {
|
|
|
|
this.onCredentialSelected(credentialType, credentialsOfType[0].id);
|
|
|
|
} else {
|
|
|
|
// Else, check id currently selected cred has been updated
|
2022-12-14 01:04:10 -08:00
|
|
|
const newSelected = credentialsOfType.find(
|
|
|
|
(cred) => cred.id === this.selected[credentialType].id,
|
|
|
|
);
|
2022-11-10 03:51:50 -08:00
|
|
|
// If it has changed, select it
|
|
|
|
if (newSelected && newSelected.name !== this.selected[credentialType].name) {
|
|
|
|
this.onCredentialSelected(credentialType, newSelected.id);
|
2022-12-14 01:04:10 -08:00
|
|
|
} else {
|
|
|
|
// Else select the last cred with that type since selected has been deleted or a new one has been added
|
|
|
|
this.onCredentialSelected(
|
|
|
|
credentialType,
|
|
|
|
credentialsOfType[credentialsOfType.length - 1].id,
|
|
|
|
);
|
2022-11-10 03:51:50 -08:00
|
|
|
}
|
2022-11-09 01:01:50 -08:00
|
|
|
}
|
|
|
|
}
|
2021-09-11 01:15:36 -07:00
|
|
|
}
|
2022-11-09 01:01:50 -08:00
|
|
|
this.subscribedToCredentialType = '';
|
2021-09-11 01:15:36 -07:00
|
|
|
});
|
|
|
|
},
|
2021-10-13 15:21:00 -07:00
|
|
|
clearSelectedCredential(credentialType: string) {
|
|
|
|
const node: INodeUi = this.node;
|
|
|
|
|
|
|
|
const credentials = {
|
|
|
|
...(node.credentials || {}),
|
|
|
|
};
|
|
|
|
|
|
|
|
delete credentials[credentialType];
|
|
|
|
|
|
|
|
const updateInformation: INodeUpdatePropertiesInformation = {
|
|
|
|
name: this.node.name,
|
|
|
|
properties: {
|
|
|
|
credentials,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
this.$emit('credentialSelected', updateInformation);
|
|
|
|
},
|
|
|
|
|
2022-12-14 01:04:10 -08:00
|
|
|
onCredentialSelected(credentialType: string, credentialId: string | null | undefined) {
|
2021-11-20 06:58:21 -08:00
|
|
|
if (credentialId === this.NEW_CREDENTIALS_TEXT) {
|
2022-11-09 01:01:50 -08:00
|
|
|
// this.listenForNewCredentials(credentialType);
|
|
|
|
this.subscribedToCredentialType = credentialType;
|
|
|
|
}
|
|
|
|
if (!credentialId || credentialId === this.NEW_CREDENTIALS_TEXT) {
|
2022-11-04 06:04:31 -07:00
|
|
|
this.uiStore.openNewCredential(credentialType);
|
2022-12-14 01:04:10 -08:00
|
|
|
this.$telemetry.track('User opened Credential modal', {
|
|
|
|
credential_type: credentialType,
|
|
|
|
source: 'node',
|
|
|
|
new_credential: true,
|
|
|
|
workflow_id: this.workflowsStore.workflowId,
|
|
|
|
});
|
2021-10-13 15:21:00 -07:00
|
|
|
return;
|
2021-09-11 01:15:36 -07:00
|
|
|
}
|
2021-10-13 15:21:00 -07:00
|
|
|
|
2022-12-14 01:04:10 -08:00
|
|
|
this.$telemetry.track('User selected credential from node modal', {
|
|
|
|
credential_type: credentialType,
|
|
|
|
node_type: this.node.type,
|
|
|
|
...(this.hasProxyAuth(this.node) ? { is_service_specific: true } : {}),
|
|
|
|
workflow_id: this.workflowsStore.workflowId,
|
|
|
|
credential_id: credentialId,
|
|
|
|
});
|
2021-10-18 20:57:49 -07:00
|
|
|
|
2022-11-09 01:01:50 -08:00
|
|
|
const selectedCredentials = this.credentialsStore.getCredentialById(credentialId);
|
2022-12-14 01:04:10 -08:00
|
|
|
const oldCredentials =
|
|
|
|
this.node.credentials && this.node.credentials[credentialType]
|
|
|
|
? this.node.credentials[credentialType]
|
|
|
|
: {};
|
2021-10-13 15:21:00 -07:00
|
|
|
|
2021-10-18 20:57:49 -07:00
|
|
|
const selected = { id: selectedCredentials.id, name: selectedCredentials.name };
|
2021-10-13 15:21:00 -07:00
|
|
|
|
|
|
|
// if credentials has been string or neither id matched nor name matched uniquely
|
2022-12-14 01:04:10 -08:00
|
|
|
if (
|
|
|
|
oldCredentials.id === null ||
|
|
|
|
(oldCredentials.id &&
|
|
|
|
!this.credentialsStore.getCredentialByIdAndType(oldCredentials.id, credentialType))
|
|
|
|
) {
|
2021-10-13 15:21:00 -07:00
|
|
|
// update all nodes in the workflow with the same old/invalid credentials
|
2022-11-04 06:04:31 -07:00
|
|
|
this.workflowsStore.replaceInvalidWorkflowCredentials({
|
2021-10-13 15:21:00 -07:00
|
|
|
credentials: selected,
|
|
|
|
invalid: oldCredentials,
|
|
|
|
type: credentialType,
|
|
|
|
});
|
|
|
|
this.updateNodesCredentialsIssues();
|
|
|
|
this.$showMessage({
|
2021-12-15 04:16:53 -08:00
|
|
|
title: this.$locale.baseText('nodeCredentials.showMessage.title'),
|
2022-12-14 01:04:10 -08:00
|
|
|
message: this.$locale.baseText('nodeCredentials.showMessage.message', {
|
|
|
|
interpolate: {
|
|
|
|
oldCredentialName: oldCredentials.name,
|
|
|
|
newCredentialName: selected.name,
|
2021-11-10 10:41:40 -08:00
|
|
|
},
|
2022-12-14 01:04:10 -08:00
|
|
|
}),
|
2021-10-13 15:21:00 -07:00
|
|
|
type: 'success',
|
|
|
|
});
|
2021-09-11 01:15:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
const node: INodeUi = this.node;
|
|
|
|
|
|
|
|
const credentials = {
|
|
|
|
...(node.credentials || {}),
|
|
|
|
[credentialType]: selected,
|
|
|
|
};
|
2019-06-23 03:35:23 -07:00
|
|
|
|
|
|
|
const updateInformation: INodeUpdatePropertiesInformation = {
|
2021-09-11 01:15:36 -07:00
|
|
|
name: this.node.name,
|
2019-06-23 03:35:23 -07:00
|
|
|
properties: {
|
2021-09-11 01:15:36 -07:00
|
|
|
credentials,
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
this.$emit('credentialSelected', updateInformation);
|
|
|
|
},
|
2021-09-11 01:15:36 -07:00
|
|
|
|
2022-12-14 01:04:10 -08:00
|
|
|
displayCredentials(credentialTypeDescription: INodeCredentialDescription): boolean {
|
2019-06-23 03:35:23 -07:00
|
|
|
if (credentialTypeDescription.displayOptions === undefined) {
|
|
|
|
// If it is not defined no need to do a proper check
|
|
|
|
return true;
|
|
|
|
}
|
2022-04-28 10:04:09 -07:00
|
|
|
return this.displayParameter(this.node.parameters, credentialTypeDescription, '', this.node);
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
2021-09-11 01:15:36 -07:00
|
|
|
|
2022-12-14 01:04:10 -08:00
|
|
|
getIssues(credentialTypeName: string): string[] {
|
2019-06-23 03:35:23 -07:00
|
|
|
const node = this.node as INodeUi;
|
|
|
|
|
|
|
|
if (node.issues === undefined || node.issues.credentials === undefined) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!node.issues.credentials.hasOwnProperty(credentialTypeName)) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
return node.issues.credentials[credentialTypeName];
|
|
|
|
},
|
|
|
|
|
2021-10-13 15:21:00 -07:00
|
|
|
isCredentialExisting(credentialType: string): boolean {
|
2022-12-14 01:04:10 -08:00
|
|
|
if (
|
|
|
|
!this.node.credentials ||
|
|
|
|
!this.node.credentials[credentialType] ||
|
|
|
|
!this.node.credentials[credentialType].id
|
|
|
|
) {
|
2021-10-13 15:21:00 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const { id } = this.node.credentials[credentialType];
|
2022-09-21 01:20:29 -07:00
|
|
|
const options = this.getCredentialOptions(credentialType);
|
2019-06-23 03:35:23 -07:00
|
|
|
|
2021-10-13 15:21:00 -07:00
|
|
|
return !!options.find((option: ICredentialsResponse) => option.id === id);
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
|
|
|
|
2021-09-11 01:15:36 -07:00
|
|
|
editCredential(credentialType: string): void {
|
2021-10-13 15:21:00 -07:00
|
|
|
const { id } = this.node.credentials[credentialType];
|
2022-11-04 06:04:31 -07:00
|
|
|
this.uiStore.openExistingCredential(id);
|
2019-06-23 03:35:23 -07:00
|
|
|
|
2022-12-14 01:04:10 -08:00
|
|
|
this.$telemetry.track('User opened Credential modal', {
|
|
|
|
credential_type: credentialType,
|
|
|
|
source: 'node',
|
|
|
|
new_credential: false,
|
|
|
|
workflow_id: this.workflowsStore.workflowId,
|
|
|
|
});
|
2022-11-09 01:01:50 -08:00
|
|
|
this.subscribedToCredentialType = credentialType;
|
2019-06-23 03:35:23 -07:00
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
|
2021-10-27 12:55:37 -07:00
|
|
|
<style lang="scss" module>
|
|
|
|
.container {
|
2022-05-24 02:36:19 -07:00
|
|
|
margin-top: var(--spacing-xs);
|
2022-06-07 06:02:08 -07:00
|
|
|
|
|
|
|
& > div:not(:first-child) {
|
|
|
|
margin-top: var(--spacing-xs);
|
|
|
|
}
|
2021-10-27 12:55:37 -07:00
|
|
|
}
|
2019-06-23 03:35:23 -07:00
|
|
|
|
2021-10-27 12:55:37 -07:00
|
|
|
.warning {
|
|
|
|
min-width: 20px;
|
|
|
|
margin-left: 5px;
|
|
|
|
color: #ff8080;
|
|
|
|
font-size: var(--font-size-s);
|
|
|
|
}
|
2021-08-29 04:36:17 -07:00
|
|
|
|
2021-10-27 12:55:37 -07:00
|
|
|
.edit {
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
color: var(--color-text-base);
|
|
|
|
min-width: 20px;
|
|
|
|
margin-left: 5px;
|
|
|
|
font-size: var(--font-size-s);
|
|
|
|
}
|
2021-10-13 15:21:00 -07:00
|
|
|
|
2021-10-27 12:55:37 -07:00
|
|
|
.input {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
2019-06-23 03:35:23 -07:00
|
|
|
}
|
|
|
|
|
2021-10-27 12:55:37 -07:00
|
|
|
.hasIssues {
|
|
|
|
composes: input;
|
|
|
|
--input-border-color: var(--color-danger);
|
|
|
|
}
|
2019-06-23 03:35:23 -07:00
|
|
|
</style>
|