Skip to content

Commit 5d0bb22

Browse files
committed
Add x-remote header auth support
1 parent ce3a69a commit 5d0bb22

File tree

5 files changed

+106
-29
lines changed

5 files changed

+106
-29
lines changed

backend/danswer/auth/users.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,12 @@ async def create(
204204
) -> models.UP:
205205
verify_email_is_invited(user_create.email)
206206
verify_email_domain(user_create.email)
207-
if hasattr(user_create, "role"):
208-
user_count = await get_user_count()
209-
if user_count == 0 or user_create.email in get_default_admin_user_emails():
210-
user_create.role = UserRole.ADMIN
211-
else:
212-
user_create.role = UserRole.BASIC
207+
# if hasattr(user_create, "role"):
208+
# user_count = await get_user_count()
209+
# if user_count == 0 or user_create.email in get_default_admin_user_emails():
210+
# user_create.role = UserRole.ADMIN
211+
# else:
212+
# user_create.role = UserRole.BASIC
213213
return await super().create(user_create, safe=safe, request=request) # type: ignore
214214

215215
async def oauth_callback(

backend/danswer/db/auth.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ async def get_user_count() -> int:
4646
# Need to override this because FastAPI Users doesn't give flexibility for backend field creation logic in OAuth flow
4747
class SQLAlchemyUserAdminDB(SQLAlchemyUserDatabase):
4848
async def create(self, create_dict: Dict[str, Any]) -> UP:
49-
user_count = await get_user_count()
50-
if user_count == 0 or create_dict["email"] in get_default_admin_user_emails():
51-
create_dict["role"] = UserRole.ADMIN
52-
else:
53-
create_dict["role"] = UserRole.BASIC
49+
# user_count = await get_user_count()
50+
# if user_count == 0 or create_dict["email"] in get_default_admin_user_emails():
51+
# create_dict["role"] = UserRole.ADMIN
52+
# else:
53+
# create_dict["role"] = UserRole.BASIC
5454
return await super().create(create_dict)
5555

5656

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"use client";
2+
3+
import { usePopup } from "@/components/admin/connectors/Popup";
4+
import { basicLogin, basicSignup } from "@/lib/user";
5+
import { useRouter } from "next/navigation";
6+
import { useEffect } from "react";
7+
import { Spinner } from "@/components/Spinner";
8+
9+
export function HeaderLoginLoading({
10+
user, groups
11+
}: {
12+
user: string;
13+
groups: string[];
14+
}) {
15+
console.log(user, groups);
16+
17+
const router = useRouter();
18+
const { popup, setPopup } = usePopup();
19+
const email = `${user}@default.com`;
20+
const password = `not-used-${window.crypto.randomUUID()}`
21+
const role = groups.includes("/admins") ? "admin" : "basic"
22+
23+
async function tryLogin() {
24+
// TODO: Update user role here if groups have changed?
25+
26+
// TODO: Use other API endpoints here to update user roles
27+
// and check for existence instead of attempting sign up
28+
// Endpoints:
29+
// - /api/manage/users
30+
// - /api/manage/promote-user-to-admin (auth required)
31+
// - /api/manage/demote-admin-to-user (auth required)
32+
33+
// signup every time.
34+
// Ensure user exists
35+
const response = await basicSignup(email, password, role);
36+
if (!response.ok) {
37+
const errorDetail = (await response.json()).detail;
38+
39+
if (errorDetail !== "REGISTER_USER_ALREADY_EXISTS") {
40+
setPopup({
41+
type: "error",
42+
message: `Failed to sign up - ${errorDetail}`,
43+
});
44+
}
45+
}
46+
// Login as user
47+
const loginResponse = await basicLogin(email, password);
48+
if (loginResponse.ok) {
49+
router.push("/");
50+
} else {
51+
const errorDetail = (await loginResponse.json()).detail;
52+
setPopup({
53+
type: "error",
54+
message: `Failed to login - ${errorDetail}`,
55+
});
56+
}
57+
}
58+
59+
useEffect(() => {
60+
tryLogin()
61+
}, []);
62+
63+
return (
64+
<>
65+
{popup}
66+
<Spinner />
67+
</>
68+
);
69+
}

web/src/app/auth/login/page.tsx

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import Link from "next/link";
1414
import { Logo } from "@/components/Logo";
1515
import { LoginText } from "./LoginText";
1616
import { getSecondsUntilExpiration } from "@/lib/time";
17+
import { headers } from 'next/headers';
18+
import { HeaderLoginLoading } from "./HeaderLogin";
1719

1820
const Page = async ({
1921
searchParams,
@@ -69,6 +71,9 @@ const Page = async ({
6971
return redirect(authUrl);
7072
}
7173

74+
const userHeader = headers().get('x-remote-user');
75+
const groupsHeader = headers().get('x-remote-group');
76+
7277
return (
7378
<main>
7479
<div className="absolute top-10x w-full">
@@ -90,23 +95,25 @@ const Page = async ({
9095
</>
9196
)}
9297
{authTypeMetadata?.authType === "basic" && (
93-
<Card className="mt-4 w-96">
94-
<div className="flex">
95-
<Title className="mb-2 mx-auto font-bold">
96-
<LoginText />
97-
</Title>
98-
</div>
99-
<EmailPasswordForm />
100-
<div className="flex">
101-
<Text className="mt-4 mx-auto">
102-
Don&apos;t have an account?{" "}
103-
<Link href="/auth/signup" className="text-link font-medium">
104-
Create an account
105-
</Link>
106-
</Text>
107-
</div>
108-
</Card>
109-
)}
98+
(userHeader && groupsHeader) ?
99+
<HeaderLoginLoading user={userHeader} groups={groupsHeader.split(',')} /> : (
100+
<Card className="mt-4 w-96">
101+
<div className="flex">
102+
<Title className="mb-2 mx-auto font-bold">
103+
<LoginText />
104+
</Title>
105+
</div>
106+
<EmailPasswordForm />
107+
<div className="flex">
108+
<Text className="mt-4 mx-auto">
109+
Don&apos;t have an account?{" "}
110+
<Link href="/auth/signup" className="text-link font-medium">
111+
Create an account
112+
</Link>
113+
</Text>
114+
</div>
115+
</Card>
116+
))}
110117
</div>
111118
</div>
112119
</main>

web/src/lib/user.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export const basicLogin = async (
4242
return response;
4343
};
4444

45-
export const basicSignup = async (email: string, password: string) => {
45+
export const basicSignup = async (email: string, password: string, role = "basic") => {
4646
const response = await fetch("/api/auth/register", {
4747
method: "POST",
4848
credentials: "include",
@@ -53,6 +53,7 @@ export const basicSignup = async (email: string, password: string) => {
5353
email,
5454
username: email,
5555
password,
56+
role,
5657
}),
5758
});
5859
return response;

0 commit comments

Comments
 (0)