Add tenant context (#2596)

* add proper tenant context to background tasks

* update for new session logic

* remove unnecessary functions

* add additional tenant context

* update ports

* proper format / directory structure

* update ports

* ensure tenant context properly passed to ee bg tasks

* add user provisioning

* nit

* validated for multi tenant

* auth

* nit

* nit

* nit

* nit

* validate pruning

* evaluate integration tests

* at long last, validated celery beat

* nit: minor edge case patched

* minor

* validate update

* nit
This commit is contained in:
pablodanswer
2024-10-10 09:34:32 -07:00
committed by GitHub
parent 9be54a2b4c
commit f40c5ca9bd
52 changed files with 1319 additions and 389 deletions

View File

@@ -0,0 +1,45 @@
"use client";
import AuthFlowContainer from "@/components/auth/AuthFlowContainer";
import { REGISTRATION_URL } from "@/lib/constants";
import { Button } from "@tremor/react";
import Link from "next/link";
import { FiLogIn } from "react-icons/fi";
const Page = () => {
return (
<AuthFlowContainer>
<div className="flex flex-col space-y-6">
<h2 className="text-2xl font-bold text-text-900 text-center">
Account Not Found
</h2>
<p className="text-text-700 max-w-md text-center">
We couldn&apos;t find your account in our records. To access Danswer,
you need to either:
</p>
<ul className="list-disc text-left text-text-600 w-full pl-6 mx-auto">
<li>Be invited to an existing Danswer organization</li>
<li>Create a new Danswer organization</li>
</ul>
<div className="flex justify-center">
<Link
href={`${REGISTRATION_URL}/register`}
className="w-full max-w-xs"
>
<Button size="lg" icon={FiLogIn} color="indigo" className="w-full">
Create New Organization
</Button>
</Link>
</div>
<p className="text-sm text-text-500 text-center">
Have an account with a different email?{" "}
<Link href="/auth/login" className="text-indigo-600 hover:underline">
Sign in
</Link>
</p>
</div>
</AuthFlowContainer>
);
};
export default Page;

View File

@@ -1,21 +1,49 @@
"use client";
import AuthFlowContainer from "@/components/auth/AuthFlowContainer";
import { Button } from "@tremor/react";
import Link from "next/link";
import { FiLogIn } from "react-icons/fi";
const Page = () => {
return (
<div className="flex flex-col items-center justify-center h-screen">
<div className="font-bold">
Unable to login, please try again and/or contact an administrator.
<AuthFlowContainer>
<div className="flex flex-col space-y-6 max-w-md mx-auto">
<h2 className="text-2xl font-bold text-text-900 text-center">
Authentication Error
</h2>
<p className="text-text-700 text-center">
We encountered an issue while attempting to log you in.
</p>
<div className="bg-red-50 border border-red-200 rounded-lg p-4 shadow-sm">
<h3 className="text-red-800 font-semibold mb-2">Possible Issues:</h3>
<ul className="space-y-2">
<li className="flex items-center text-red-700">
<div className="w-2 h-2 bg-red-500 rounded-full mr-2"></div>
Incorrect or expired login credentials
</li>
<li className="flex items-center text-red-700">
<div className="w-2 h-2 bg-red-500 rounded-full mr-2"></div>
Temporary authentication system disruption
</li>
<li className="flex items-center text-red-700">
<div className="w-2 h-2 bg-red-500 rounded-full mr-2"></div>
Account access restrictions or permissions
</li>
</ul>
</div>
<Link href="/auth/login" className="w-full">
<Button size="lg" icon={FiLogIn} color="indigo" className="w-full">
Return to Login Page
</Button>
</Link>
<p className="text-sm text-text-500 text-center">
We recommend trying again. If you continue to experience problems,
please reach out to your system administrator for assistance.
</p>
</div>
<Link href="/auth/login" className="w-fit">
<Button className="mt-4" size="xs" icon={FiLogIn}>
Back to login
</Button>
</Link>
</div>
</AuthFlowContainer>
);
};

View File

@@ -6,11 +6,15 @@ import { SettingsContext } from "@/components/settings/SettingsProvider";
export const LoginText = () => {
const settings = useContext(SettingsContext);
if (!settings) {
throw new Error("SettingsContext is not available");
}
// if (!settings) {
// throw new Error("SettingsContext is not available");
// }
return (
<>Log In to {settings?.enterpriseSettings?.application_name || "Danswer"}</>
<>
Log In to{" "}
{(settings && settings?.enterpriseSettings?.application_name) ||
"Danswer"}
</>
);
};

View File

@@ -14,6 +14,7 @@ import Link from "next/link";
import { Logo } from "@/components/Logo";
import { LoginText } from "./LoginText";
import { getSecondsUntilExpiration } from "@/lib/time";
import AuthFlowContainer from "@/components/auth/AuthFlowContainer";
const Page = async ({
searchParams,
@@ -51,7 +52,6 @@ const Page = async ({
if (authTypeMetadata?.requiresVerification && !currentUser.is_verified) {
return redirect("/auth/waiting-on-verification");
}
return redirect("/");
}
@@ -70,46 +70,44 @@ const Page = async ({
}
return (
<main>
<AuthFlowContainer>
<div className="absolute top-10x w-full">
<HealthCheckBanner />
</div>
<div className="min-h-screen flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
<div>
<Logo height={64} width={64} className="mx-auto w-fit" />
{authUrl && authTypeMetadata && (
<>
<h2 className="text-center text-xl text-strong font-bold mt-6">
<LoginText />
</h2>
<SignInButton
authorizeUrl={authUrl}
authType={authTypeMetadata?.authType}
/>
</>
)}
{authTypeMetadata?.authType === "basic" && (
<Card className="mt-4 w-96">
<div className="flex">
<Title className="mb-2 mx-auto font-bold">
<LoginText />
</Title>
</div>
<EmailPasswordForm />
<div className="flex">
<Text className="mt-4 mx-auto">
Don&apos;t have an account?{" "}
<Link href="/auth/signup" className="text-link font-medium">
Create an account
</Link>
</Text>
</div>
</Card>
)}
</div>
<div>
{authUrl && authTypeMetadata && (
<>
<h2 className="text-center text-xl text-strong font-bold">
<LoginText />
</h2>
<SignInButton
authorizeUrl={authUrl}
authType={authTypeMetadata?.authType}
/>
</>
)}
{authTypeMetadata?.authType === "basic" && (
<Card className="mt-4 w-96">
<div className="flex">
<Title className="mb-2 mx-auto font-bold">
<LoginText />
</Title>
</div>
<EmailPasswordForm />
<div className="flex">
<Text className="mt-4 mx-auto">
Don&apos;t have an account?{" "}
<Link href="/auth/signup" className="text-link font-medium">
Create an account
</Link>
</Text>
</div>
</Card>
)}
</div>
</main>
</AuthFlowContainer>
);
};

View File

@@ -11,6 +11,12 @@ export const GET = async (request: NextRequest) => {
const response = await fetch(url.toString());
const setCookieHeader = response.headers.get("set-cookie");
if (response.status === 401) {
return NextResponse.redirect(
new URL("/auth/create-account", getDomain(request))
);
}
if (!setCookieHeader) {
return NextResponse.redirect(new URL("/auth/error", getDomain(request)));
}

View File

@@ -10,6 +10,7 @@ import { EmailPasswordForm } from "../login/EmailPasswordForm";
import { Card, Title, Text } from "@tremor/react";
import Link from "next/link";
import { Logo } from "@/components/Logo";
import { CLOUD_ENABLED } from "@/lib/constants";
const Page = async () => {
// catch cases where the backend is completely unreachable here
@@ -25,6 +26,9 @@ const Page = async () => {
} catch (e) {
console.log(`Some fetch failed for the login page - ${e}`);
}
if (CLOUD_ENABLED) {
return redirect("/auth/login");
}
// simply take the user to the home page if Auth is disabled
if (authTypeMetadata?.authType === "disabled") {

View File

@@ -19,6 +19,8 @@ import { HeaderTitle } from "@/components/header/HeaderTitle";
import { Logo } from "@/components/Logo";
import { UserProvider } from "@/components/user/UserProvider";
import { ProviderContextProvider } from "@/components/chat_search/ProviderContext";
import { redirect } from "next/navigation";
import { headers } from "next/headers";
const inter = Inter({
subsets: ["latin"],
@@ -56,8 +58,6 @@ export default async function RootLayout({
const combinedSettings = await fetchSettingsSS();
if (!combinedSettings) {
// Just display a simple full page error if fetching fails.
return (
<html lang="en" className={`${inter.variable} font-sans`}>
<Head>

View File

@@ -0,0 +1,16 @@
import { Logo } from "../Logo";
export default function AuthFlowContainer({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="flex flex-col items-center justify-center min-h-screen bg-background">
<div className="w-full max-w-md p-8 gap-y-4 bg-white flex items-center flex-col rounded-xl shadow-lg border border-bacgkround-100">
<Logo width={70} height={70} />
{children}
</div>
</div>
);
}

View File

@@ -40,7 +40,7 @@ export async function fetchSettingsSS(): Promise<CombinedSettings | null> {
let settings: Settings;
if (!results[0].ok) {
if (results[0].status === 403) {
if (results[0].status === 403 || results[0].status === 401) {
settings = {
gpu_enabled: false,
chat_page_enabled: true,
@@ -62,7 +62,7 @@ export async function fetchSettingsSS(): Promise<CombinedSettings | null> {
let enterpriseSettings: EnterpriseSettings | null = null;
if (tasks.length > 1) {
if (!results[1].ok) {
if (results[1].status !== 403) {
if (results[1].status !== 403 && results[1].status !== 401) {
throw new Error(
`fetchEnterpriseSettingsSS failed: status=${results[1].status} body=${await results[1].text()}`
);

View File

@@ -55,3 +55,7 @@ export const CUSTOM_ANALYTICS_ENABLED = process.env.CUSTOM_ANALYTICS_SECRET_KEY
export const DISABLE_LLM_DOC_RELEVANCE =
process.env.DISABLE_LLM_DOC_RELEVANCE?.toLowerCase() === "true";
export const CLOUD_ENABLED = process.env.NEXT_PUBLIC_CLOUD_ENABLED;
export const REGISTRATION_URL =
process.env.INTERNAL_URL || "http://127.0.0.1:3001";