Fix AUTH_TYPE env variable bug on frontend

This commit is contained in:
Weves 2023-10-03 16:58:19 -07:00 committed by Chris Weaver
parent 29a0a45518
commit 732f5efb12
15 changed files with 81 additions and 60 deletions

View File

@ -89,14 +89,12 @@ services:
dockerfile: Dockerfile
args:
- NEXT_PUBLIC_DISABLE_STREAMING=${NEXT_PUBLIC_DISABLE_STREAMING:-false}
- NEXT_PUBLIC_AUTH_TYPE=${AUTH_TYPE:-disabled}
depends_on:
- api_server
restart: always
environment:
- INTERNAL_URL=http://api_server:8080
- WEB_DOMAIN=${WEB_DOMAIN:-}
- AUTH_TYPE=${AUTH_TYPE:-disabled}
- OAUTH_NAME=${OAUTH_NAME:-}
relational_db:
image: postgres:15.2-alpine

View File

@ -103,14 +103,12 @@ services:
dockerfile: Dockerfile
args:
- NEXT_PUBLIC_DISABLE_STREAMING=${NEXT_PUBLIC_DISABLE_STREAMING:-false}
- NEXT_PUBLIC_AUTH_TYPE=${AUTH_TYPE:-disabled}
depends_on:
- api_server
restart: always
environment:
- INTERNAL_URL=http://api_server:8080
- WEB_DOMAIN=${WEB_DOMAIN:-}
- AUTH_TYPE=${AUTH_TYPE:-disabled}
- OAUTH_NAME=${OAUTH_NAME:-}
relational_db:
image: postgres:15.2-alpine

View File

@ -59,14 +59,12 @@ services:
dockerfile: Dockerfile
args:
- NEXT_PUBLIC_DISABLE_STREAMING=${NEXT_PUBLIC_DISABLE_STREAMING:-false}
- NEXT_PUBLIC_AUTH_TYPE=${AUTH_TYPE:-google_oauth}
depends_on:
- api_server
restart: always
env_file:
- .env
environment:
- AUTH_TYPE=${AUTH_TYPE:-google_oauth}
- INTERNAL_URL=http://api_server:8080
relational_db:
image: postgres:15.2-alpine

View File

@ -54,14 +54,12 @@ services:
dockerfile: Dockerfile
args:
- NEXT_PUBLIC_DISABLE_STREAMING=${NEXT_PUBLIC_DISABLE_STREAMING:-false}
- NEXT_PUBLIC_AUTH_TYPE=${AUTH_TYPE:-google_oauth}
depends_on:
- api_server
restart: always
env_file:
- .env
environment:
- AUTH_TYPE=${AUTH_TYPE:-google_oauth}
- INTERNAL_URL=http://api_server:8080
relational_db:
image: postgres:15.2-alpine

View File

@ -30,9 +30,6 @@ 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
@ -68,9 +65,6 @@ 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

View File

