feat: support guest session (#919)

This commit is contained in:
Jeremy 2025-04-25 23:40:15 -07:00 committed by GitHub
parent 24cb2ce19b
commit 9279135355
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 741 additions and 288 deletions

View file

@ -0,0 +1,21 @@
import { signIn } from '@/app/(auth)/auth';
import { isDevelopmentEnvironment } from '@/lib/constants';
import { getToken } from 'next-auth/jwt';
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const redirectUrl = searchParams.get('redirectUrl') || '/';
const token = await getToken({
req: request,
secret: process.env.AUTH_SECRET,
secureCookie: !isDevelopmentEnvironment,
});
if (token) {
return NextResponse.redirect(new URL('/', request.url));
}
return signIn('guest', { redirect: true, redirectTo: redirectUrl });
}

View file

@ -9,31 +9,5 @@ export const authConfig = {
// added later in auth.ts since it requires bcrypt which is only compatible with Node.js
// while this file is also used in non-Node.js environments
],
callbacks: {
authorized({ auth, request: { nextUrl } }) {
const isLoggedIn = !!auth?.user;
const isOnChat = nextUrl.pathname.startsWith('/');
const isOnRegister = nextUrl.pathname.startsWith('/register');
const isOnLogin = nextUrl.pathname.startsWith('/login');
if (isLoggedIn && (isOnLogin || isOnRegister)) {
return Response.redirect(new URL('/', nextUrl as unknown as URL));
}
if (isOnRegister || isOnLogin) {
return true; // Always allow access to register and login pages
}
if (isOnChat) {
if (isLoggedIn) return true;
return false; // Redirect unauthenticated users to login page
}
if (isLoggedIn) {
return Response.redirect(new URL('/', nextUrl as unknown as URL));
}
return true;
},
},
callbacks: {},
} satisfies NextAuthConfig;

View file

@ -1,14 +1,33 @@
import { compare } from 'bcrypt-ts';
import NextAuth, { type User, type Session } from 'next-auth';
import NextAuth, { type DefaultSession } from 'next-auth';
import Credentials from 'next-auth/providers/credentials';
import { getUser } from '@/lib/db/queries';
import { createGuestUser, getUser } from '@/lib/db/queries';
import { authConfig } from './auth.config';
import { DUMMY_PASSWORD } from '@/lib/constants';
import type { DefaultJWT } from 'next-auth/jwt';
interface ExtendedSession extends Session {
user: User;
export type UserType = 'guest' | 'regular';
declare module 'next-auth' {
interface Session extends DefaultSession {
user: {
id: string;
type: UserType;
} & DefaultSession['user'];
}
interface User {
id?: string;
email?: string | null;
type: UserType;
}
}
declare module 'next-auth/jwt' {
interface JWT extends DefaultJWT {
id: string;
type: UserType;
}
}
export const {
@ -40,27 +59,31 @@ export const {
if (!passwordsMatch) return null;
return user as any;
return { ...user, type: 'regular' };
},
}),
Credentials({
id: 'guest',
credentials: {},
async authorize() {
const [guestUser] = await createGuestUser();
return { ...guestUser, type: 'guest' };
},
}),
],
callbacks: {
async jwt({ token, user }) {
if (user) {
token.id = user.id;
token.id = user.id as string;
token.type = user.type;
}
return token;
},
async session({
session,
token,
}: {
session: ExtendedSession;
token: any;
}) {
async session({ session, token }) {
if (session.user) {
session.user.id = token.id as string;
session.user.id = token.id;
session.user.type = token.type;
}
return session;

View file

@ -9,6 +9,7 @@ import { AuthForm } from '@/components/auth-form';
import { SubmitButton } from '@/components/submit-button';
import { login, type LoginActionState } from '../actions';
import { useSession } from 'next-auth/react';
export default function Page() {
const router = useRouter();
@ -23,6 +24,8 @@ export default function Page() {
},
);
const { update: updateSession } = useSession();
useEffect(() => {
if (state.status === 'failed') {
toast({
@ -36,6 +39,7 @@ export default function Page() {
});
} else if (state.status === 'success') {
setIsSuccessful(true);
updateSession();
router.refresh();
}
}, [state.status]);

View file

@ -9,6 +9,7 @@ import { SubmitButton } from '@/components/submit-button';
import { register, type RegisterActionState } from '../actions';
import { toast } from '@/components/toast';
import { useSession } from 'next-auth/react';
export default function Page() {
const router = useRouter();
@ -23,6 +24,8 @@ export default function Page() {
},
);
const { update: updateSession } = useSession();
useEffect(() => {
if (state.status === 'user_exists') {
toast({ type: 'error', description: 'Account already exists!' });
@ -37,6 +40,7 @@ export default function Page() {
toast({ type: 'success', description: 'Account created successfully!' });
setIsSuccessful(true);
updateSession();
router.refresh();
}
}, [state]);