Closes #805 - Unable to signin on self-hosted installations with non-www subdomain
This commit is contained in:
@ -8,6 +8,7 @@ import UsersStore from 'stores/UsersStore';
|
|||||||
import CollectionsStore from 'stores/CollectionsStore';
|
import CollectionsStore from 'stores/CollectionsStore';
|
||||||
import IntegrationsStore from 'stores/IntegrationsStore';
|
import IntegrationsStore from 'stores/IntegrationsStore';
|
||||||
import LoadingIndicator from 'components/LoadingIndicator';
|
import LoadingIndicator from 'components/LoadingIndicator';
|
||||||
|
import { isCustomSubdomain } from 'shared/utils/domains';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
auth: AuthStore,
|
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
|
// If we're authenticated but viewing a subdomain that doesn't match the
|
||||||
// authenticated team then kick the user to the teams subdomain.
|
// currently authenticated team then kick the user to the teams subdomain.
|
||||||
// www is a special case, as always
|
|
||||||
if (
|
if (
|
||||||
process.env.SUBDOMAINS_ENABLED &&
|
process.env.SUBDOMAINS_ENABLED &&
|
||||||
team.subdomain &&
|
team.subdomain &&
|
||||||
!hostname.startsWith(`${team.subdomain}.`) &&
|
isCustomSubdomain(hostname) &&
|
||||||
!hostname.startsWith('www.')
|
!hostname.startsWith(`${team.subdomain}.`)
|
||||||
) {
|
) {
|
||||||
window.location.href = `${team.url}${window.location.pathname}`;
|
window.location.href = `${team.url}${window.location.pathname}`;
|
||||||
return <LoadingIndicator />;
|
return <LoadingIndicator />;
|
||||||
|
@ -8,6 +8,7 @@ import serve from 'koa-static';
|
|||||||
import parseDomain from 'parse-domain';
|
import parseDomain from 'parse-domain';
|
||||||
import apexRedirect from './middlewares/apexRedirect';
|
import apexRedirect from './middlewares/apexRedirect';
|
||||||
import renderpage from './utils/renderpage';
|
import renderpage from './utils/renderpage';
|
||||||
|
import { isCustomSubdomain } from '../shared/utils/domains';
|
||||||
import { robotsResponse } from './utils/robots';
|
import { robotsResponse } from './utils/robots';
|
||||||
import { NotFoundError } from './errors';
|
import { NotFoundError } from './errors';
|
||||||
import { Team } from './models';
|
import { Team } from './models';
|
||||||
@ -67,8 +68,6 @@ router.get('/changelog', async ctx => {
|
|||||||
router.get('/', async ctx => {
|
router.get('/', async ctx => {
|
||||||
const lastSignedIn = ctx.cookies.get('lastSignedIn');
|
const lastSignedIn = ctx.cookies.get('lastSignedIn');
|
||||||
const accessToken = ctx.cookies.get('accessToken');
|
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
|
// 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.
|
// 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
|
// If we're on a custom subdomain then we display a slightly different signed
|
||||||
// out view that includes the teams basic information.
|
// 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({
|
const team = await Team.find({
|
||||||
where: { subdomain },
|
where: { subdomain },
|
||||||
});
|
});
|
||||||
if (team && process.env.SUBDOMAINS_ENABLED === 'true') {
|
if (team) {
|
||||||
return renderpage(
|
return renderpage(
|
||||||
ctx,
|
ctx,
|
||||||
<SubdomainSignin
|
<SubdomainSignin
|
||||||
|
@ -9,6 +9,13 @@ export function stripSubdomain(hostname: string) {
|
|||||||
return parsed.domain;
|
return parsed.domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isCustomSubdomain(hostname: string) {
|
||||||
|
const parsed = parseDomain(hostname);
|
||||||
|
if (!parsed) return false;
|
||||||
|
if (!parsed.subdomain || parsed.subdomain === 'www') return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
export const RESERVED_SUBDOMAINS = [
|
export const RESERVED_SUBDOMAINS = [
|
||||||
'about',
|
'about',
|
||||||
'account',
|
'account',
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable flowtype/require-valid-file-annotation */
|
/* eslint-disable flowtype/require-valid-file-annotation */
|
||||||
import { stripSubdomain } from './domains';
|
import { stripSubdomain, isCustomSubdomain } from './domains';
|
||||||
|
|
||||||
describe('#stripSubdomain', () => {
|
describe('#stripSubdomain', () => {
|
||||||
test('to work with localhost', () => {
|
test('to work with localhost', () => {
|
||||||
@ -15,3 +15,22 @@ describe('#stripSubdomain', () => {
|
|||||||
expect(stripSubdomain('test.example.com:3000')).toBe('example.com');
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Reference in New Issue
Block a user