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:
@@ -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(/\/$/, "");
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
);
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user