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);
+ });
+});