diff --git a/frontend/ee/components/LoginPage/GoogleSSOLoginButton.jsx b/frontend/ee/components/LoginPage/GoogleSSOLoginButton.jsx index 862dd27c78..bd344ac31e 100644 --- a/frontend/ee/components/LoginPage/GoogleSSOLoginButton.jsx +++ b/frontend/ee/components/LoginPage/GoogleSSOLoginButton.jsx @@ -14,7 +14,9 @@ export default function GoogleSSOLoginButton(props) { e.preventDefault(); const { client_id } = props.configs; const authUrl = buildURLWithQuery('https://accounts.google.com/o/oauth2/auth', { - redirect_uri: `${window.public_config?.TOOLJET_HOST}/sso/google${props.configId ? `/${props.configId}` : ''}`, + redirect_uri: `${window.public_config?.TOOLJET_HOST}${window.public_config?.SUB_PATH ?? '/'}sso/google${ + props.configId ? `/${props.configId}` : '' + }`, response_type: 'id_token', scope: 'email profile', client_id, diff --git a/frontend/src/Editor/ManageAppUsers.jsx b/frontend/src/Editor/ManageAppUsers.jsx index bb977ea4e8..fb8e7db03f 100644 --- a/frontend/src/Editor/ManageAppUsers.jsx +++ b/frontend/src/Editor/ManageAppUsers.jsx @@ -9,6 +9,7 @@ import Textarea from '@/_ui/Textarea'; import { withTranslation } from 'react-i18next'; import { Link } from 'react-router-dom'; import { getPrivateRoute } from '@/_helpers/routes'; +import { getSubpath } from '@/_helpers/utils'; class ManageAppUsersComponent extends React.Component { constructor(props) { @@ -133,7 +134,7 @@ class ManageAppUsersComponent extends React.Component { render() { const { isLoading, app, slugError, isSlugVerificationInProgress } = this.state; const appId = app.id; - const appLink = `${window.public_config?.TOOLJET_HOST}/applications/`; + const appLink = `${window.public_config?.TOOLJET_HOST}${getSubpath() ? getSubpath() : ''}/applications/`; const shareableLink = appLink + (this.props.slug || appId); const slugButtonClass = isSlugVerificationInProgress ? '' : slugError !== null ? 'is-invalid' : 'is-valid'; const embeddableLink = ``; diff --git a/frontend/src/HomePage/AppCard.jsx b/frontend/src/HomePage/AppCard.jsx index cf2f1a75c5..b0612991e5 100644 --- a/frontend/src/HomePage/AppCard.jsx +++ b/frontend/src/HomePage/AppCard.jsx @@ -12,6 +12,7 @@ import SolidIcon from '@/_ui/Icon/SolidIcons'; import BulkIcon from '@/_ui/Icon/BulkIcons'; import { getPrivateRoute } from '@/_helpers/routes'; +import { getSubpath } from '@/_helpers/utils'; const { defaultIcon } = configs; export default function AppCard({ @@ -149,7 +150,9 @@ export default function AppCard({ )} onClick={() => { if (app?.current_version_id) { - window.open(urlJoin(window.public_config?.TOOLJET_HOST, `/applications/${app.slug}`)); + window.open( + urlJoin(window.public_config?.TOOLJET_HOST, getSubpath() ?? '', `/applications/${app.slug}`) + ); } else { navigate(app?.current_version_id ? `/applications/${app.slug}` : ''); } diff --git a/frontend/src/ManageOrgUsers/ManageOrgUsers.jsx b/frontend/src/ManageOrgUsers/ManageOrgUsers.jsx index 7a32d9e93a..b6f5013bcf 100644 --- a/frontend/src/ManageOrgUsers/ManageOrgUsers.jsx +++ b/frontend/src/ManageOrgUsers/ManageOrgUsers.jsx @@ -205,11 +205,13 @@ class ManageOrgUsersComponent extends React.Component { if (user.account_setup_token) { return urlJoin( window.public_config?.TOOLJET_HOST, + window.public_config?.SUB_PATH ?? '', `/invitations/${user.account_setup_token}/workspaces/${user.invitation_token}?oid=${authenticationService?.currentSessionValue.current_organization_id}` ); } return urlJoin( window.public_config?.TOOLJET_HOST, + window.public_config?.SUB_PATH ?? '', `/organization-invitations/${user.invitation_token}?oid=${authenticationService?.currentSessionValue.current_organization_id}` ); }; diff --git a/frontend/src/ManageSSO/GeneralSettings.jsx b/frontend/src/ManageSSO/GeneralSettings.jsx index f8d2234785..eaaf53e73c 100644 --- a/frontend/src/ManageSSO/GeneralSettings.jsx +++ b/frontend/src/ManageSSO/GeneralSettings.jsx @@ -166,7 +166,9 @@ export function GeneralSettings({ settings, updateData, instanceSettings, darkMo

- {`${window.public_config?.TOOLJET_HOST}/login/${authenticationService?.currentSessionValue?.current_organization_id}`} + {`${window.public_config?.TOOLJET_HOST}${ + window.public_config?.SUB_PATH ? window.public_config?.SUB_PATH : '/' + }login/${authenticationService?.currentSessionValue?.current_organization_id}`}

copyFunction('login-url')} />
diff --git a/frontend/src/ManageSSO/Git.jsx b/frontend/src/ManageSSO/Git.jsx index 8a18d0d0ce..9706f245c4 100644 --- a/frontend/src/ManageSSO/Git.jsx +++ b/frontend/src/ManageSSO/Git.jsx @@ -152,10 +152,9 @@ export function Git({ settings, updateData }) { {t('header.organization.menus.manageSSO.github.redirectUrl', 'Redirect URL')}
-

{`${window.public_config?.TOOLJET_HOST}/sso/git/${configId}`}

+

{`${window.public_config?.TOOLJET_HOST}${ + window.public_config?.SUB_PATH ? window.public_config?.SUB_PATH : '/' + }sso/git/${configId}`}

copyFunction('redirect-url')} />
diff --git a/frontend/src/ManageSSO/Google.jsx b/frontend/src/ManageSSO/Google.jsx index b8e83327ac..ccda44e98a 100644 --- a/frontend/src/ManageSSO/Google.jsx +++ b/frontend/src/ManageSSO/Google.jsx @@ -113,10 +113,9 @@ export function Google({ settings, updateData }) { {t('header.organization.menus.manageSSO.google.redirectUrl', 'Redirect URL')}
-

{`${window.public_config?.TOOLJET_HOST}/sso/google/${configId}`}

+

{`${window.public_config?.TOOLJET_HOST}${ + window.public_config?.SUB_PATH ? window.public_config?.SUB_PATH : '/' + }sso/google/${configId}`}

copyFunction('redirect-url')} />
diff --git a/server/ee/services/oauth/oauth.service.ts b/server/ee/services/oauth/oauth.service.ts index df7c1bef55..415c498a02 100644 --- a/server/ee/services/oauth/oauth.service.ts +++ b/server/ee/services/oauth/oauth.service.ts @@ -17,7 +17,7 @@ import { URL_SSO_SOURCE, WORKSPACE_USER_STATUS, } from 'src/helpers/user_lifecycle'; -import { dbTransactionWrap, generateNextName } from 'src/helpers/utils.helper'; +import { dbTransactionWrap, generateInviteURL, generateNextName } from 'src/helpers/utils.helper'; import { DeepPartial, EntityManager } from 'typeorm'; import { GitOAuthService } from './git_oauth.service'; import { GoogleOAuthService } from './google_oauth.service'; @@ -316,9 +316,12 @@ export class OauthService { )?.invitationToken; return decamelizeKeys({ - redirectUrl: `${this.configService.get('TOOLJET_HOST')}/invitations/${ - userDetails.invitationToken - }/workspaces/${organizationToken}?oid=${organization.id}&source=${URL_SSO_SOURCE}`, + redirectUrl: generateInviteURL( + userDetails.invitationToken, + organizationToken, + organization.id, + URL_SSO_SOURCE + ), }); } } @@ -331,9 +334,7 @@ export class OauthService { manager ); return decamelizeKeys({ - redirectUrl: `${this.configService.get('TOOLJET_HOST')}/invitations/${ - userDetails.invitationToken - }?source=${URL_SSO_SOURCE}`, + redirectUrl: generateInviteURL(userDetails.invitationToken, null, null, URL_SSO_SOURCE), }); } return await this.authService.generateLoginResultPayload( diff --git a/server/src/helpers/utils.helper.ts b/server/src/helpers/utils.helper.ts index 55803c1eef..134c50569f 100644 --- a/server/src/helpers/utils.helper.ts +++ b/server/src/helpers/utils.helper.ts @@ -144,3 +144,25 @@ export const truncateAndReplace = (name) => { } return name + secondsSinceEpoch; }; + +export const generateInviteURL = ( + invitationToken: string, + organizationToken?: string, + organizationId?: string, + source?: string +) => { + const host = process.env.TOOLJET_HOST; + const subpath = process.env.SUB_PATH; + + return `${host}${subpath ? subpath : '/'}invitations/${invitationToken}${ + organizationToken ? `/workspaces/${organizationToken}${organizationId ? `?oid=${organizationId}` : ''}` : '' + }${source ? `${organizationId ? '&' : '?'}source=${source}` : ''}`; +}; + +export const generateOrgInviteURL = (organizationToken: string, organizationId?: string) => { + const host = process.env.TOOLJET_HOST; + const subpath = process.env.SUB_PATH; + return `${host}${subpath ? subpath : '/'}organization-invitations/${organizationToken}${ + organizationId ? `?oid=${organizationId}` : '' + }`; +}; diff --git a/server/src/services/auth.service.ts b/server/src/services/auth.service.ts index 20671c2836..f8b17d65e9 100644 --- a/server/src/services/auth.service.ts +++ b/server/src/services/auth.service.ts @@ -21,7 +21,7 @@ import { DeepPartial, EntityManager, Repository } from 'typeorm'; import { OrganizationUser } from 'src/entities/organization_user.entity'; import { CreateAdminDto, CreateUserDto } from '@dto/user.dto'; import { AcceptInviteDto } from '@dto/accept-organization-invite.dto'; -import { dbTransactionWrap, generateNextName } from 'src/helpers/utils.helper'; +import { dbTransactionWrap, generateInviteURL, generateNextName, generateOrgInviteURL } from 'src/helpers/utils.helper'; import { getUserErrorMessages, getUserStatusAndSource, @@ -458,7 +458,8 @@ export class AuthService { user.email, `${user.firstName} ${user.lastName} ?? ''`, user.invitationToken, - `${organizationUser.invitationToken}?oid=${organizationUser.organizationId}` + `${organizationUser.invitationToken}`, + organizationUser.organizationId ) .catch((err) => console.error('Error while sending welcome mail', err)); throw new UnauthorizedException( @@ -484,13 +485,11 @@ export class AuthService { if (!user && organizationUser) { return { - redirect_url: `${this.configService.get( - 'TOOLJET_HOST' - )}/organization-invitations/${organizationToken}?oid=${organizationUser.organizationId}`, + redirect_url: generateOrgInviteURL(organizationToken, organizationUser.organizationId), }; } else if (user && !organizationUser) { return { - redirect_url: `${this.configService.get('TOOLJET_HOST')}/invitations/${token}`, + redirect_url: generateInviteURL(token), }; } } diff --git a/server/src/services/email.service.ts b/server/src/services/email.service.ts index 23db9f83ee..d5c09ae97b 100644 --- a/server/src/services/email.service.ts +++ b/server/src/services/email.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@nestjs/common'; import handlebars from 'handlebars'; +import { generateInviteURL, generateOrgInviteURL } from 'src/helpers/utils.helper'; const path = require('path'); const fs = require('fs'); const nodemailer = require('nodemailer'); @@ -70,13 +71,12 @@ export class EmailService { name: string, invitationtoken: string, organizationInvitationToken?: string, + organizationId?: string, organizationName?: string, sender?: string ) { const subject = 'Welcome to ToolJet'; - const inviteUrl = `${this.TOOLJET_HOST}/invitations/${invitationtoken}${ - organizationInvitationToken ? `/workspaces/${organizationInvitationToken}` : '' - }`; + const inviteUrl = generateInviteURL(invitationtoken, organizationInvitationToken, organizationId); const html = ` @@ -117,7 +117,7 @@ export class EmailService { organizationName: string ) { const subject = 'Welcome to ToolJet'; - const inviteUrl = `${this.TOOLJET_HOST}/organization-invitations/${invitationtoken}`; + const inviteUrl = generateOrgInviteURL(invitationtoken); const html = ` diff --git a/server/src/services/organizations.service.ts b/server/src/services/organizations.service.ts index be6f41f8d5..709c6a541e 100644 --- a/server/src/services/organizations.service.ts +++ b/server/src/services/organizations.service.ts @@ -598,7 +598,8 @@ export class OrganizationsService { user.email, user.firstName, user.invitationToken, - `${organizationUser.invitationToken}?oid=${organizationUser.organizationId}`, + organizationUser.invitationToken, + organizationUser.organizationId, currentOrganization.name, `${currentUser.firstName} ${currentUser.lastName ?? ''}` )