fix(editor): Remove obsolete credential resolver warnings (#31466)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Guillaume Jacquart 2026-06-01 13:49:54 +02:00 committed by GitHub
parent fe635a754e
commit f09e1c70a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 2 additions and 118 deletions

View File

@ -1150,9 +1150,6 @@
"credentials.private.callout.connected": "Your account is connected",
"credentials.private.callout.notConnected": "Your account isn't connected yet.",
"credentials.private.callout.connect": "Connect",
"credentials.dynamic.warning.noResolver": "Dynamic credentials are enabled, but no resolver is selected. Select one in {workflowSettings} to resolve user accounts at run time.",
"credentials.dynamic.warning.noResolver.workflowSettings": "Workflow settings",
"credentials.dynamic.warning.noResolver.documentation": "documentation",
"credentials.search.placeholder": "Search credentials...",
"credentials.filters.type": "Type",
"credentials.filters.setup": "Needs first setup",
@ -4129,7 +4126,6 @@
"workflows.item.availableInMCP": "Available in MCP",
"workflows.dynamic.tooltip": "This workflow resolves credentials at runtime based on who executes it.",
"workflows.dynamic.tooltipTitle": "Dynamic credentials",
"workflows.dynamic.resolverMissing": "Credential resolver missing",
"workflows.dependencies.tooltip.workflow": "Click to view resources referenced by this workflow",
"workflows.dependencies.tooltip.credential": "Click to view resources referencing this credential",
"workflows.dependencies.tooltip.dataTable": "Click to view resources referencing this data table",

View File

@ -1116,34 +1116,6 @@ describe('WorkflowCard', () => {
expect(indicator).toBeNull();
});
it('should show resolver missing badge when workflow has resolvable credentials but no resolver configured', () => {
const data = createWorkflow({
hasResolvableCredentials: true,
settings: {
credentialResolverId: undefined,
},
});
const { getByTestId } = renderComponent({ props: { data } });
const badge = getByTestId('workflow-card-resolver-missing');
expect(badge).toBeVisible();
});
it('should hide resolver missing badge when workflow has resolver configured', () => {
const data = createWorkflow({
hasResolvableCredentials: true,
settings: {
credentialResolverId: 'resolver-123',
},
});
const { queryByTestId } = renderComponent({ props: { data } });
const badge = queryByTestId('workflow-card-resolver-missing');
expect(badge).toBeNull();
});
it('should show Archived text on archived workflows', async () => {
const data = createWorkflow({ isArchived: true });
const { getByTestId, queryByTestId } = renderComponent({ props: { data } });

View File

@ -321,14 +321,6 @@ const hasDynamicCredentials = computed(() => {
return isDynamicCredentialsEnabled.value && props.data.hasResolvableCredentials;
});
const isResolverMissing = computed(() => {
return (
isDynamicCredentialsEnabled.value &&
props.data.hasResolvableCredentials &&
!props.data.settings?.credentialResolverId
);
});
const workflowHasDependencies = computed(() => hasDependencies(props.data.id));
async function onClick(event?: KeyboardEvent | PointerEvent) {
@ -644,16 +636,6 @@ const tags = computed(
</span>
</N8nBadge>
</N8nTooltip>
<N8nBadge
v-if="isResolverMissing"
theme="warning"
class="ml-3xs pl-3xs pr-3xs"
data-test-id="workflow-card-resolver-missing"
>
<span :class="$style.resolverMissingBadge">
{{ locale.baseText('workflows.dynamic.resolverMissing') }}
</span>
</N8nBadge>
</N8nText>
</template>
<div :class="$style.cardDescription">
@ -852,14 +834,6 @@ const tags = computed(
height: 18px;
}
.resolverMissingBadge {
display: inline-flex;
align-items: center;
font-size: var(--font-size--3xs);
height: 18px;
color: var(--color--warning);
}
.tooltipContent {
display: flex;
flex-direction: column;

View File

@ -510,27 +510,6 @@ describe('NodeCredentials', () => {
expect(screen.queryByTestId('node-credential-private-icon')).toBeInTheDocument();
});
it('should show warning when resolvable credential selected but workflow has no resolver', async () => {
setupResolvableCredential();
workflowDocumentStore.setSettings({ executionOrder: 'v1' });
renderComponent();
expect(screen.queryByTestId('node-credential-resolver-warning')).toBeInTheDocument();
});
it('should not show warning when resolvable credential selected and workflow has resolver', async () => {
setupResolvableCredential();
workflowDocumentStore.setSettings({
executionOrder: 'v1',
credentialResolverId: 'resolver-123',
});
renderComponent();
expect(screen.queryByTestId('node-credential-resolver-warning')).not.toBeInTheDocument();
});
});
describe('quick connect', () => {

View File

@ -8,7 +8,6 @@ import type {
NodeParameterValueType,
} from 'n8n-workflow';
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import { I18nT } from 'vue-i18n';
import { useNodeHelpers } from '@/app/composables/useNodeHelpers';
import {
@ -23,7 +22,7 @@ import { useToast } from '@/app/composables/useToast';
import TitledList from '@/app/components/TitledList.vue';
import { useI18n } from '@n8n/i18n';
import { useTelemetry } from '@/app/composables/useTelemetry';
import { CREDENTIAL_ONLY_NODE_PREFIX, WORKFLOW_SETTINGS_MODAL_KEY } from '@/app/constants';
import { CREDENTIAL_ONLY_NODE_PREFIX } from '@/app/constants';
import { ndvEventBus } from '@/features/ndv/shared/ndv.eventBus';
import { useCredentialsStore } from '../credentials.store';
import { useQuickConnect } from '../quickConnect/composables/useQuickConnect';
@ -161,10 +160,6 @@ const selected = computed<Record<string, INodeCredentialsDetails>>(
() => props.node.credentials ?? {},
);
const hasWorkflowResolver = computed(() => {
return !!workflowDocumentStore?.value?.settings?.credentialResolverId;
});
function isCredentialResolvable(credentialType: string): boolean {
if (!isDynamicCredentialsEnabled.value) return false;
const credentialId = selected.value[credentialType]?.id;
@ -185,17 +180,6 @@ function isPrivateConnected(credentialType: string): boolean {
return getSelectedPrivateCredential(credentialType)?.connectedByMe === true;
}
function showResolvableWarning(credentialType: string): boolean {
return isCredentialResolvable(credentialType) && !hasWorkflowResolver.value;
}
// TODO: use actual docs link when available
const dynamicCredentialsDocsUrl = '';
function openWorkflowSettings() {
uiStore.openModal(WORKFLOW_SETTINGS_MODAL_KEY);
}
watch(
() => props.node.parameters,
(newValue, oldValue) => {
@ -904,10 +888,7 @@ async function onQuickConnectSignIn(credentialTypeName: string) {
/>
</div>
</div>
<div
v-if="getSelectedPrivateCredential(type.name) || showResolvableWarning(type.name)"
:class="$style.noticesContainer"
>
<div v-if="getSelectedPrivateCredential(type.name)" :class="$style.noticesContainer">
<N8nNotice
v-if="getSelectedPrivateCredential(type.name)"
:theme="isPrivateConnected(type.name) ? 'info' : 'warning'"
@ -939,24 +920,6 @@ async function onQuickConnectSignIn(credentialTypeName: string) {
</div>
</div>
</N8nNotice>
<N8nNotice
v-if="showResolvableWarning(type.name)"
theme="warning"
data-test-id="node-credential-resolver-warning"
>
<I18nT keypath="credentials.dynamic.warning.noResolver" tag="span" scope="global">
<template #workflowSettings>
<N8nLink @click="openWorkflowSettings">
{{ i18n.baseText('credentials.dynamic.warning.noResolver.workflowSettings') }}
</N8nLink>
</template>
<template v-if="dynamicCredentialsDocsUrl" #documentation>
<N8nLink :href="dynamicCredentialsDocsUrl" new-window>
{{ i18n.baseText('credentials.dynamic.warning.noResolver.documentation') }}
</N8nLink>
</template>
</I18nT>
</N8nNotice>
</div>
</N8nInputLabel>
</div>