diff --git a/app/components/Auth.js b/app/components/Auth.js index 268dae30..894ffb6c 100644 --- a/app/components/Auth.js +++ b/app/components/Auth.js @@ -8,6 +8,7 @@ import UsersStore from 'stores/UsersStore'; import CollectionsStore from 'stores/CollectionsStore'; import IntegrationsStore from 'stores/IntegrationsStore'; import LoadingIndicator from 'components/LoadingIndicator'; +import { isCustomSubdomain } from 'shared/utils/domains'; type Props = { auth: AuthStore, @@ -26,13 +27,12 @@ const Auth = observer(({ auth, children }: Props) => { } // If we're authenticated but viewing a subdomain that doesn't match the - // authenticated team then kick the user to the teams subdomain. - // www is a special case, as always + // currently authenticated team then kick the user to the teams subdomain. if ( process.env.SUBDOMAINS_ENABLED && team.subdomain && - !hostname.startsWith(`${team.subdomain}.`) && - !hostname.startsWith('www.') + isCustomSubdomain(hostname) && + !hostname.startsWith(`${team.subdomain}.`) ) { window.location.href = `${team.url}${window.location.pathname}`; return ; diff --git a/server/routes.js b/server/routes.js index 926f5541..b0378c4d 100644 --- a/server/routes.js +++ b/server/routes.js @@ -8,6 +8,7 @@ import serve from 'koa-static'; import parseDomain from 'parse-domain'; import apexRedirect from './middlewares/apexRedirect'; import renderpage from './utils/renderpage'; +import { isCustomSubdomain } from '../shared/utils/domains'; import { robotsResponse } from './utils/robots'; import { NotFoundError } from './errors'; import { Team } from './models'; @@ -67,8 +68,6 @@ router.get('/changelog', async ctx => { router.get('/', async ctx => { const lastSignedIn = ctx.cookies.get('lastSignedIn'); const accessToken = ctx.cookies.get('accessToken'); - const domain = parseDomain(ctx.request.hostname); - const subdomain = domain ? domain.subdomain : undefined; // Because we render both the signed in and signed out views depending // on a cookie it's important that the browser does not render from cache. @@ -82,11 +81,16 @@ router.get('/', async ctx => { // If we're on a custom subdomain then we display a slightly different signed // out view that includes the teams basic information. - if (subdomain && subdomain !== 'www') { + if ( + process.env.SUBDOMAINS_ENABLED === 'true' && + isCustomSubdomain(ctx.request.hostname) + ) { + const domain = parseDomain(ctx.request.hostname); + const subdomain = domain ? domain.subdomain : undefined; const team = await Team.find({ where: { subdomain }, }); - if (team && process.env.SUBDOMAINS_ENABLED === 'true') { + if (team) { return renderpage( ctx, { test('to work with localhost', () => { @@ -15,3 +15,22 @@ describe('#stripSubdomain', () => { expect(stripSubdomain('test.example.com:3000')).toBe('example.com'); }); }); + +describe('#isCustomSubdomain', () => { + test('to work with localhost', () => { + expect(isCustomSubdomain('localhost')).toBe(false); + }); + test('to return false for domains without a subdomain', () => { + expect(isCustomSubdomain('example')).toBe(false); + expect(isCustomSubdomain('example.com')).toBe(false); + expect(isCustomSubdomain('example.org:3000')).toBe(false); + }); + test('to return false for www', () => { + expect(isCustomSubdomain('www.example.com')).toBe(false); + expect(isCustomSubdomain('www.example.com:3000')).toBe(false); + }); + test('to return true for subdomains', () => { + expect(isCustomSubdomain('test.example.com')).toBe(true); + expect(isCustomSubdomain('test.example.com:3000')).toBe(true); + }); +});