chore: Migrate authentication to new tables (#1929)

This work provides a foundation for a more pluggable authentication system such as the one outlined in #1317.

closes #1317
This commit is contained in:
Tom Moor
2021-03-09 12:22:08 -08:00
committed by GitHub
parent ab7b16bbb9
commit ed2a42ac27
35 changed files with 1280 additions and 297 deletions

View File

@@ -37,10 +37,14 @@ services.push({
function filterServices(team) {
let output = services;
if (team && !team.googleId) {
const providerNames = team
? team.authenticationProviders.map((provider) => provider.name)
: [];
if (team && !providerNames.includes("google")) {
output = reject(output, (service) => service.id === "google");
}
if (team && !team.slackId) {
if (team && !providerNames.includes("slack")) {
output = reject(output, (service) => service.id === "slack");
}
if (!team || !team.guestSignin) {
@@ -55,7 +59,7 @@ router.post("auth.config", async (ctx) => {
// 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.findAll();
const teams = await Team.scope("withAuthenticationProviders").findAll();
if (teams.length === 1) {
const team = teams[0];
@@ -70,7 +74,7 @@ router.post("auth.config", async (ctx) => {
}
if (isCustomDomain(ctx.request.hostname)) {
const team = await Team.findOne({
const team = await Team.scope("withAuthenticationProviders").findOne({
where: { domain: ctx.request.hostname },
});
@@ -95,7 +99,7 @@ router.post("auth.config", async (ctx) => {
) {
const domain = parseDomain(ctx.request.hostname);
const subdomain = domain ? domain.subdomain : undefined;
const team = await Team.findOne({
const team = await Team.scope("withAuthenticationProviders").findOne({
where: { subdomain },
});

View File

@@ -3,6 +3,8 @@ import Router from "koa-router";
import { escapeRegExp } from "lodash";
import { AuthenticationError, InvalidRequestError } from "../errors";
import {
UserAuthentication,
AuthenticationProvider,
Authentication,
Document,
User,
@@ -25,7 +27,14 @@ router.post("hooks.unfurl", async (ctx) => {
}
const user = await User.findOne({
where: { service: "slack", serviceId: event.user },
include: [
{
where: { providerId: event.user },
model: UserAuthentication,
as: "authentications",
required: true,
},
],
});
if (!user) return;
@@ -70,11 +79,21 @@ router.post("hooks.interactive", async (ctx) => {
throw new AuthenticationError("Invalid verification token");
}
const team = await Team.findOne({
where: { slackId: data.team.id },
const authProvider = await AuthenticationProvider.findOne({
where: {
name: "slack",
providerId: data.team.id,
},
include: [
{
model: Team,
as: "team",
required: true,
},
],
});
if (!team) {
if (!authProvider) {
ctx.body = {
text:
"Sorry, we couldnt find an integration for your team. Head to your Outline settings to set one up.",
@@ -84,6 +103,8 @@ router.post("hooks.interactive", async (ctx) => {
return;
}
const { team } = authProvider;
// we find the document based on the users teamId to ensure access
const document = await Document.findOne({
where: {
@@ -131,20 +152,41 @@ router.post("hooks.slack", async (ctx) => {
return;
}
let user;
let user, team;
// attempt to find the corresponding team for this request based on the team_id
let team = await Team.findOne({
where: { slackId: team_id },
});
if (team) {
user = await User.findOne({
where: {
teamId: team.id,
service: "slack",
serviceId: user_id,
team = await Team.findOne({
include: [
{
where: {
name: "slack",
providerId: team_id,
},
as: "authenticationProviders",
model: AuthenticationProvider,
required: true,
},
],
});
if (team) {
const authentication = await UserAuthentication.findOne({
where: {
providerId: user_id,
},
include: [
{
where: { teamId: team.id },
model: User,
as: "user",
required: true,
},
],
});
if (authentication) {
user = authentication.user;
}
} else {
// If we couldn't find a team it's still possible that the request is from
// a team that authenticated with a different service, but connected Slack

View File

@@ -33,7 +33,7 @@ describe("#hooks.unfurl", () => {
event: {
type: "link_shared",
channel: "Cxxxxxx",
user: user.serviceId,
user: user.authentications[0].providerId,
message_ts: "123456789.9875",
links: [
{
@@ -56,8 +56,8 @@ describe("#hooks.slack", () => {
const res = await server.post("/api/hooks.slack", {
body: {
token: process.env.SLACK_VERIFICATION_TOKEN,
user_id: user.serviceId,
team_id: team.slackId,
user_id: user.authentications[0].providerId,
team_id: team.authenticationProviders[0].providerId,
text: "dsfkndfskndsfkn",
},
});
@@ -76,8 +76,8 @@ describe("#hooks.slack", () => {
const res = await server.post("/api/hooks.slack", {
body: {
token: process.env.SLACK_VERIFICATION_TOKEN,
user_id: user.serviceId,
team_id: team.slackId,
user_id: user.authentications[0].providerId,
team_id: team.authenticationProviders[0].providerId,
text: "contains",
},
});
@@ -98,8 +98,8 @@ describe("#hooks.slack", () => {
const res = await server.post("/api/hooks.slack", {
body: {
token: process.env.SLACK_VERIFICATION_TOKEN,
user_id: user.serviceId,
team_id: team.slackId,
user_id: user.authentications[0].providerId,
team_id: team.authenticationProviders[0].providerId,
text: "*contains",
},
});
@@ -118,8 +118,8 @@ describe("#hooks.slack", () => {
const res = await server.post("/api/hooks.slack", {
body: {
token: process.env.SLACK_VERIFICATION_TOKEN,
user_id: user.serviceId,
team_id: team.slackId,
user_id: user.authentications[0].providerId,
team_id: team.authenticationProviders[0].providerId,
text: "contains",
},
});
@@ -137,8 +137,8 @@ describe("#hooks.slack", () => {
await server.post("/api/hooks.slack", {
body: {
token: process.env.SLACK_VERIFICATION_TOKEN,
user_id: user.serviceId,
team_id: team.slackId,
user_id: user.authentications[0].providerId,
team_id: team.authenticationProviders[0].providerId,
text: "contains",
},
});
@@ -161,8 +161,8 @@ describe("#hooks.slack", () => {
const res = await server.post("/api/hooks.slack", {
body: {
token: process.env.SLACK_VERIFICATION_TOKEN,
user_id: user.serviceId,
team_id: team.slackId,
user_id: user.authentications[0].providerId,
team_id: team.authenticationProviders[0].providerId,
text: "help",
},
});
@@ -176,8 +176,8 @@ describe("#hooks.slack", () => {
const res = await server.post("/api/hooks.slack", {
body: {
token: process.env.SLACK_VERIFICATION_TOKEN,
user_id: user.serviceId,
team_id: team.slackId,
user_id: user.authentications[0].providerId,
team_id: team.authenticationProviders[0].providerId,
text: "",
},
});
@@ -206,7 +206,7 @@ describe("#hooks.slack", () => {
body: {
token: process.env.SLACK_VERIFICATION_TOKEN,
user_id: "unknown-slack-user-id",
team_id: team.slackId,
team_id: team.authenticationProviders[0].providerId,
text: "contains",
},
});
@@ -260,8 +260,8 @@ describe("#hooks.slack", () => {
const res = await server.post("/api/hooks.slack", {
body: {
token: "wrong-verification-token",
team_id: team.slackId,
user_id: user.serviceId,
user_id: user.authentications[0].providerId,
team_id: team.authenticationProviders[0].providerId,
text: "Welcome",
},
});
@@ -280,8 +280,8 @@ describe("#hooks.interactive", () => {
const payload = JSON.stringify({
token: process.env.SLACK_VERIFICATION_TOKEN,
user: { id: user.serviceId },
team: { id: team.slackId },
user: { id: user.authentications[0].providerId },
team: { id: team.authenticationProviders[0].providerId },
callback_id: document.id,
});
const res = await server.post("/api/hooks.interactive", {
@@ -305,7 +305,7 @@ describe("#hooks.interactive", () => {
const payload = JSON.stringify({
token: process.env.SLACK_VERIFICATION_TOKEN,
user: { id: "unknown-slack-user-id" },
team: { id: team.slackId },
team: { id: team.authenticationProviders[0].providerId },
callback_id: document.id,
});
const res = await server.post("/api/hooks.interactive", {
@@ -322,7 +322,7 @@ describe("#hooks.interactive", () => {
const { user } = await seed();
const payload = JSON.stringify({
token: "wrong-verification-token",
user: { id: user.serviceId, name: user.name },
user: { id: user.authentications[0].providerId, name: user.name },
callback_id: "doesnt-matter",
});
const res = await server.post("/api/hooks.interactive", {