From 702abd36313f99ca4fbdb9caa9c42012f143e9c0 Mon Sep 17 00:00:00 2001 From: Omar Ajoue Date: Thu, 10 Mar 2022 13:27:12 +0100 Subject: [PATCH 1/7] Added public url variable for emails --- packages/cli/config/index.ts | 6 ++++++ packages/cli/src/UserManagement/UserManagementHelper.ts | 3 ++- packages/cli/src/UserManagement/routes/passwordReset.ts | 5 ++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/cli/config/index.ts b/packages/cli/config/index.ts index ca0a978d3937e..8bd3c3fb0c1da 100644 --- a/packages/cli/config/index.ts +++ b/packages/cli/config/index.ts @@ -411,6 +411,12 @@ const config = convict({ env: 'N8N_SSL_CERT', doc: 'SSL Cert for HTTPS Protocol', }, + externalUrl: { + format: String, + default: '', + env: 'N8N_EXTERNAL_URL', + doc: 'Public URL where your instance can be reached. Used by emails sent from n8n.', + }, security: { excludeEndpoints: { diff --git a/packages/cli/src/UserManagement/UserManagementHelper.ts b/packages/cli/src/UserManagement/UserManagementHelper.ts index b2a1cae9e9923..cc5f4709634d8 100644 --- a/packages/cli/src/UserManagement/UserManagementHelper.ts +++ b/packages/cli/src/UserManagement/UserManagementHelper.ts @@ -55,7 +55,8 @@ export async function getInstanceOwner(): Promise { * Return the n8n instance base URL without trailing slash. */ export function getInstanceBaseUrl(): string { - const baseUrl = GenericHelpers.getBaseUrl(); + const externalUrl = config.get('externalUrl'); + const baseUrl = externalUrl || GenericHelpers.getBaseUrl(); return baseUrl.endsWith('/') ? baseUrl.slice(0, baseUrl.length - 1) : baseUrl; } diff --git a/packages/cli/src/UserManagement/routes/passwordReset.ts b/packages/cli/src/UserManagement/routes/passwordReset.ts index 7dbb630283d30..203c03358603f 100644 --- a/packages/cli/src/UserManagement/routes/passwordReset.ts +++ b/packages/cli/src/UserManagement/routes/passwordReset.ts @@ -11,11 +11,10 @@ import { LoggerProxy as Logger } from 'n8n-workflow'; import { Db, InternalHooksManager, ResponseHelper } from '../..'; import { N8nApp } from '../Interfaces'; -import { validatePassword } from '../UserManagementHelper'; +import { getInstanceBaseUrl, validatePassword } from '../UserManagementHelper'; import * as UserManagementMailer from '../email'; import type { PasswordResetRequest } from '../../requests'; import { issueCookie } from '../auth/jwt'; -import { getBaseUrl } from '../../GenericHelpers'; import config = require('../../../config'); export function passwordResetNamespace(this: N8nApp): void { @@ -73,7 +72,7 @@ export function passwordResetNamespace(this: N8nApp): void { await Db.collections.User!.update(id, { resetPasswordToken, resetPasswordTokenExpiration }); - const baseUrl = getBaseUrl(); + const baseUrl = getInstanceBaseUrl(); const url = new URL('/change-password', baseUrl); url.searchParams.append('userId', id); url.searchParams.append('token', resetPasswordToken); From caa51adc4832a1ed38ebbd7a3bf9c13b4917290d Mon Sep 17 00:00:00 2001 From: Omar Ajoue Date: Thu, 10 Mar 2022 13:32:57 +0100 Subject: [PATCH 2/7] Fixed base url for reset password - the current implementation overrides possibly existing path --- packages/cli/src/UserManagement/routes/passwordReset.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/UserManagement/routes/passwordReset.ts b/packages/cli/src/UserManagement/routes/passwordReset.ts index 203c03358603f..3930cb3041f60 100644 --- a/packages/cli/src/UserManagement/routes/passwordReset.ts +++ b/packages/cli/src/UserManagement/routes/passwordReset.ts @@ -73,7 +73,7 @@ export function passwordResetNamespace(this: N8nApp): void { await Db.collections.User!.update(id, { resetPasswordToken, resetPasswordTokenExpiration }); const baseUrl = getInstanceBaseUrl(); - const url = new URL('/change-password', baseUrl); + const url = new URL(`${baseUrl}/change-password`); url.searchParams.append('userId', id); url.searchParams.append('token', resetPasswordToken); From 15d311c8adfa9b34c2fa202f31c95a95d4b15b13 Mon Sep 17 00:00:00 2001 From: Omar Ajoue Date: Thu, 10 Mar 2022 14:41:33 +0100 Subject: [PATCH 3/7] Change variable name to editorUrl --- packages/cli/config/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/config/index.ts b/packages/cli/config/index.ts index 8bd3c3fb0c1da..c2d2740726b3e 100644 --- a/packages/cli/config/index.ts +++ b/packages/cli/config/index.ts @@ -411,10 +411,10 @@ const config = convict({ env: 'N8N_SSL_CERT', doc: 'SSL Cert for HTTPS Protocol', }, - externalUrl: { + editorUrl: { format: String, default: '', - env: 'N8N_EXTERNAL_URL', + env: 'N8N_EDITOR_URL', doc: 'Public URL where your instance can be reached. Used by emails sent from n8n.', }, From f3317f06ff27436bc329c9a6d3678b706c6b2dff Mon Sep 17 00:00:00 2001 From: Omar Ajoue Date: Thu, 10 Mar 2022 14:42:57 +0100 Subject: [PATCH 4/7] Using correct name editorUrl for emails --- packages/cli/src/UserManagement/UserManagementHelper.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/UserManagement/UserManagementHelper.ts b/packages/cli/src/UserManagement/UserManagementHelper.ts index cc5f4709634d8..4dcc48ebb9789 100644 --- a/packages/cli/src/UserManagement/UserManagementHelper.ts +++ b/packages/cli/src/UserManagement/UserManagementHelper.ts @@ -55,8 +55,8 @@ export async function getInstanceOwner(): Promise { * Return the n8n instance base URL without trailing slash. */ export function getInstanceBaseUrl(): string { - const externalUrl = config.get('externalUrl'); - const baseUrl = externalUrl || GenericHelpers.getBaseUrl(); + const editorUrl = config.get('editorUrl'); + const baseUrl = editorUrl || GenericHelpers.getBaseUrl(); return baseUrl.endsWith('/') ? baseUrl.slice(0, baseUrl.length - 1) : baseUrl; } From bfa919cf660c72816166d975d0f8cb2a3d0baf10 Mon Sep 17 00:00:00 2001 From: Omar Ajoue Date: Thu, 10 Mar 2022 14:45:11 +0100 Subject: [PATCH 5/7] Changed variable description --- packages/cli/config/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/config/index.ts b/packages/cli/config/index.ts index c2d2740726b3e..c5f900c25027f 100644 --- a/packages/cli/config/index.ts +++ b/packages/cli/config/index.ts @@ -415,7 +415,7 @@ const config = convict({ format: String, default: '', env: 'N8N_EDITOR_URL', - doc: 'Public URL where your instance can be reached. Used by emails sent from n8n.', + doc: 'Public URL where the editor is accessible. Also used for emails sent from n8n.', }, security: { From adc0f32c52784e77a42262ffcb39c776fda7bdb6 Mon Sep 17 00:00:00 2001 From: Omar Ajoue Date: Fri, 11 Mar 2022 11:43:49 +0100 Subject: [PATCH 6/7] Improved base url naming and appending path so it remains consistent --- packages/cli/config/index.ts | 6 +++--- packages/cli/src/Interfaces.ts | 1 + packages/cli/src/Server.ts | 3 ++- packages/cli/src/UserManagement/UserManagementHelper.ts | 5 ++--- packages/cli/src/UserManagement/routes/passwordReset.ts | 2 +- packages/cli/src/UserManagement/routes/users.ts | 4 ++-- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/cli/config/index.ts b/packages/cli/config/index.ts index c5f900c25027f..b6810bf9f6591 100644 --- a/packages/cli/config/index.ts +++ b/packages/cli/config/index.ts @@ -411,11 +411,11 @@ const config = convict({ env: 'N8N_SSL_CERT', doc: 'SSL Cert for HTTPS Protocol', }, - editorUrl: { + editorBaseUrl: { format: String, default: '', - env: 'N8N_EDITOR_URL', - doc: 'Public URL where the editor is accessible. Also used for emails sent from n8n.', + env: 'N8N_EDITOR_BASE_URL', + doc: 'Public URL where the editor is accessible; path will be concatenated to this base. Also used for emails sent from n8n.', }, security: { diff --git a/packages/cli/src/Interfaces.ts b/packages/cli/src/Interfaces.ts index 7d151093fac0d..ac8290140c7ef 100644 --- a/packages/cli/src/Interfaces.ts +++ b/packages/cli/src/Interfaces.ts @@ -446,6 +446,7 @@ export interface IN8nUISettings { }; timezone: string; urlBaseWebhook: string; + urlBaseEditor: string; versionCli: string; n8nMetadata?: { [key: string]: string | number | undefined; diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts index 667d8839b0e8c..57a986c370752 100644 --- a/packages/cli/src/Server.ts +++ b/packages/cli/src/Server.ts @@ -171,7 +171,7 @@ import { ExecutionEntity } from './databases/entities/ExecutionEntity'; import { SharedWorkflow } from './databases/entities/SharedWorkflow'; import { AUTH_COOKIE_NAME, RESPONSE_ERROR_MESSAGES } from './constants'; import { credentialsController } from './api/credentials.api'; -import { isEmailSetUp } from './UserManagement/UserManagementHelper'; +import { getInstanceBaseUrl, isEmailSetUp } from './UserManagement/UserManagementHelper'; require('body-parser-xml')(bodyParser); @@ -296,6 +296,7 @@ class App { maxExecutionTimeout: this.maxExecutionTimeout, timezone: this.timezone, urlBaseWebhook, + urlBaseEditor: getInstanceBaseUrl(), versionCli: '', oauthCallbackUrls: { oauth1: `${urlBaseWebhook}${this.restEndpoint}/oauth1-credential/callback`, diff --git a/packages/cli/src/UserManagement/UserManagementHelper.ts b/packages/cli/src/UserManagement/UserManagementHelper.ts index 4dcc48ebb9789..afa1814126f5f 100644 --- a/packages/cli/src/UserManagement/UserManagementHelper.ts +++ b/packages/cli/src/UserManagement/UserManagementHelper.ts @@ -55,9 +55,8 @@ export async function getInstanceOwner(): Promise { * Return the n8n instance base URL without trailing slash. */ export function getInstanceBaseUrl(): string { - const editorUrl = config.get('editorUrl'); - const baseUrl = editorUrl || GenericHelpers.getBaseUrl(); - return baseUrl.endsWith('/') ? baseUrl.slice(0, baseUrl.length - 1) : baseUrl; + const editorBaseUrl = config.get('editorBaseUrl'); + return editorBaseUrl ? editorBaseUrl + config.get('path') : GenericHelpers.getBaseUrl(); } export async function isInstanceOwnerSetup(): Promise { diff --git a/packages/cli/src/UserManagement/routes/passwordReset.ts b/packages/cli/src/UserManagement/routes/passwordReset.ts index 3930cb3041f60..72f9340a39630 100644 --- a/packages/cli/src/UserManagement/routes/passwordReset.ts +++ b/packages/cli/src/UserManagement/routes/passwordReset.ts @@ -73,7 +73,7 @@ export function passwordResetNamespace(this: N8nApp): void { await Db.collections.User!.update(id, { resetPasswordToken, resetPasswordTokenExpiration }); const baseUrl = getInstanceBaseUrl(); - const url = new URL(`${baseUrl}/change-password`); + const url = new URL(`${baseUrl}change-password`); url.searchParams.append('userId', id); url.searchParams.append('token', resetPasswordToken); diff --git a/packages/cli/src/UserManagement/routes/users.ts b/packages/cli/src/UserManagement/routes/users.ts index 8391c90e1491b..e442ef134151b 100644 --- a/packages/cli/src/UserManagement/routes/users.ts +++ b/packages/cli/src/UserManagement/routes/users.ts @@ -176,7 +176,7 @@ export function usersNamespace(this: N8nApp): void { const emailingResults = await Promise.all( usersPendingSetup.map(async ([email, id]) => { // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - const inviteAcceptUrl = `${baseUrl}/signup?inviterId=${req.user.id}&inviteeId=${id}`; + const inviteAcceptUrl = `${baseUrl}signup?inviterId=${req.user.id}&inviteeId=${id}`; const result = await mailer?.invite({ email, inviteAcceptUrl, @@ -512,7 +512,7 @@ export function usersNamespace(this: N8nApp): void { } const baseUrl = getInstanceBaseUrl(); - const inviteAcceptUrl = `${baseUrl}/signup?inviterId=${req.user.id}&inviteeId=${reinvitee.id}`; + const inviteAcceptUrl = `${baseUrl}signup?inviterId=${req.user.id}&inviteeId=${reinvitee.id}`; let mailer: UserManagementMailer.UserManagementMailer | undefined; try { From a8c935681650b3e6b05602ae69a9dee6125f8487 Mon Sep 17 00:00:00 2001 From: Omar Ajoue Date: Fri, 11 Mar 2022 15:00:27 +0100 Subject: [PATCH 7/7] Removed trailing slash from editor base url --- packages/cli/src/UserManagement/UserManagementHelper.ts | 3 ++- packages/cli/src/UserManagement/routes/passwordReset.ts | 2 +- packages/cli/src/UserManagement/routes/users.ts | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/UserManagement/UserManagementHelper.ts b/packages/cli/src/UserManagement/UserManagementHelper.ts index afa1814126f5f..e46278f63dd05 100644 --- a/packages/cli/src/UserManagement/UserManagementHelper.ts +++ b/packages/cli/src/UserManagement/UserManagementHelper.ts @@ -56,7 +56,8 @@ export async function getInstanceOwner(): Promise { */ export function getInstanceBaseUrl(): string { const editorBaseUrl = config.get('editorBaseUrl'); - return editorBaseUrl ? editorBaseUrl + config.get('path') : GenericHelpers.getBaseUrl(); + const baseUrl = editorBaseUrl ? editorBaseUrl + config.get('path') : GenericHelpers.getBaseUrl(); + return baseUrl.endsWith('/') ? baseUrl.slice(0, baseUrl.length - 1) : baseUrl; } export async function isInstanceOwnerSetup(): Promise { diff --git a/packages/cli/src/UserManagement/routes/passwordReset.ts b/packages/cli/src/UserManagement/routes/passwordReset.ts index 72f9340a39630..3930cb3041f60 100644 --- a/packages/cli/src/UserManagement/routes/passwordReset.ts +++ b/packages/cli/src/UserManagement/routes/passwordReset.ts @@ -73,7 +73,7 @@ export function passwordResetNamespace(this: N8nApp): void { await Db.collections.User!.update(id, { resetPasswordToken, resetPasswordTokenExpiration }); const baseUrl = getInstanceBaseUrl(); - const url = new URL(`${baseUrl}change-password`); + const url = new URL(`${baseUrl}/change-password`); url.searchParams.append('userId', id); url.searchParams.append('token', resetPasswordToken); diff --git a/packages/cli/src/UserManagement/routes/users.ts b/packages/cli/src/UserManagement/routes/users.ts index e442ef134151b..8391c90e1491b 100644 --- a/packages/cli/src/UserManagement/routes/users.ts +++ b/packages/cli/src/UserManagement/routes/users.ts @@ -176,7 +176,7 @@ export function usersNamespace(this: N8nApp): void { const emailingResults = await Promise.all( usersPendingSetup.map(async ([email, id]) => { // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - const inviteAcceptUrl = `${baseUrl}signup?inviterId=${req.user.id}&inviteeId=${id}`; + const inviteAcceptUrl = `${baseUrl}/signup?inviterId=${req.user.id}&inviteeId=${id}`; const result = await mailer?.invite({ email, inviteAcceptUrl, @@ -512,7 +512,7 @@ export function usersNamespace(this: N8nApp): void { } const baseUrl = getInstanceBaseUrl(); - const inviteAcceptUrl = `${baseUrl}signup?inviterId=${req.user.id}&inviteeId=${reinvitee.id}`; + const inviteAcceptUrl = `${baseUrl}/signup?inviterId=${req.user.id}&inviteeId=${reinvitee.id}`; let mailer: UserManagementMailer.UserManagementMailer | undefined; try {