mirror of
https://github.com/n8n-io/n8n.git
synced 2026-09-24 23:22:38 +08:00
feat(editor): Localize insecure connection warning (no-changelog) (#34636)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
db5c59f9e5
commit
8301a804b4
@@ -3072,6 +3072,11 @@
|
||||
"saveButton.saved": "Saved",
|
||||
"saveButton.saving": "Saving",
|
||||
"settings": "Settings",
|
||||
"settings.authCookie.insecureConnection.title": "Your n8n server is configured to use a secure cookie, however you are either visiting this via an insecure URL, or using Safari.",
|
||||
"settings.authCookie.insecureConnection.fixIntro": "To fix this, please consider the following options:",
|
||||
"settings.authCookie.insecureConnection.option.tls": "Setup TLS/HTTPS (<strong>recommended</strong>), or",
|
||||
"settings.authCookie.insecureConnection.option.localhost": "If you are running this locally, and not using Safari, try using <a href=\"{localhostUrl}\">localhost</a> instead",
|
||||
"settings.authCookie.insecureConnection.option.disableSecureCookie": "If you prefer to disable this security feature (<strong>not recommended</strong>), set the environment variable <code>{envVar}</code> to <code>false</code>",
|
||||
"settings.communityNodes": "Community nodes",
|
||||
"settings.communityNodes.empty.title": "Supercharge your workflows with community nodes",
|
||||
"settings.communityNodes.empty.verified.only.title": "Supercharge your workflows with verified community nodes",
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@n8n/api-types": "workspace:*",
|
||||
"@n8n/i18n": "workspace:*",
|
||||
"@n8n/permissions": "workspace:*",
|
||||
"@n8n/rest-api-client": "workspace:*",
|
||||
"n8n-workflow": "workspace:*",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { FrontendSettings } from '@n8n/api-types';
|
||||
import { i18n } from '@n8n/i18n';
|
||||
import { createPinia, setActivePinia } from 'pinia';
|
||||
import type { MockInstance } from 'vitest';
|
||||
import { mock } from 'vitest-mock-extended';
|
||||
|
||||
import { useSettingsStore } from './settings.store';
|
||||
@@ -167,6 +169,56 @@ describe('settings.store', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('insecure connection warning', () => {
|
||||
let writeSpy: MockInstance<(...text: string[]) => void>;
|
||||
|
||||
beforeEach(() => {
|
||||
writeSpy = vi.spyOn(document, 'write').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it('should render the localized warning over an insecure, non-localhost origin', async () => {
|
||||
vi.stubGlobal('location', { protocol: 'http:', hostname: 'n8n.example.com' });
|
||||
|
||||
getSettings.mockResolvedValueOnce({ ...mockSettings, authCookie: { secure: true } });
|
||||
|
||||
await useSettingsStore().getSettings();
|
||||
|
||||
expect(writeSpy).toHaveBeenCalledTimes(1);
|
||||
const markup = writeSpy.mock.calls[0][0];
|
||||
expect(markup).toContain(i18n.baseText('settings.authCookie.insecureConnection.title'));
|
||||
expect(markup).toContain('N8N_SECURE_COOKIE');
|
||||
expect(markup).toContain('http://localhost:5678');
|
||||
});
|
||||
|
||||
it('should not render the warning over localhost in a non-Safari browser', async () => {
|
||||
vi.stubGlobal('location', { protocol: 'http:', hostname: 'localhost' });
|
||||
vi.stubGlobal('navigator', {
|
||||
userAgent:
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0',
|
||||
});
|
||||
|
||||
getSettings.mockResolvedValueOnce({ ...mockSettings, authCookie: { secure: true } });
|
||||
|
||||
await useSettingsStore().getSettings();
|
||||
|
||||
expect(writeSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not render the warning when the cookie is not secure', async () => {
|
||||
vi.stubGlobal('location', { protocol: 'http:', hostname: 'n8n.example.com' });
|
||||
|
||||
getSettings.mockResolvedValueOnce({ ...mockSettings, authCookie: { secure: false } });
|
||||
|
||||
await useSettingsStore().getSettings();
|
||||
|
||||
expect(writeSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSettings', () => {
|
||||
describe('telemetry', () => {
|
||||
it('should fetch settings and call sessionStarted if telemetry is enabled', async () => {
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
type FrontendModuleSettings,
|
||||
type WorkflowReviewsPolicy,
|
||||
} from '@n8n/api-types';
|
||||
import { i18n } from '@n8n/i18n';
|
||||
import { makeRestApiRequest } from '@n8n/rest-api-client';
|
||||
import * as aiUsageApi from '@n8n/rest-api-client/api/ai-usage';
|
||||
import * as eventsApi from '@n8n/rest-api-client/api/events';
|
||||
@@ -22,19 +23,20 @@ import { useRootStore } from './useRootStore';
|
||||
/**
|
||||
* Full-page warning rendered when the instance requires a secure cookie but the
|
||||
* page is served over an insecure origin (or via Safari, which drops the cookie).
|
||||
* The copy is localized; the structural markup and inline styles stay in code
|
||||
* because this is written via `document.write` before the Vue app mounts.
|
||||
*/
|
||||
const INSECURE_CONNECTION_WARNING = `
|
||||
const buildInsecureConnectionWarning = () => `
|
||||
<body style="margin-top: 20px; font-family: 'Open Sans', sans-serif; text-align: center;">
|
||||
<h1 style="font-size: 40px">🚫</h1>
|
||||
<h2>Your n8n server is configured to use a secure cookie, <br/>however you are either visiting this via an insecure URL, or using Safari.
|
||||
</h2>
|
||||
<h2>${i18n.baseText('settings.authCookie.insecureConnection.title')}</h2>
|
||||
<br/>
|
||||
<div style="font-size: 18px; max-width: 640px; text-align: left; margin: 10px auto">
|
||||
To fix this, please consider the following options:
|
||||
${i18n.baseText('settings.authCookie.insecureConnection.fixIntro')}
|
||||
<ul>
|
||||
<li>Setup TLS/HTTPS (<strong>recommended</strong>), or</li>
|
||||
<li>If you are running this locally, and not using Safari, try using <a href="http://localhost:5678">localhost</a> instead</li>
|
||||
<li>If you prefer to disable this security feature (<strong>not recommended</strong>), set the environment variable <code>N8N_SECURE_COOKIE</code> to <code>false</code></li>
|
||||
<li>${i18n.baseText('settings.authCookie.insecureConnection.option.tls')}</li>
|
||||
<li>${i18n.baseText('settings.authCookie.insecureConnection.option.localhost', { interpolate: { localhostUrl: 'http://localhost:5678' } })}</li>
|
||||
<li>${i18n.baseText('settings.authCookie.insecureConnection.option.disableSecureCookie', { interpolate: { envVar: 'N8N_SECURE_COOKIE' } })}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</body>`;
|
||||
@@ -290,7 +292,7 @@ export const useSettingsStore = defineStore(STORES.SETTINGS, () => {
|
||||
location.protocol === 'http:' &&
|
||||
(!['localhost', '127.0.0.1'].includes(location.hostname) || browser.name === 'Safari')
|
||||
) {
|
||||
document.write(INSECURE_CONNECTION_WARNING);
|
||||
document.write(buildInsecureConnectionWarning());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+3
@@ -5383,6 +5383,9 @@ importers:
|
||||
'@n8n/api-types':
|
||||
specifier: workspace:*
|
||||
version: link:../../../@n8n/api-types
|
||||
'@n8n/i18n':
|
||||
specifier: workspace:*
|
||||
version: link:../i18n
|
||||
'@n8n/permissions':
|
||||
specifier: workspace:*
|
||||
version: link:../../../@n8n/permissions
|
||||
|
||||
Reference in New Issue
Block a user