mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-09-27 20:38:32 +02:00
Consolidate versions for easier extension (#495)
This commit is contained in:
@@ -30,6 +30,9 @@ ENV NEXT_TELEMETRY_DISABLED 1
|
||||
ARG NEXT_PUBLIC_DISABLE_STREAMING
|
||||
ENV NEXT_PUBLIC_DISABLE_STREAMING=${NEXT_PUBLIC_DISABLE_STREAMING}
|
||||
|
||||
ARG NEXT_PUBLIC_AUTH_TYPE
|
||||
ENV NEXT_PUBLIC_AUTH_TYPE=${NEXT_PUBLIC_AUTH_TYPE}
|
||||
|
||||
RUN npm run build
|
||||
|
||||
# Step 3. Production image, copy all the files and run next
|
||||
@@ -65,6 +68,9 @@ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
ARG NEXT_PUBLIC_DISABLE_STREAMING
|
||||
ENV NEXT_PUBLIC_DISABLE_STREAMING=${NEXT_PUBLIC_DISABLE_STREAMING}
|
||||
|
||||
ARG NEXT_PUBLIC_AUTH_TYPE
|
||||
ENV NEXT_PUBLIC_AUTH_TYPE=${NEXT_PUBLIC_AUTH_TYPE}
|
||||
|
||||
# Note: Don't expose ports here, Compose will handle that for us if necessary.
|
||||
# If you want to run this without compose, specify the ports to
|
||||
# expose via cli
|
||||
|
@@ -1,23 +0,0 @@
|
||||
import { getDomain } from "@/lib/redirectSS";
|
||||
import { buildUrl } from "@/lib/utilsSS";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
export const GET = async (request: NextRequest) => {
|
||||
// Wrapper around the FastAPI endpoint /auth/google/callback,
|
||||
// which adds back a redirect to the main app.
|
||||
const url = new URL(buildUrl("/auth/google/callback"));
|
||||
url.search = request.nextUrl.search;
|
||||
|
||||
const response = await fetch(url.toString());
|
||||
const setCookieHeader = response.headers.get("set-cookie");
|
||||
|
||||
if (!setCookieHeader) {
|
||||
return NextResponse.redirect(new URL("/auth/error", getDomain(request)));
|
||||
}
|
||||
|
||||
const redirectResponse = NextResponse.redirect(
|
||||
new URL("/", getDomain(request))
|
||||
);
|
||||
redirectResponse.headers.set("set-cookie", setCookieHeader);
|
||||
return redirectResponse;
|
||||
};
|
@@ -1,7 +1,7 @@
|
||||
import { HealthCheckBanner } from "@/components/health/healthcheck";
|
||||
import { DISABLE_AUTH, OAUTH_NAME } from "@/lib/constants";
|
||||
import { User } from "@/lib/types";
|
||||
import { getGoogleOAuthUrlSS, getCurrentUserSS } from "@/lib/userSS";
|
||||
import { getCurrentUserSS, getAuthUrlSS } from "@/lib/userSS";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
const BUTTON_STYLE =
|
||||
@@ -21,10 +21,11 @@ const Page = async () => {
|
||||
// will not render
|
||||
let currentUser: User | null = null;
|
||||
let authorizationUrl: string | null = null;
|
||||
let autoRedirect: boolean = false;
|
||||
try {
|
||||
[currentUser, authorizationUrl] = await Promise.all([
|
||||
[currentUser, [authorizationUrl, autoRedirect]] = await Promise.all([
|
||||
getCurrentUserSS(),
|
||||
getGoogleOAuthUrlSS(),
|
||||
getAuthUrlSS(),
|
||||
]);
|
||||
} catch (e) {
|
||||
console.log(`Some fetch failed for the login page - ${e}`);
|
||||
@@ -35,6 +36,10 @@ const Page = async () => {
|
||||
return redirect("/");
|
||||
}
|
||||
|
||||
if (autoRedirect && authorizationUrl) {
|
||||
return redirect(authorizationUrl);
|
||||
}
|
||||
|
||||
return (
|
||||
<main>
|
||||
<div className="absolute top-10x w-full">
|
||||
|
8
web/src/app/auth/logout/route.ts
Normal file
8
web/src/app/auth/logout/route.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { logoutSS } from "@/lib/userSS";
|
||||
import { NextRequest } from "next/server";
|
||||
|
||||
export const POST = async (request: NextRequest) => {
|
||||
// Directs the logout request to the appropriate FastAPI endpoint.
|
||||
// Needed since env variables don't work well on the client-side
|
||||
return await logoutSS(request.headers);
|
||||
};
|
33
web/src/app/auth/saml/callback/route.ts
Normal file
33
web/src/app/auth/saml/callback/route.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { getDomain } from "@/lib/redirectSS";
|
||||
import { buildUrl } from "@/lib/utilsSS";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
// have to use this so we don't hit the redirect URL with a `POST` request
|
||||
const SEE_OTHER_REDIRECT_STATUS = 303;
|
||||
|
||||
export const POST = async (request: NextRequest) => {
|
||||
// Wrapper around the FastAPI endpoint /auth/saml/callback,
|
||||
// which adds back a redirect to the main app.
|
||||
const url = new URL(buildUrl("/auth/saml/callback"));
|
||||
url.search = request.nextUrl.search;
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
method: "POST",
|
||||
body: await request.formData(),
|
||||
});
|
||||
const setCookieHeader = response.headers.get("set-cookie");
|
||||
|
||||
if (!setCookieHeader) {
|
||||
return NextResponse.redirect(
|
||||
new URL("/auth/error", getDomain(request)),
|
||||
SEE_OTHER_REDIRECT_STATUS
|
||||
);
|
||||
}
|
||||
|
||||
const redirectResponse = NextResponse.redirect(
|
||||
new URL("/", getDomain(request)),
|
||||
SEE_OTHER_REDIRECT_STATUS
|
||||
);
|
||||
redirectResponse.headers.set("set-cookie", setCookieHeader);
|
||||
return redirectResponse;
|
||||
};
|
@@ -1,5 +1,9 @@
|
||||
export const DISABLE_AUTH = process.env.DISABLE_AUTH?.toLowerCase() === "true";
|
||||
export type AuthType = "disabled" | "google_oauth" | "oidc" | "saml";
|
||||
|
||||
export const AUTH_TYPE = (process.env.AUTH_TYPE ||
|
||||
process.env.NEXT_PUBLIC_AUTH_TYPE ||
|
||||
"disabled") as AuthType;
|
||||
export const DISABLE_AUTH = AUTH_TYPE === "disabled";
|
||||
export const OAUTH_NAME = process.env.OAUTH_NAME || "Google";
|
||||
|
||||
export const INTERNAL_URL = process.env.INTERNAL_URL || "http://127.0.0.1:8080";
|
||||
|
@@ -2,7 +2,7 @@ import { User } from "./types";
|
||||
|
||||
// should be used client-side only
|
||||
export const getCurrentUser = async (): Promise<User | null> => {
|
||||
const response = await fetch("/api/users/me", {
|
||||
const response = await fetch("/api/manage/me", {
|
||||
credentials: "include",
|
||||
});
|
||||
if (!response.ok) {
|
||||
@@ -13,7 +13,7 @@ export const getCurrentUser = async (): Promise<User | null> => {
|
||||
};
|
||||
|
||||
export const logout = async (): Promise<boolean> => {
|
||||
const response = await fetch("/api/auth/database/logout", {
|
||||
const response = await fetch("/auth/logout", {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
});
|
||||
|
@@ -2,8 +2,19 @@ import { cookies } from "next/headers";
|
||||
import { User } from "./types";
|
||||
import { buildUrl } from "./utilsSS";
|
||||
import { ReadonlyRequestCookies } from "next/dist/server/web/spec-extension/adapters/request-cookies";
|
||||
import { AUTH_TYPE } from "./constants";
|
||||
|
||||
export const getGoogleOAuthUrlSS = async (): Promise<string> => {
|
||||
const geOIDCAuthUrlSS = async (): Promise<string> => {
|
||||
const res = await fetch(buildUrl("/auth/oidc/authorize"));
|
||||
if (!res.ok) {
|
||||
throw new Error("Failed to fetch data");
|
||||
}
|
||||
|
||||
const data: { authorization_url: string } = await res.json();
|
||||
return data.authorization_url;
|
||||
};
|
||||
|
||||
const getGoogleOAuthUrlSS = async (): Promise<string> => {
|
||||
const res = await fetch(buildUrl("/auth/oauth/authorize"));
|
||||
if (!res.ok) {
|
||||
throw new Error("Failed to fetch data");
|
||||
@@ -13,10 +24,63 @@ export const getGoogleOAuthUrlSS = async (): Promise<string> => {
|
||||
return data.authorization_url;
|
||||
};
|
||||
|
||||
// should be used server-side only
|
||||
const getSAMLAuthUrlSS = async (): Promise<string> => {
|
||||
const res = await fetch(buildUrl("/auth/saml/authorize"));
|
||||
if (!res.ok) {
|
||||
throw new Error("Failed to fetch data");
|
||||
}
|
||||
|
||||
const data: { authorization_url: string } = await res.json();
|
||||
return data.authorization_url;
|
||||
};
|
||||
|
||||
export const getAuthUrlSS = async (): Promise<[string, boolean]> => {
|
||||
// Returns the auth url and whether or not we should auto-redirect
|
||||
switch (AUTH_TYPE) {
|
||||
case "disabled":
|
||||
return ["", true];
|
||||
case "google_oauth": {
|
||||
return [await getGoogleOAuthUrlSS(), false];
|
||||
}
|
||||
case "saml": {
|
||||
return [await getSAMLAuthUrlSS(), true];
|
||||
}
|
||||
case "oidc": {
|
||||
return [await geOIDCAuthUrlSS(), true];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const logoutStandardSS = async (headers: Headers): Promise<Response> => {
|
||||
return await fetch(buildUrl("/auth/logout"), {
|
||||
method: "POST",
|
||||
headers: headers,
|
||||
});
|
||||
};
|
||||
|
||||
const logoutSAMLSS = async (headers: Headers): Promise<Response> => {
|
||||
return await fetch(buildUrl("/auth/saml/logout"), {
|
||||
method: "POST",
|
||||
headers: headers,
|
||||
});
|
||||
};
|
||||
|
||||
export const logoutSS = async (headers: Headers): Promise<Response | null> => {
|
||||
switch (AUTH_TYPE) {
|
||||
case "disabled":
|
||||
return null;
|
||||
case "saml": {
|
||||
return await logoutSAMLSS(headers);
|
||||
}
|
||||
default: {
|
||||
return await logoutStandardSS(headers);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const getCurrentUserSS = async (): Promise<User | null> => {
|
||||
try {
|
||||
const response = await fetch(buildUrl("/users/me"), {
|
||||
const response = await fetch(buildUrl("/manage/me"), {
|
||||
credentials: "include",
|
||||
next: { revalidate: 0 },
|
||||
headers: {
|
||||
|
Reference in New Issue
Block a user