mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-09-19 03:58:30 +02:00
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:
45
web/src/app/auth/create-account/page.tsx
Normal file
45
web/src/app/auth/create-account/page.tsx
Normal 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'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;
|
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
@@ -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"}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@@ -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'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't have an account?{" "}
|
||||
<Link href="/auth/signup" className="text-link font-medium">
|
||||
Create an account
|
||||
</Link>
|
||||
</Text>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
</AuthFlowContainer>
|
||||
);
|
||||
};
|
||||
|
||||
|
@@ -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)));
|
||||
}
|
||||
|
@@ -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") {
|
||||
|
@@ -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>
|
||||
|
16
web/src/components/auth/AuthFlowContainer.tsx
Normal file
16
web/src/components/auth/AuthFlowContainer.tsx
Normal 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>
|
||||
);
|
||||
}
|
@@ -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()}`
|
||||
);
|
||||
|
@@ -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";
|
||||
|
Reference in New Issue
Block a user