@ -27,7 +27,6 @@ const Main = () => {
const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
const [filesAreUploading, setFilesAreUploading] = useState<boolean>(false);
const { popup, setPopup } = usePopup();
console.log(popup);
const { mutate } = useSWRConfig();

View File

@ -23,8 +23,7 @@ import {
BookmarkIcon,
CPUIcon,
} from "@/components/icons/icons";
import { DISABLE_AUTH } from "@/lib/constants";
import { getCurrentUserSS } from "@/lib/userSS";
import { getAuthDisabledSS, getCurrentUserSS } from "@/lib/userSS";
import { redirect } from "next/navigation";
export default async function AdminLayout({
@ -32,9 +31,12 @@ export default async function AdminLayout({
}: {
children: React.ReactNode;
}) {
let user = null;
if (!DISABLE_AUTH) {
user = await getCurrentUserSS();
const [authDisabled, user] = await Promise.all([
getAuthDisabledSS(),
getCurrentUserSS(),
]);
if (!authDisabled) {
if (!user) {
return redirect("/auth/login");
}

View File

@ -1,7 +1,7 @@
import { HealthCheckBanner } from "@/components/health/healthcheck";
import { DISABLE_AUTH, OAUTH_NAME } from "@/lib/constants";
import { AuthType, OAUTH_NAME } from "@/lib/constants";
import { User } from "@/lib/types";
import { getCurrentUserSS, getAuthUrlSS } from "@/lib/userSS";
import { getCurrentUserSS, getAuthUrlSS, getAuthTypeSS } from "@/lib/userSS";
import { redirect } from "next/navigation";
const BUTTON_STYLE =
@ -11,33 +11,43 @@ const BUTTON_STYLE =
" mx-auto";
const Page = async () => {
// no need for any of the below if auth is disabled
if (DISABLE_AUTH) {
return redirect("/");
}
// catch cases where the backend is completely unreachable here
// without try / catch, will just raise an exception and the page
// will not render
let authType: AuthType | null = null;
let currentUser: User | null = null;
let authorizationUrl: string | null = null;
let autoRedirect: boolean = false;
try {
[currentUser, [authorizationUrl, autoRedirect]] = await Promise.all([
[authType, currentUser] = await Promise.all([
getAuthTypeSS(),
getCurrentUserSS(),
getAuthUrlSS(),
]);
} catch (e) {
console.log(`Some fetch failed for the login page - ${e}`);
}
// simply take the user to the home page if Auth is disabled
if (authType === "disabled") {
return redirect("/");
}
// if user is already logged in, take them to the main app page
if (currentUser && currentUser.is_active && currentUser.is_verified) {
return redirect("/");
}
if (autoRedirect && authorizationUrl) {
return redirect(authorizationUrl);
// get where to send the user to authenticate
let authUrl: string | null = null;
let autoRedirect: boolean = false;
if (authType) {
try {
[authUrl, autoRedirect] = await getAuthUrlSS(authType);
} catch (e) {
console.log(`Some fetch failed for the login page - ${e}`);
}
}
if (autoRedirect && authUrl) {
return redirect(authUrl);
}
return (
@ -53,9 +63,9 @@ const Page = async () => {
</h2>
</div>
<div className="flex">
{authorizationUrl ? (
{authUrl ? (
<a
href={authorizationUrl || ""}
href={authUrl || ""}
className={
BUTTON_STYLE +
" focus:outline-none focus:ring-2 hover:bg-red-700 focus:ring-offset-2 focus:ring-red-500"

View File

@ -1,8 +1,9 @@
import { logoutSS } from "@/lib/userSS";
import { getAuthTypeSS, 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);
const authType = await getAuthTypeSS();
return await logoutSS(authType, request.headers);
};

View File

@ -12,6 +12,8 @@ export const metadata = {
description: "Question answering for your documents",
};
export const dynamic = "force-dynamic";
export default async function RootLayout({
children,
}: {

View File

@ -1,8 +1,11 @@
import { SearchSection } from "@/components/search/SearchSection";
import { Header } from "@/components/Header";
import { getCurrentUserSS, processCookies } from "@/lib/userSS";
import {
getAuthDisabledSS,
getCurrentUserSS,
processCookies,
} from "@/lib/userSS";
import { redirect } from "next/navigation";
import { DISABLE_AUTH } from "@/lib/constants";
import { HealthCheckBanner } from "@/components/health/healthcheck";
import { ApiKeyModal } from "@/components/openai/ApiKeyModal";
import { buildUrl } from "@/lib/utilsSS";
@ -12,7 +15,8 @@ import { SearchType } from "@/lib/search/interfaces";
export default async function Home() {
const tasks = [
DISABLE_AUTH ? (async () => null)() : getCurrentUserSS(),
getAuthDisabledSS(),
getCurrentUserSS(),
fetch(buildUrl("/manage/connector"), {
next: { revalidate: 0 },
headers: {
@ -30,17 +34,18 @@ export default async function Home() {
// catch cases where the backend is completely unreachable here
// without try / catch, will just raise an exception and the page
// will not render
let results: (User | Response | null)[] = [null, null];
let results: (User | Response | boolean | null)[] = [null, null, null, null];
try {
results = await Promise.all(tasks);
} catch (e) {
console.log(`Some fetch failed for the main search page - ${e}`);
}
const user = results[0] as User | null;
const connectorsResponse = results[1] as Response | null;
const documentSetsResponse = results[2] as Response | null;
const authDisabled = results[0] as boolean;
const user = results[1] as User | null;
const connectorsResponse = results[2] as Response | null;
const documentSetsResponse = results[3] as Response | null;
if (!DISABLE_AUTH && !user) {
if (!authDisabled && !user) {
return redirect("/auth/login");
}

View File

@ -1,6 +1,5 @@
import { Header } from "@/components/Header";
import { DISABLE_AUTH } from "@/lib/constants";
import { getCurrentUserSS } from "@/lib/userSS";
import { getAuthDisabledSS, getCurrentUserSS } from "@/lib/userSS";
import { redirect } from "next/navigation";
export default async function AdminLayout({
@ -8,9 +7,12 @@ export default async function AdminLayout({
}: {
children: React.ReactNode;
}) {
let user = null;
if (!DISABLE_AUTH) {
user = await getCurrentUserSS();
const [authDisabled, user] = await Promise.all([
getAuthDisabledSS(),
getCurrentUserSS(),
]);
if (!authDisabled) {
if (!user) {
return redirect("/auth/login");
}

View File

@ -47,7 +47,6 @@ export const SearchSection: React.FC<SearchSectionProps> = ({
documentSets,
defaultSearchType,
}) => {
console.log(documentSets);
// Search Bar
const [query, setQuery] = useState<string>("");

View File

@ -1,9 +1,5 @@
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";

View File

@ -2,7 +2,21 @@ 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";
import { AuthType } from "./constants";
export const getAuthTypeSS = async (): Promise<AuthType> => {
const res = await fetch(buildUrl("/auth/type"));
if (!res.ok) {
throw new Error("Failed to fetch data");
}
const data: { auth_type: string } = await res.json();
return data.auth_type as AuthType;
};
export const getAuthDisabledSS = async (): Promise<boolean> => {
return (await getAuthTypeSS()) === "disabled";
};
const geOIDCAuthUrlSS = async (): Promise<string> => {
const res = await fetch(buildUrl("/auth/oidc/authorize"));
@ -34,9 +48,11 @@ const getSAMLAuthUrlSS = async (): Promise<string> => {
return data.authorization_url;
};
export const getAuthUrlSS = async (): Promise<[string, boolean]> => {
export const getAuthUrlSS = async (
authType: AuthType
): Promise<[string, boolean]> => {
// Returns the auth url and whether or not we should auto-redirect
switch (AUTH_TYPE) {
switch (authType) {
case "disabled":
return ["", true];
case "google_oauth": {
@ -65,8 +81,11 @@ const logoutSAMLSS = async (headers: Headers): Promise<Response> => {
});
};
export const logoutSS = async (headers: Headers): Promise<Response | null> => {
switch (AUTH_TYPE) {
export const logoutSS = async (
authType: AuthType,
headers: Headers
): Promise<Response | null> => {
switch (authType) {
case "disabled":
return null;
case "saml": {