Skip to content

Commit 9b15c3a

Browse files
committed
Merge remote-tracking branch 'upstream/main'
2 parents e4fba2f + f18af23 commit 9b15c3a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2400
-1983
lines changed

app/(auth)/_register/page.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { SubmitButton } from '@/components/submit-button';
99

1010
import { register, type RegisterActionState } from '../actions';
1111
import { toast } from '@/components/toast';
12+
import { useSession } from 'next-auth/react';
1213

1314
export default function Page() {
1415
const router = useRouter();
@@ -23,6 +24,8 @@ export default function Page() {
2324
},
2425
);
2526

27+
const { update: updateSession } = useSession();
28+
2629
useEffect(() => {
2730
if (state.status === 'user_exists') {
2831
toast({ type: 'error', description: 'Account already exists!' });
@@ -37,6 +40,7 @@ export default function Page() {
3740
toast({ type: 'success', description: 'Account created successfully!' });
3841

3942
setIsSuccessful(true);
43+
updateSession();
4044
router.refresh();
4145
}
4246
}, [state]);

app/(auth)/api/auth/guest/route.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { signIn } from '@/app/(auth)/auth';
2+
import { isDevelopmentEnvironment } from '@/lib/constants';
3+
import { getToken } from 'next-auth/jwt';
4+
import { NextResponse } from 'next/server';
5+
6+
export async function GET(request: Request) {
7+
const { searchParams } = new URL(request.url);
8+
const redirectUrl = searchParams.get('redirectUrl') || '/';
9+
10+
const token = await getToken({
11+
req: request,
12+
secret: process.env.AUTH_SECRET,
13+
secureCookie: !isDevelopmentEnvironment,
14+
});
15+
16+
if (token) {
17+
return NextResponse.redirect(new URL('/', request.url));
18+
}
19+
20+
return signIn('guest', { redirect: true, redirectTo: redirectUrl });
21+
}

app/(auth)/auth.config.ts

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,5 @@ export const authConfig = {
99
// added later in auth.ts since it requires bcrypt which is only compatible with Node.js
1010
// while this file is also used in non-Node.js environments
1111
],
12-
callbacks: {
13-
authorized({ auth, request: { nextUrl } }) {
14-
const isLoggedIn = !!auth?.user;
15-
const isOnChat = nextUrl.pathname.startsWith('/');
16-
const isOnRegister = nextUrl.pathname.startsWith('/register');
17-
const isOnLogin = nextUrl.pathname.startsWith('/login');
18-
19-
if (isLoggedIn && (isOnLogin || isOnRegister)) {
20-
return Response.redirect(new URL('/', nextUrl as unknown as URL));
21-
}
22-
23-
if (isOnRegister || isOnLogin) {
24-
return true; // Always allow access to register and login pages
25-
}
26-
27-
if (isOnChat) {
28-
if (isLoggedIn) return true;
29-
return false; // Redirect unauthenticated users to login page
30-
}
31-
32-
if (isLoggedIn) {
33-
return Response.redirect(new URL('/', nextUrl as unknown as URL));
34-
}
35-
36-
return true;
37-
},
38-
},
12+
callbacks: {},
3913
} satisfies NextAuthConfig;

app/(auth)/auth.ts

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,33 @@
11
import { compare } from 'bcrypt-ts';
2-
import NextAuth, { type User, type Session } from 'next-auth';
2+
import NextAuth, { type DefaultSession } from 'next-auth';
33
import Credentials from 'next-auth/providers/credentials';
4+
import { createGuestUser, getUser } from '@/lib/db/queries';
5+
import { authConfig } from './auth.config';
6+
import { DUMMY_PASSWORD } from '@/lib/constants';
7+
import type { DefaultJWT } from 'next-auth/jwt';
48

5-
import { getUser } from '@/lib/db/queries';
9+
export type UserType = 'guest' | 'regular';
610

