Skip to content

Commit b38c49d

Browse files
Check session user id before performing action (vercel#391)
1 parent c2757f8 commit b38c49d

File tree

3 files changed

+62
-36
lines changed

3 files changed

+62
-36
lines changed

app/(chat)/chat/[id]/page.tsx

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,13 @@ export async function generateMetadata({
2323
}
2424

2525
const chat = await getChat(params.id, session.user.id)
26-
return {
27-
title: chat?.title.toString().slice(0, 50) ?? 'Chat'
26+
27+
if (!chat || 'error' in chat) {
28+
redirect('/')
29+
} else {
30+
return {
31+
title: chat?.title.toString().slice(0, 50) ?? 'Chat'
32+
}
2833
}
2934
}
3035

@@ -39,22 +44,22 @@ export default async function ChatPage({ params }: ChatPageProps) {
3944
const userId = session.user.id as string
4045
const chat = await getChat(params.id, userId)
4146

42-
if (!chat) {
47+
if (!chat || 'error' in chat) {
4348
redirect('/')
44-
}
49+
} else {
50+
if (chat?.userId !== session?.user?.id) {
51+
notFound()
52+
}
4553

46-
if (chat?.userId !== session?.user?.id) {
47-
notFound()
54+
return (
55+
<AI initialAIState={{ chatId: chat.id, messages: chat.messages }}>
56+
<Chat
57+
id={chat.id}
58+
session={session}
59+
initialMessages={chat.messages}
60+
missingKeys={missingKeys}
61+
/>
62+
</AI>
63+
)
4864
}
49-
50-
return (
51-
<AI initialAIState={{ chatId: chat.id, messages: chat.messages }}>
52-
<Chat
53-
id={chat.id}
54-
session={session}
55-
initialMessages={chat.messages}
56-
missingKeys={missingKeys}
57-
/>
58-
</AI>
59-
)
6065
}

app/actions.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,18 @@ import { auth } from '@/auth'
88
import { type Chat } from '@/lib/types'
99

1010
export async function getChats(userId?: string | null) {
11+
const session = await auth()
12+
1113
if (!userId) {
1214
return []
1315
}
1416

17+
if (userId !== session?.user?.id) {
18+
return {
19+
error: 'Unauthorized'
20+
}
21+
}
22+
1523
try {
1624
const pipeline = kv.pipeline()
1725
const chats: string[] = await kv.zrange(`user:chat:${userId}`, 0, -1, {
@@ -31,6 +39,14 @@ export async function getChats(userId?: string | null) {
3139
}
3240

3341
export async function getChat(id: string, userId: string) {
42+
const session = await auth()
43+
44+
if (userId !== session?.user?.id) {
45+
return {
46+
error: 'Unauthorized'
47+
}
48+
}
49+
3450
const chat = await kv.hgetall<Chat>(`chat:${id}`)
3551

3652
if (!chat || (userId && chat.userId !== userId)) {
@@ -49,7 +65,7 @@ export async function removeChat({ id, path }: { id: string; path: string }) {
4965
}
5066
}
5167

52-
//Convert uid to string for consistent comparison with session.user.id
68+
// Convert uid to string for consistent comparison with session.user.id
5369
const uid = String(await kv.hget(`chat:${id}`, 'userId'))
5470

5571
if (uid !== session?.user?.id) {

components/sidebar-list.tsx

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { clearChats, getChats } from '@/app/actions'
22
import { ClearHistory } from '@/components/clear-history'
33
import { SidebarItems } from '@/components/sidebar-items'
44
import { ThemeToggle } from '@/components/theme-toggle'
5+
import { redirect } from 'next/navigation'
56
import { cache } from 'react'
67

78
interface SidebarListProps {
@@ -16,23 +17,27 @@ const loadChats = cache(async (userId?: string) => {
1617
export async function SidebarList({ userId }: SidebarListProps) {
1718
const chats = await loadChats(userId)
1819

19-
return (
20-
<div className="flex flex-1 flex-col overflow-hidden">
21-
<div className="flex-1 overflow-auto">
22-
{chats?.length ? (
23-
<div className="space-y-2 px-2">
24-
<SidebarItems chats={chats} />
25-
</div>
26-
) : (
27-
<div className="p-8 text-center">
28-
<p className="text-sm text-muted-foreground">No chat history</p>
29-
</div>
30-
)}
20+
if (!chats || 'error' in chats) {
21+
redirect('/')
22+
} else {
23+
return (
24+
<div className="flex flex-1 flex-col overflow-hidden">
25+
<div className="flex-1 overflow-auto">
26+
{chats?.length ? (
27+
<div className="space-y-2 px-2">
28+
<SidebarItems chats={chats} />
29+
</div>
30+
) : (
31+
<div className="p-8 text-center">
32+
<p className="text-sm text-muted-foreground">No chat history</p>
33+
</div>
34+
)}
35+
</div>
36+
<div className="flex items-center justify-between p-4">
37+
<ThemeToggle />
38+
<ClearHistory clearChats={clearChats} isEnabled={chats?.length > 0} />
39+
</div>
3140
</div>
32-
<div className="flex items-center justify-between p-4">
33-
<ThemeToggle />
34-
<ClearHistory clearChats={clearChats} isEnabled={chats?.length > 0} />
35-
</div>
36-
</div>
37-
)
41+
)
42+
}
3843
}

0 commit comments

Comments
 (0)