Skip to content

Commit 575256f

Browse files
authored
Merge pull request #2 from stackhpc/feat/remote-user-header
Add support for authentication via x-remote headers
2 parents 983bd4f + 07f60cc commit 575256f

File tree

7 files changed

+110
-31
lines changed

7 files changed

+110
-31
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

deployment/helm/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ home: https://www.danswer.ai/
55
sources:
66
- "https://github.com/danswer-ai/danswer"
77
type: application
8-
version: 0.1.0-azimuth.1
8+
version: 0.2.0
99
appVersion: v0.5.10
1010
dependencies:
1111
- name: postgresql

deployment/helm/values.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ appVersionOverride: # e.g "v0.3.93"
1111
# tags to refer to downstream StackHPC-modified images.
1212
# The full image ref will be:
1313
# {{ image-name }}:{{ image-tag or appVersion }}-{{ tagSuffix }}
14-
tagSuffix: stackhpc.1
14+
# tagSuffix: stackhpc.1
15+
tagSuffix: stackhpc.2
1516

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

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)