7-
import { authConfig } from './auth.config';
11+
declare module 'next-auth' {
12+
interface Session extends DefaultSession {
13+
user: {
14+
id: string;
15+
type: UserType;
16+
} & DefaultSession['user'];
17+
}
18+
19+
interface User {
20+
id?: string;
21+
email?: string | null;
22+
type: UserType;
23+
}
24+
}
825

9-
interface ExtendedSession extends Session {
10-
user: User;
26+
declare module 'next-auth/jwt' {
27+
interface JWT extends DefaultJWT {
28+
id: string;
29+
type: UserType;
30+
}
1131
}
1232

1333
export const {
@@ -22,31 +42,48 @@ export const {
2242
credentials: {},
2343
async authorize({ email, password }: any) {
2444
const users = await getUser(email);
25-
if (users.length === 0) return null;
26-
// biome-ignore lint: Forbidden non-null assertion.
27-
const passwordsMatch = await compare(password, users[0].password!);
45+
46+
if (users.length === 0) {
47+
await compare(password, DUMMY_PASSWORD);
48+
return null;
49+
}
50+
51+
const [user] = users;
52+
53+
if (!user.password) {
54+
await compare(password, DUMMY_PASSWORD);
55+
return null;
56+
}
57+
58+
const passwordsMatch = await compare(password, user.password);
59+
2860
if (!passwordsMatch) return null;
29-
return users[0] as any;
61+
62+
return { ...user, type: 'regular' };
63+
},
64+
}),
65+
Credentials({
66+
id: 'guest',
67+
credentials: {},
68+
async authorize() {
69+
const [guestUser] = await createGuestUser();
70+
return { ...guestUser, type: 'guest' };
3071
},
3172
}),
3273
],
3374
callbacks: {
3475
async jwt({ token, user }) {
3576
if (user) {
36-
token.id = user.id;
77+
token.id = user.id as string;
78+
token.type = user.type;
3779
}
3880

3981
return token;
4082
},
41-
async session({
42-
session,
43-
token,
44-
}: {
45-
session: ExtendedSession;
46-
token: any;
47-
}) {
83+
async session({ session, token }) {
4884
if (session.user) {
49-
session.user.id = token.id as string;
85+
session.user.id = token.id;
86+
session.user.type = token.type;
5087
}
5188

5289
return session;

app/(auth)/login/page.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { AuthForm } from '@/components/auth-form';
99
import { SubmitButton } from '@/components/submit-button';
1010

1111
import { login, type LoginActionState } from '../actions';
12+
import { useSession } from 'next-auth/react';
1213

1314
export default function Page() {
1415
const router = useRouter();
@@ -23,6 +24,8 @@ export default function Page() {
2324
},
2425
);
2526

27+
const { update: updateSession } = useSession();
28+
2629
useEffect(() => {
2730
if (state.status === 'failed') {
2831
toast({
@@ -36,6 +39,7 @@ export default function Page() {
3639
});
3740
} else if (state.status === 'success') {
3841
setIsSuccessful(true);
42+
updateSession();
3943
router.refresh();
4044
}
4145
}, [state.status]);

app/(chat)/actions.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use server';
22

3-
import { generateText, Message } from 'ai';
3+
import { generateText, type UIMessage } from 'ai';
44
import { cookies } from 'next/headers';
55
import webpush, { type PushSubscription } from 'web-push';
66

@@ -12,7 +12,7 @@ import {
1212
saveSubscription,
1313
updateChatVisiblityById,
1414
} from '@/lib/db/queries';
15-
import { VisibilityType } from '@/components/visibility-selector';
15+
import type { VisibilityType } from '@/components/visibility-selector';
1616
import { myProvider } from '@/lib/ai/providers';
1717
import { auth } from '../(auth)/auth';
1818

@@ -24,7 +24,7 @@ export async function saveChatModelAsCookie(model: string) {
2424
export async function generateTitleFromUserMessage({
2525
message,
2626
}: {
27-
message: Message;
27+
message: UIMessage;
2828
}) {
2929
const { text: title } = await generateText({
3030
model: myProvider.languageModel('title-model'),

0 commit comments

Comments
 (0)