chore: refactor domain parsing to be more general (#3448)

* change the api of domain parsing to just parseDomain and getCookieDomain
* adds getBaseDomain as the method to get the domain after any official subdomains
This commit is contained in:
Nan Yu
2022-05-31 18:48:23 -07:00
committed by GitHub
parent 876f788f59
commit 41e425756d
16 changed files with 216 additions and 237 deletions

View File

@@ -19,7 +19,7 @@ import {
DataType,
} from "sequelize-typescript";
import { v4 as uuidv4 } from "uuid";
import { stripSubdomain, RESERVED_SUBDOMAINS } from "@shared/utils/domains";
import { getBaseDomain, RESERVED_SUBDOMAINS } from "@shared/utils/domains";
import env from "@server/env";
import Logger from "@server/logging/Logger";
import { generateAvatarUrl } from "@server/utils/avatars";
@@ -122,6 +122,7 @@ class Team extends ParanoidModel {
}
get url() {
// custom domain
if (this.domain) {
return `https://${this.domain}`;
}
@@ -131,7 +132,7 @@ class Team extends ParanoidModel {
}
const url = new URL(env.URL);
url.host = `${this.subdomain}.${stripSubdomain(url.host)}`;
url.host = `${this.subdomain}.${getBaseDomain()}`;
return url.href.replace(/\/$/, "");
}

View File

@@ -1,12 +1,11 @@
import invariant from "invariant";
import Router from "koa-router";
import { find } from "lodash";
import { parseDomain, isCustomSubdomain } from "@shared/utils/domains";
import { parseDomain } from "@shared/utils/domains";
import env from "@server/env";
import auth from "@server/middlewares/authentication";
import { Team, TeamDomain } from "@server/models";
import { presentUser, presentTeam, presentPolicies } from "@server/presenters";
import { isCustomDomain } from "@server/utils/domains";
import providers from "../auth/providers";
const router = new Router();
@@ -55,7 +54,9 @@ router.post("auth.config", async (ctx) => {
}
}
if (isCustomDomain(ctx.request.hostname)) {
const domain = parseDomain(ctx.request.hostname);
if (domain.custom) {
const team = await Team.scope("withAuthenticationProviders").findOne({
where: {
domain: ctx.request.hostname,
@@ -76,16 +77,10 @@ router.post("auth.config", async (ctx) => {
// If subdomain signin page then we return minimal team details to allow
// for a custom screen showing only relevant signin options for that team.
if (
env.SUBDOMAINS_ENABLED &&
isCustomSubdomain(ctx.request.hostname) &&
!isCustomDomain(ctx.request.hostname)
) {
const domain = parseDomain(ctx.request.hostname);
const subdomain = domain ? domain.subdomain : undefined;
else if (env.SUBDOMAINS_ENABLED && domain.teamSubdomain) {
const team = await Team.scope("withAuthenticationProviders").findOne({
where: {
subdomain,
subdomain: domain.teamSubdomain,
},
});

View File

@@ -1,4 +1,5 @@
import TestServer from "fetch-test-server";
import sharedEnv from "@shared/env";
import SigninEmail from "@server/emails/templates/SigninEmail";
import WelcomeEmail from "@server/emails/templates/WelcomeEmail";
import env from "@server/env";
@@ -41,8 +42,8 @@ describe("email", () => {
});
it("should respond with redirect location when user is SSO enabled on another subdomain", async () => {
env.URL = "http://localoutline.com";
env.SUBDOMAINS_ENABLED = true;
env.URL = sharedEnv.URL = "http://localoutline.com";
env.SUBDOMAINS_ENABLED = sharedEnv.SUBDOMAINS_ENABLED = true;
const user = await buildUser();
const spy = jest.spyOn(WelcomeEmail, "schedule");
await buildTeam({
@@ -94,8 +95,8 @@ describe("email", () => {
describe("with multiple users matching email", () => {
it("should default to current subdomain with SSO", async () => {
const spy = jest.spyOn(SigninEmail, "schedule");
env.URL = "http://localoutline.com";
env.SUBDOMAINS_ENABLED = true;
env.URL = sharedEnv.URL = "http://localoutline.com";
env.SUBDOMAINS_ENABLED = sharedEnv.SUBDOMAINS_ENABLED = true;
const email = "sso-user@example.org";
const team = await buildTeam({
subdomain: "example",
@@ -124,8 +125,8 @@ describe("email", () => {
it("should default to current subdomain with guest email", async () => {
const spy = jest.spyOn(SigninEmail, "schedule");
env.URL = "http://localoutline.com";
env.SUBDOMAINS_ENABLED = true;
env.URL = sharedEnv.URL = "http://localoutline.com";
env.SUBDOMAINS_ENABLED = sharedEnv.SUBDOMAINS_ENABLED = true;
const email = "guest-user@example.org";
const team = await buildTeam({
subdomain: "example",

View File

@@ -1,7 +1,7 @@
import { subMinutes } from "date-fns";
import Router from "koa-router";
import { find } from "lodash";
import { parseDomain, isCustomSubdomain } from "@shared/utils/domains";
import { parseDomain } from "@shared/utils/domains";
import SigninEmail from "@server/emails/templates/SigninEmail";
import WelcomeEmail from "@server/emails/templates/WelcomeEmail";
import env from "@server/env";
@@ -10,7 +10,6 @@ import errorHandling from "@server/middlewares/errorHandling";
import methodOverride from "@server/middlewares/methodOverride";
import { User, Team } from "@server/models";
import { signIn } from "@server/utils/authentication";
import { isCustomDomain } from "@server/utils/domains";
import { getUserForEmailSigninToken } from "@server/utils/jwt";
import { assertEmail, assertPresent } from "@server/validation";
@@ -34,25 +33,18 @@ router.post("email", errorHandling(), async (ctx) => {
if (users.length) {
let team!: Team | null;
const domain = parseDomain(ctx.request.hostname);
if (isCustomDomain(ctx.request.hostname)) {
if (domain.custom) {
team = await Team.scope("withAuthenticationProviders").findOne({
where: {
domain: ctx.request.hostname,
},
});
}
if (
env.SUBDOMAINS_ENABLED &&
isCustomSubdomain(ctx.request.hostname) &&
!isCustomDomain(ctx.request.hostname)
) {
const domain = parseDomain(ctx.request.hostname);
const subdomain = domain ? domain.subdomain : undefined;
} else if (env.SUBDOMAINS_ENABLED && domain.teamSubdomain) {
team = await Team.scope("withAuthenticationProviders").findOne({
where: {
subdomain,
subdomain: domain.teamSubdomain,
},
});
}

View File

@@ -2,10 +2,10 @@ import querystring from "querystring";
import { addMonths } from "date-fns";
import { Context } from "koa";
import { pick } from "lodash";
import { getCookieDomain } from "@shared/utils/domains";
import env from "@server/env";
import Logger from "@server/logging/Logger";
import { User, Event, Team, Collection, View } from "@server/models";
import { getCookieDomain } from "@server/utils/domains";
export async function signIn(
ctx: Context,

View File

@@ -1,15 +0,0 @@
import { parseDomain, stripSubdomain } from "@shared/utils/domains";
import env from "@server/env";
export function getCookieDomain(domain: string) {
return env.SUBDOMAINS_ENABLED ? stripSubdomain(domain) : domain;
}
export function isCustomDomain(hostname: string) {
const parsed = parseDomain(hostname);
const main = parseDomain(env.URL);
return (
parsed && main && (main.domain !== parsed.domain || main.tld !== parsed.tld)
);
}

View File

@@ -6,8 +6,8 @@ import {
StateStoreStoreCallback,
StateStoreVerifyCallback,
} from "passport-oauth2";
import { getCookieDomain } from "@shared/utils/domains";
import { OAuthStateMismatchError } from "../errors";
import { getCookieDomain } from "./domains";
export class StateStore {
key = "state";