diff --git a/packages/cli/src/GenericHelpers.ts b/packages/cli/src/GenericHelpers.ts index 4645535332e1e..b37d395882505 100644 --- a/packages/cli/src/GenericHelpers.ts +++ b/packages/cli/src/GenericHelpers.ts @@ -1,6 +1,5 @@ import type express from 'express'; import { validate } from 'class-validator'; -import config from '@/config'; import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; import type { CredentialsEntity } from '@db/entities/CredentialsEntity'; import type { TagEntity } from '@db/entities/TagEntity'; @@ -8,21 +7,6 @@ import type { User } from '@db/entities/User'; import type { UserUpdatePayload } from '@/requests'; import { BadRequestError } from './errors/response-errors/bad-request.error'; -/** - * Returns the base URL n8n is reachable from - */ -export function getBaseUrl(): string { - const protocol = config.getEnv('protocol'); - const host = config.getEnv('host'); - const port = config.getEnv('port'); - const path = config.getEnv('path'); - - if ((protocol === 'http' && port === 80) || (protocol === 'https' && port === 443)) { - return `${protocol}://${host}${path}`; - } - return `${protocol}://${host}:${port}${path}`; -} - /** * Returns the session id if one is set */ diff --git a/packages/cli/src/PublicApi/index.ts b/packages/cli/src/PublicApi/index.ts index 8a88a51e073d8..d4cb53b26a6f2 100644 --- a/packages/cli/src/PublicApi/index.ts +++ b/packages/cli/src/PublicApi/index.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ +import { Container } from 'typedi'; import type { Router } from 'express'; import express from 'express'; import fs from 'fs/promises'; @@ -11,11 +12,11 @@ import type { OpenAPIV3 } from 'openapi-types'; import type { JsonObject } from 'swagger-ui-express'; import config from '@/config'; -import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper'; -import { Container } from 'typedi'; + import { InternalHooks } from '@/InternalHooks'; import { License } from '@/License'; import { UserRepository } from '@db/repositories/user.repository'; +import { UrlService } from '@/services/url.service'; async function createApiRouter( version: string, @@ -29,7 +30,7 @@ async function createApiRouter( // from the Swagger UI swaggerDocument.server = [ { - url: `${getInstanceBaseUrl()}/${publicApiEndpoint}/${version}}`, + url: `${Container.get(UrlService).getInstanceBaseUrl()}/${publicApiEndpoint}/${version}}`, }, ]; const apiController = express.Router(); diff --git a/packages/cli/src/UserManagement/UserManagementHelper.ts b/packages/cli/src/UserManagement/UserManagementHelper.ts index 2a1cdd38fdf39..548719fdc0d80 100644 --- a/packages/cli/src/UserManagement/UserManagementHelper.ts +++ b/packages/cli/src/UserManagement/UserManagementHelper.ts @@ -1,30 +1,15 @@ import { In } from 'typeorm'; import { Container } from 'typedi'; +import type { Scope } from '@n8n/permissions'; import type { WhereClause } from '@/Interfaces'; import type { User } from '@db/entities/User'; -import config from '@/config'; import { License } from '@/License'; -import { getWebhookBaseUrl } from '@/WebhookHelpers'; -import type { Scope } from '@n8n/permissions'; export function isSharingEnabled(): boolean { return Container.get(License).isSharingEnabled(); } -/** - * Return the n8n instance base URL without trailing slash. - */ -export function getInstanceBaseUrl(): string { - const n8nBaseUrl = config.getEnv('editorBaseUrl') || getWebhookBaseUrl(); - - return n8nBaseUrl.endsWith('/') ? n8nBaseUrl.slice(0, n8nBaseUrl.length - 1) : n8nBaseUrl; -} - -export function generateUserInviteUrl(inviterId: string, inviteeId: string): string { - return `${getInstanceBaseUrl()}/signup?inviterId=${inviterId}&inviteeId=${inviteeId}`; -} - // return the difference between two arrays export function rightDiff( [arr1, keyExtractor1]: [T1[], (item: T1) => string], diff --git a/packages/cli/src/WebhookHelpers.ts b/packages/cli/src/WebhookHelpers.ts index f218ec11c1b7a..f86b90621ea5a 100644 --- a/packages/cli/src/WebhookHelpers.ts +++ b/packages/cli/src/WebhookHelpers.ts @@ -49,7 +49,6 @@ import type { WebhookCORSRequest, WebhookRequest, } from '@/Interfaces'; -import * as GenericHelpers from '@/GenericHelpers'; import * as ResponseHelper from '@/ResponseHelper'; import * as WorkflowHelpers from '@/WorkflowHelpers'; import { WorkflowRunner } from '@/WorkflowRunner'; @@ -820,14 +819,3 @@ export async function executeWebhook( return; } } - -/** - * Returns the base URL of the webhooks - */ -export function getWebhookBaseUrl() { - let urlBaseWebhook = process.env.WEBHOOK_URL ?? GenericHelpers.getBaseUrl(); - if (!urlBaseWebhook.endsWith('/')) { - urlBaseWebhook += '/'; - } - return urlBaseWebhook; -} diff --git a/packages/cli/src/WorkflowExecuteAdditionalData.ts b/packages/cli/src/WorkflowExecuteAdditionalData.ts index e81d97098273f..cdb809a83ce03 100644 --- a/packages/cli/src/WorkflowExecuteAdditionalData.ts +++ b/packages/cli/src/WorkflowExecuteAdditionalData.ts @@ -48,7 +48,6 @@ import type { } from '@/Interfaces'; import { NodeTypes } from '@/NodeTypes'; import { Push } from '@/push'; -import * as WebhookHelpers from '@/WebhookHelpers'; import * as WorkflowHelpers from '@/WorkflowHelpers'; import { findSubworkflowStart, isWorkflowIdValid } from '@/utils'; import { PermissionChecker } from './UserManagement/PermissionChecker'; @@ -68,6 +67,7 @@ import { Logger } from './Logger'; import { saveExecutionProgress } from './executionLifecycleHooks/saveExecutionProgress'; import { WorkflowStaticDataService } from './workflows/workflowStaticData.service'; import { WorkflowRepository } from './databases/repositories/workflow.repository'; +import { UrlService } from './services/url.service'; const ERROR_TRIGGER_TYPE = config.getEnv('nodes.errorTriggerType'); @@ -133,7 +133,7 @@ export function executeErrorWorkflow( // Check if there was an error and if so if an errorWorkflow or a trigger is set let pastExecutionUrl: string | undefined; if (executionId !== undefined) { - pastExecutionUrl = `${WebhookHelpers.getWebhookBaseUrl()}workflow/${ + pastExecutionUrl = `${Container.get(UrlService).getWebhookBaseUrl()}workflow/${ workflowData.id }/executions/${executionId}`; } @@ -965,7 +965,7 @@ export async function getBase( currentNodeParameters?: INodeParameters, executionTimeoutTimestamp?: number, ): Promise { - const urlBaseWebhook = WebhookHelpers.getWebhookBaseUrl(); + const urlBaseWebhook = Container.get(UrlService).getWebhookBaseUrl(); const formWaitingBaseUrl = urlBaseWebhook + config.getEnv('endpoints.formWaiting'); diff --git a/packages/cli/src/commands/start.ts b/packages/cli/src/commands/start.ts index be9039fd6b4ad..a2d674d9adabb 100644 --- a/packages/cli/src/commands/start.ts +++ b/packages/cli/src/commands/start.ts @@ -15,7 +15,6 @@ import config from '@/config'; import { ActiveExecutions } from '@/ActiveExecutions'; import { ActiveWorkflowRunner } from '@/ActiveWorkflowRunner'; -import * as GenericHelpers from '@/GenericHelpers'; import { Server } from '@/Server'; import { EDITOR_UI_DIST_DIR, LICENSE_FEATURES } from '@/constants'; import { eventBus } from '@/eventbus'; @@ -27,6 +26,7 @@ import { SingleMainSetup } from '@/services/orchestration/main/SingleMainSetup'; import { OrchestrationHandlerMainService } from '@/services/orchestration/main/orchestration.handler.main.service'; import { PruningService } from '@/services/pruning.service'; import { MultiMainSetup } from '@/services/orchestration/main/MultiMainSetup.ee'; +import { UrlService } from '@/services/url.service'; import { SettingsRepository } from '@db/repositories/settings.repository'; import { ExecutionRepository } from '@db/repositories/execution.repository'; import { FeatureNotLicensedError } from '@/errors/feature-not-licensed.error'; @@ -77,7 +77,7 @@ export class Start extends BaseCommand { * Opens the UI in browser */ private openBrowser() { - const editorUrl = GenericHelpers.getBaseUrl(); + const editorUrl = Container.get(UrlService).baseUrl; // eslint-disable-next-line @typescript-eslint/no-unused-vars open(editorUrl, { wait: true }).catch((error: Error) => { @@ -321,7 +321,7 @@ export class Start extends BaseCommand { // Start to get active workflows and run their triggers await this.activeWorkflowRunner.init(); - const editorUrl = GenericHelpers.getBaseUrl(); + const editorUrl = Container.get(UrlService).baseUrl; this.log(`\nEditor is now accessible via:\n${editorUrl}`); // Allow to open n8n editor by pressing "o" diff --git a/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts b/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts index 9229c3aaa47d0..185a9afa015cf 100644 --- a/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts +++ b/packages/cli/src/controllers/oauth/abstractOAuth.controller.ts @@ -7,13 +7,13 @@ import type { User } from '@db/entities/User'; import { CredentialsRepository } from '@db/repositories/credentials.repository'; import { SharedCredentialsRepository } from '@db/repositories/sharedCredentials.repository'; import type { ICredentialsDb } from '@/Interfaces'; -import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper'; import type { OAuthRequest } from '@/requests'; import { RESPONSE_ERROR_MESSAGES } from '@/constants'; import { CredentialsHelper } from '@/CredentialsHelper'; import * as WorkflowExecuteAdditionalData from '@/WorkflowExecuteAdditionalData'; import { Logger } from '@/Logger'; import { ExternalHooks } from '@/ExternalHooks'; +import { UrlService } from '@/services/url.service'; import { BadRequestError } from '@/errors/response-errors/bad-request.error'; import { NotFoundError } from '@/errors/response-errors/not-found.error'; @@ -27,10 +27,11 @@ export abstract class AbstractOAuthController { private readonly credentialsHelper: CredentialsHelper, private readonly credentialsRepository: CredentialsRepository, private readonly sharedCredentialsRepository: SharedCredentialsRepository, + private readonly urlService: UrlService, ) {} get baseUrl() { - const restUrl = `${getInstanceBaseUrl()}/${config.getEnv('endpoints.rest')}`; + const restUrl = `${this.urlService.getInstanceBaseUrl()}/${config.getEnv('endpoints.rest')}`; return `${restUrl}/oauth${this.oauthVersion}-credential`; } diff --git a/packages/cli/src/controllers/passwordReset.controller.ts b/packages/cli/src/controllers/passwordReset.controller.ts index 06b1dd250c2d7..dce0338e2e0c5 100644 --- a/packages/cli/src/controllers/passwordReset.controller.ts +++ b/packages/cli/src/controllers/passwordReset.controller.ts @@ -5,7 +5,6 @@ import { IsNull, Not } from 'typeorm'; import validator from 'validator'; import { Get, Post, RestController } from '@/decorators'; -import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper'; import { PasswordUtility } from '@/services/password.utility'; import { UserManagementMailer } from '@/UserManagement/email'; import { PasswordResetRequest } from '@/requests'; @@ -19,6 +18,7 @@ import { MfaService } from '@/Mfa/mfa.service'; import { Logger } from '@/Logger'; import { ExternalHooks } from '@/ExternalHooks'; import { InternalHooks } from '@/InternalHooks'; +import { UrlService } from '@/services/url.service'; import { InternalServerError } from '@/errors/response-errors/internal-server.error'; import { BadRequestError } from '@/errors/response-errors/bad-request.error'; import { UnauthorizedError } from '@/errors/response-errors/unauthorized.error'; @@ -41,6 +41,7 @@ export class PasswordResetController { private readonly mailer: UserManagementMailer, private readonly userService: UserService, private readonly mfaService: MfaService, + private readonly urlService: UrlService, private readonly license: License, private readonly passwordUtility: PasswordUtility, ) {} @@ -130,7 +131,7 @@ export class PasswordResetController { firstName, lastName, passwordResetUrl: url, - domain: getInstanceBaseUrl(), + domain: this.urlService.getInstanceBaseUrl(), }); } catch (error) { void this.internalHooks.onEmailFailed({ diff --git a/packages/cli/src/environments/variables/enviromentHelpers.ts b/packages/cli/src/environments/variables/environmentHelpers.ts similarity index 100% rename from packages/cli/src/environments/variables/enviromentHelpers.ts rename to packages/cli/src/environments/variables/environmentHelpers.ts diff --git a/packages/cli/src/environments/variables/variables.service.ee.ts b/packages/cli/src/environments/variables/variables.service.ee.ts index a962896de4631..96060e7a4ad5d 100644 --- a/packages/cli/src/environments/variables/variables.service.ee.ts +++ b/packages/cli/src/environments/variables/variables.service.ee.ts @@ -2,7 +2,7 @@ import { Container, Service } from 'typedi'; import type { Variables } from '@db/entities/Variables'; import { InternalHooks } from '@/InternalHooks'; import { generateNanoId } from '@db/utils/generators'; -import { canCreateNewVariable } from './enviromentHelpers'; +import { canCreateNewVariable } from './environmentHelpers'; import { CacheService } from '@/services/cache.service'; import { VariablesRepository } from '@db/repositories/variables.repository'; import type { DeepPartial } from 'typeorm'; diff --git a/packages/cli/src/services/frontend.service.ts b/packages/cli/src/services/frontend.service.ts index fe7d6141ba3d0..cac41c7fd77fb 100644 --- a/packages/cli/src/services/frontend.service.ts +++ b/packages/cli/src/services/frontend.service.ts @@ -12,18 +12,16 @@ import type { } from 'n8n-workflow'; import { InstanceSettings } from 'n8n-core'; +import config from '@/config'; import { LICENSE_FEATURES } from '@/constants'; import { CredentialsOverwrites } from '@/CredentialsOverwrites'; import { CredentialTypes } from '@/CredentialTypes'; import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials'; import { License } from '@/License'; -import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper'; -import * as WebhookHelpers from '@/WebhookHelpers'; -import config from '@/config'; import { getCurrentAuthenticationMethod } from '@/sso/ssoHelpers'; import { getLdapLoginLabel } from '@/Ldap/helpers'; import { getSamlLoginLabel } from '@/sso/saml/samlHelpers'; -import { getVariablesLimit } from '@/environments/variables/enviromentHelpers'; +import { getVariablesLimit } from '@/environments/variables/environmentHelpers'; import { getWorkflowHistoryLicensePruneTime, getWorkflowHistoryPruneTime, @@ -31,6 +29,7 @@ import { import { UserManagementMailer } from '@/UserManagement/email'; import type { CommunityPackagesService } from '@/services/communityPackages.service'; import { Logger } from '@/Logger'; +import { UrlService } from './url.service'; @Service() export class FrontendService { @@ -46,6 +45,7 @@ export class FrontendService { private readonly license: License, private readonly mailer: UserManagementMailer, private readonly instanceSettings: InstanceSettings, + private readonly urlService: UrlService, ) { loadNodesAndCredentials.addPostProcessor(async () => this.generateTypes()); void this.generateTypes(); @@ -61,7 +61,7 @@ export class FrontendService { } private initSettings() { - const instanceBaseUrl = getInstanceBaseUrl(); + const instanceBaseUrl = this.urlService.getInstanceBaseUrl(); const restEndpoint = config.getEnv('endpoints.rest'); const telemetrySettings: ITelemetrySettings = { @@ -93,7 +93,7 @@ export class FrontendService { maxExecutionTimeout: config.getEnv('executions.maxTimeout'), workflowCallerPolicyDefaultOption: config.getEnv('workflows.callerPolicyDefaultOption'), timezone: config.getEnv('generic.timezone'), - urlBaseWebhook: WebhookHelpers.getWebhookBaseUrl(), + urlBaseWebhook: this.urlService.getWebhookBaseUrl(), urlBaseEditor: instanceBaseUrl, versionCli: '', releaseChannel: config.getEnv('generic.releaseChannel'), @@ -222,8 +222,8 @@ export class FrontendService { const restEndpoint = config.getEnv('endpoints.rest'); // Update all urls, in case `WEBHOOK_URL` was updated by `--tunnel` - const instanceBaseUrl = getInstanceBaseUrl(); - this.settings.urlBaseWebhook = WebhookHelpers.getWebhookBaseUrl(); + const instanceBaseUrl = this.urlService.getInstanceBaseUrl(); + this.settings.urlBaseWebhook = this.urlService.getWebhookBaseUrl(); this.settings.urlBaseEditor = instanceBaseUrl; this.settings.oauthCallbackUrls = { oauth1: `${instanceBaseUrl}/${restEndpoint}/oauth1-credential/callback`, diff --git a/packages/cli/src/services/url.service.ts b/packages/cli/src/services/url.service.ts new file mode 100644 index 0000000000000..b1ef737c2f43e --- /dev/null +++ b/packages/cli/src/services/url.service.ts @@ -0,0 +1,40 @@ +import { Service } from 'typedi'; +import config from '@/config'; + +@Service() +export class UrlService { + /** Returns the base URL n8n is reachable from */ + readonly baseUrl: string; + + constructor() { + this.baseUrl = this.generateBaseUrl(); + } + + /** Returns the base URL of the webhooks */ + getWebhookBaseUrl() { + let urlBaseWebhook = process.env.WEBHOOK_URL ?? this.baseUrl; + if (!urlBaseWebhook.endsWith('/')) { + urlBaseWebhook += '/'; + } + return urlBaseWebhook; + } + + /** Return the n8n instance base URL without trailing slash */ + getInstanceBaseUrl(): string { + const n8nBaseUrl = config.getEnv('editorBaseUrl') || this.getWebhookBaseUrl(); + + return n8nBaseUrl.endsWith('/') ? n8nBaseUrl.slice(0, n8nBaseUrl.length - 1) : n8nBaseUrl; + } + + private generateBaseUrl(): string { + const protocol = config.getEnv('protocol'); + const host = config.getEnv('host'); + const port = config.getEnv('port'); + const path = config.getEnv('path'); + + if ((protocol === 'http' && port === 80) || (protocol === 'https' && port === 443)) { + return `${protocol}://${host}${path}`; + } + return `${protocol}://${host}:${port}${path}`; + } +} diff --git a/packages/cli/src/services/user.service.ts b/packages/cli/src/services/user.service.ts index 41037f26c27c1..cae8c40c3c911 100644 --- a/packages/cli/src/services/user.service.ts +++ b/packages/cli/src/services/user.service.ts @@ -1,10 +1,9 @@ -import Container, { Service } from 'typedi'; +import { Container, Service } from 'typedi'; import type { EntityManager, FindManyOptions, FindOneOptions, FindOptionsWhere } from 'typeorm'; import { In } from 'typeorm'; import { User } from '@db/entities/User'; import type { IUserSettings } from 'n8n-workflow'; import { UserRepository } from '@db/repositories/user.repository'; -import { generateUserInviteUrl, getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper'; import type { PublicUser } from '@/Interfaces'; import type { PostHogClient } from '@/posthog'; import { type JwtPayload, JwtService } from './jwt.service'; @@ -14,6 +13,7 @@ import { createPasswordSha } from '@/auth/jwt'; import { UserManagementMailer } from '@/UserManagement/email'; import { InternalHooks } from '@/InternalHooks'; import { RoleService } from '@/services/role.service'; +import { UrlService } from '@/services/url.service'; import { ApplicationError, ErrorReporterProxy as ErrorReporter } from 'n8n-workflow'; import type { UserRequest } from '@/requests'; import { InternalServerError } from '@/errors/response-errors/internal-server.error'; @@ -26,6 +26,7 @@ export class UserService { private readonly jwtService: JwtService, private readonly mailer: UserManagementMailer, private readonly roleService: RoleService, + private readonly urlService: UrlService, ) {} async findOne(options: FindOneOptions) { @@ -78,7 +79,7 @@ export class UserService { } generatePasswordResetUrl(user: User) { - const instanceBaseUrl = getInstanceBaseUrl(); + const instanceBaseUrl = this.urlService.getInstanceBaseUrl(); const url = new URL(`${instanceBaseUrl}/change-password`); url.searchParams.append('token', this.generatePasswordResetToken(user)); @@ -161,7 +162,7 @@ export class UserService { } private addInviteUrl(inviterId: string, invitee: PublicUser) { - const url = new URL(getInstanceBaseUrl()); + const url = new URL(this.urlService.getInstanceBaseUrl()); url.pathname = '/signup'; url.searchParams.set('inviterId', inviterId); url.searchParams.set('inviteeId', invitee.id); @@ -193,11 +194,11 @@ export class UserService { toInviteUsers: { [key: string]: string }, role: 'member' | 'admin', ) { - const domain = getInstanceBaseUrl(); + const domain = this.urlService.getInstanceBaseUrl(); return Promise.all( Object.entries(toInviteUsers).map(async ([email, id]) => { - const inviteAcceptUrl = generateUserInviteUrl(owner.id, id); + const inviteAcceptUrl = `${domain}/signup?inviterId=${owner.id}&inviteeId=${id}`; const invitedUser: UserRequest.InviteResponse = { user: { id, diff --git a/packages/cli/src/sso/saml/routes/saml.controller.ee.ts b/packages/cli/src/sso/saml/routes/saml.controller.ee.ts index 85958e83a6da8..eeaf74bf145f5 100644 --- a/packages/cli/src/sso/saml/routes/saml.controller.ee.ts +++ b/packages/cli/src/sso/saml/routes/saml.controller.ee.ts @@ -1,6 +1,5 @@ import express from 'express'; import { Container, Service } from 'typedi'; -import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper'; import { Authorized, Get, @@ -35,12 +34,16 @@ import url from 'url'; import querystring from 'querystring'; import { BadRequestError } from '@/errors/response-errors/bad-request.error'; import { AuthError } from '@/errors/response-errors/auth.error'; +import { UrlService } from '@/services/url.service'; @Service() @Authorized() @RestController('/sso/saml') export class SamlController { - constructor(private samlService: SamlService) {} + constructor( + private readonly samlService: SamlService, + private readonly urlService: UrlService, + ) {} @NoAuthRequired() @Get(SamlUrls.metadata) @@ -147,10 +150,10 @@ export class SamlController { if (isSamlLicensedAndEnabled()) { await issueCookie(res, loginResult.authenticatedUser); if (loginResult.onboardingRequired) { - return res.redirect(getInstanceBaseUrl() + SamlUrls.samlOnboarding); + return res.redirect(this.urlService.getInstanceBaseUrl() + SamlUrls.samlOnboarding); } else { const redirectUrl = req.body?.RelayState ?? SamlUrls.defaultRedirect; - return res.redirect(getInstanceBaseUrl() + redirectUrl); + return res.redirect(this.urlService.getInstanceBaseUrl() + redirectUrl); } } else { return res.status(202).send(loginResult.attributes); diff --git a/packages/cli/src/sso/saml/saml.service.ee.ts b/packages/cli/src/sso/saml/saml.service.ee.ts index 20ce62749ef7b..2a20c25c7d5a2 100644 --- a/packages/cli/src/sso/saml/saml.service.ee.ts +++ b/packages/cli/src/sso/saml/saml.service.ee.ts @@ -24,12 +24,12 @@ import axios from 'axios'; import https from 'https'; import type { SamlLoginBinding } from './types'; import { validateMetadata, validateResponse } from './samlValidator'; -import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper'; import { Logger } from '@/Logger'; import { UserRepository } from '@db/repositories/user.repository'; import { SettingsRepository } from '@db/repositories/settings.repository'; import { BadRequestError } from '@/errors/response-errors/bad-request.error'; import { AuthError } from '@/errors/response-errors/auth.error'; +import { UrlService } from '@/services/url.service'; @Service() export class SamlService { @@ -55,7 +55,7 @@ export class SamlService { loginLabel: 'SAML', wantAssertionsSigned: true, wantMessageSigned: true, - relayState: getInstanceBaseUrl(), + relayState: this.urlService.getInstanceBaseUrl(), signatureConfig: { prefix: 'ds', location: { @@ -73,7 +73,10 @@ export class SamlService { }; } - constructor(private readonly logger: Logger) {} + constructor( + private readonly logger: Logger, + private readonly urlService: UrlService, + ) {} async init(): Promise { // load preferences first but do not apply so as to not load samlify unnecessarily @@ -143,14 +146,14 @@ export class SamlService { private getRedirectLoginRequestUrl(relayState?: string): BindingContext { const sp = this.getServiceProviderInstance(); - sp.entitySetting.relayState = relayState ?? getInstanceBaseUrl(); + sp.entitySetting.relayState = relayState ?? this.urlService.getInstanceBaseUrl(); const loginRequest = sp.createLoginRequest(this.getIdentityProviderInstance(), 'redirect'); return loginRequest; } private getPostLoginRequestUrl(relayState?: string): PostBindingContext { const sp = this.getServiceProviderInstance(); - sp.entitySetting.relayState = relayState ?? getInstanceBaseUrl(); + sp.entitySetting.relayState = relayState ?? this.urlService.getInstanceBaseUrl(); const loginRequest = sp.createLoginRequest( this.getIdentityProviderInstance(), 'post', diff --git a/packages/cli/src/sso/saml/serviceProvider.ee.ts b/packages/cli/src/sso/saml/serviceProvider.ee.ts index fa1fde62832d7..372d277b30386 100644 --- a/packages/cli/src/sso/saml/serviceProvider.ee.ts +++ b/packages/cli/src/sso/saml/serviceProvider.ee.ts @@ -1,21 +1,22 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper'; +import { Container } from 'typedi'; import type { ServiceProviderInstance } from 'samlify'; +import { UrlService } from '@/services/url.service'; import { SamlUrls } from './constants'; import type { SamlPreferences } from './types/samlPreferences'; let serviceProviderInstance: ServiceProviderInstance | undefined; export function getServiceProviderEntityId(): string { - return getInstanceBaseUrl() + SamlUrls.restMetadata; + return Container.get(UrlService).getInstanceBaseUrl() + SamlUrls.restMetadata; } export function getServiceProviderReturnUrl(): string { - return getInstanceBaseUrl() + SamlUrls.restAcs; + return Container.get(UrlService).getInstanceBaseUrl() + SamlUrls.restAcs; } export function getServiceProviderConfigTestReturnUrl(): string { - return getInstanceBaseUrl() + SamlUrls.configTestReturn; + return Container.get(UrlService).getInstanceBaseUrl() + SamlUrls.configTestReturn; } // TODO:SAML: make these configurable for the end user