n8n/packages/editor-ui/src/components/CredentialsSelect.vue
Ricardo Espinoza 609bc4d97d
Some checks failed
Test Master / install-and-build (push) Has been cancelled
Test Master / Unit tests (18.x) (push) Has been cancelled
Test Master / Unit tests (20.x) (push) Has been cancelled
Test Master / Unit tests (22.4) (push) Has been cancelled
Test Master / Lint (push) Has been cancelled
Test Master / Notify Slack on failure (push) Has been cancelled
refactor(editor): Standardize components sections order (no-changelog) (#10540)
2024-08-24 09:24:08 -04:00

165 lines
4.3 KiB
Vue

<script lang="ts">
import type { ICredentialType } from 'n8n-workflow';
import { defineComponent } from 'vue';
import ScopesNotice from '@/components/ScopesNotice.vue';
import NodeCredentials from '@/components/NodeCredentials.vue';
import { mapStores } from 'pinia';
import { useCredentialsStore } from '@/stores/credentials.store';
export default defineComponent({
name: 'CredentialsSelect',
components: {
ScopesNotice,
NodeCredentials,
},
props: [
'activeCredentialType',
'node',
'parameter',
'inputSize',
'displayValue',
'isReadOnly',
'displayTitle',
],
emits: ['update:modelValue', 'setFocus', 'onBlur', 'credentialSelected'],
computed: {
...mapStores(useCredentialsStore),
allCredentialTypes(): ICredentialType[] {
return this.credentialsStore.allCredentialTypes;
},
scopes(): string[] {
if (!this.activeCredentialType) return [];
return this.credentialsStore.getScopesByCredentialType(this.activeCredentialType);
},
supportedCredentialTypes(): ICredentialType[] {
return this.allCredentialTypes.filter((c: ICredentialType) => this.isSupported(c.name));
},
},
methods: {
focus() {
const selectRef = this.$refs.innerSelect as HTMLElement | undefined;
if (selectRef) {
selectRef.focus();
}
},
/**
* Check if a credential type belongs to one of the supported sets defined
* in the `credentialTypes` key in a `credentialsSelect` parameter
*/
isSupported(name: string): boolean {
const supported = this.getSupportedSets(this.parameter.credentialTypes);
const checkedCredType = this.credentialsStore.getCredentialTypeByName(name);
if (!checkedCredType) return false;
for (const property of supported.has) {
if (checkedCredType[property as keyof ICredentialType] !== undefined) {
// edge case: `httpHeaderAuth` has `authenticate` auth but belongs to generic auth
if (name === 'httpHeaderAuth' && property === 'authenticate') continue;
return true;
}
}
if (
checkedCredType.extends &&
checkedCredType.extends.some((parentType: string) => supported.extends.includes(parentType))
) {
return true;
}
if (checkedCredType.extends && supported.extends.length) {
// recurse upward until base credential type
// e.g. microsoftDynamicsOAuth2Api -> microsoftOAuth2Api -> oAuth2Api
return checkedCredType.extends.reduce(
(acc: boolean, parentType: string) => acc || this.isSupported(parentType),
false,
);
}
return false;
},
getSupportedSets(credentialTypes: string[]) {
return credentialTypes.reduce<{ extends: string[]; has: string[] }>(
(acc, cur) => {
const _extends = cur.split('extends:');
if (_extends.length === 2) {
acc.extends.push(_extends[1]);
return acc;
}
const _has = cur.split('has:');
if (_has.length === 2) {
acc.has.push(_has[1]);
return acc;
}
return acc;
},
{ extends: [], has: [] },
);
},
},
});
</script>
<template>
<div>
<div :class="$style['parameter-value-container']">
<n8n-select
ref="innerSelect"
:size="inputSize"
filterable
:model-value="displayValue"
:placeholder="$locale.baseText('parameterInput.select')"
:title="displayTitle"
:disabled="isReadOnly"
data-test-id="credential-select"
@update:model-value="(value: string) => $emit('update:modelValue', value)"
@keydown.stop
@focus="$emit('setFocus')"
@blur="$emit('onBlur')"
>
<n8n-option
v-for="credType in supportedCredentialTypes"
:key="credType.name"
:value="credType.name"
:label="credType.displayName"
data-test-id="credential-select-option"
>
<div class="list-option">
<div class="option-headline">
{{ credType.displayName }}
</div>
</div>
</n8n-option>
</n8n-select>
<slot name="issues-and-options" />
</div>
<ScopesNotice
v-if="scopes.length > 0"
:active-credential-type="activeCredentialType"
:scopes="scopes"
/>
<div>
<NodeCredentials
:node="node"
:readonly="isReadOnly"
:override-cred-type="node.parameters[parameter.name]"
@credential-selected="(updateInformation) => $emit('credentialSelected', updateInformation)"
/>
</div>
</div>
</template>
<style module lang="scss">
.parameter-value-container {
display: flex;
align-items: center;
}
</style>