Fixes #3412 Previously the only way to restrict the domains for a Team were with the ALLOWED_DOMAINS environment variable for self hosted instances. This PR migrates this to be a database backed setting on the Team object. This is done through the creation of a TeamDomain model that is associated with the Team and contains the domain name This settings is updated on the Security Tab. Here domains can be added or removed from the Team. On the server side, we take the code paths that previously were using ALLOWED_DOMAINS and switched them to use the Team allowed domains instead
131 lines
3.4 KiB
TypeScript
131 lines
3.4 KiB
TypeScript
import invariant from "invariant";
|
|
import Router from "koa-router";
|
|
import { find } from "lodash";
|
|
import { parseDomain, isCustomSubdomain } from "@shared/utils/domains";
|
|
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();
|
|
|
|
function filterProviders(team: Team) {
|
|
return providers
|
|
.sort((provider) => (provider.id === "email" ? 1 : -1))
|
|
.filter((provider) => {
|
|
// guest sign-in is an exception as it does not have an authentication
|
|
// provider using passport, instead it exists as a boolean option on the team
|
|
if (provider.id === "email") {
|
|
return team?.emailSigninEnabled;
|
|
}
|
|
|
|
return (
|
|
!team ||
|
|
find(team.authenticationProviders, {
|
|
name: provider.id,
|
|
enabled: true,
|
|
})
|
|
);
|
|
})
|
|
.map((provider) => ({
|
|
id: provider.id,
|
|
name: provider.name,
|
|
authUrl: provider.authUrl,
|
|
}));
|
|
}
|
|
|
|
router.post("auth.config", async (ctx) => {
|
|
// If self hosted AND there is only one team then that team becomes the
|
|
// brand for the knowledge base and it's guest signin option is used for the
|
|
// root login page.
|
|
if (process.env.DEPLOYMENT !== "hosted") {
|
|
const teams = await Team.scope("withAuthenticationProviders").findAll();
|
|
|
|
if (teams.length === 1) {
|
|
const team = teams[0];
|
|
ctx.body = {
|
|
data: {
|
|
name: team.name,
|
|
providers: filterProviders(team),
|
|
},
|
|
};
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (isCustomDomain(ctx.request.hostname)) {
|
|
const team = await Team.scope("withAuthenticationProviders").findOne({
|
|
where: {
|
|
domain: ctx.request.hostname,
|
|
},
|
|
});
|
|
|
|
if (team) {
|
|
ctx.body = {
|
|
data: {
|
|
name: team.name,
|
|
hostname: ctx.request.hostname,
|
|
providers: filterProviders(team),
|
|
},
|
|
};
|
|
return;
|
|
}
|
|
}
|
|
|
|
// 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 (
|
|
process.env.SUBDOMAINS_ENABLED === "true" &&
|
|
isCustomSubdomain(ctx.request.hostname) &&
|
|
!isCustomDomain(ctx.request.hostname)
|
|
) {
|
|
const domain = parseDomain(ctx.request.hostname);
|
|
const subdomain = domain ? domain.subdomain : undefined;
|
|
const team = await Team.scope("withAuthenticationProviders").findOne({
|
|
where: {
|
|
subdomain,
|
|
},
|
|
});
|
|
|
|
if (team) {
|
|
ctx.body = {
|
|
data: {
|
|
name: team.name,
|
|
hostname: ctx.request.hostname,
|
|
providers: filterProviders(team),
|
|
},
|
|
};
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Otherwise, we're requesting from the standard root signin page
|
|
ctx.body = {
|
|
data: {
|
|
// @ts-expect-error ts-migrate(2554) FIXME: Expected 1 arguments, but got 0.
|
|
providers: filterProviders(),
|
|
},
|
|
};
|
|
});
|
|
|
|
router.post("auth.info", auth(), async (ctx) => {
|
|
const { user } = ctx.state;
|
|
const team = await Team.findByPk(user.teamId, {
|
|
include: [{ model: TeamDomain }],
|
|
});
|
|
invariant(team, "Team not found");
|
|
|
|
ctx.body = {
|
|
data: {
|
|
user: presentUser(user, {
|
|
includeDetails: true,
|
|
}),
|
|
team: presentTeam(team),
|
|
},
|
|
policies: presentPolicies(user, [team]),
|
|
};
|
|
});
|
|
|
|
export default router;
|