-
Notifications
You must be signed in to change notification settings - Fork 0
feat: support guest session #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
📝 Changed routes:
|
Very cool feature 👍. Will it be merged with the main branch? |
/codehelper review pls |
const session = await auth(); | ||
|
||
if (!session?.user?.id) { | ||
await signIn('guest', { redirect: false }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Security: Consider adding a rate limit for guest sign-ins to prevent abuse of the anonymous user creation feature.
const session = await auth(); | ||
|
||
if (!session?.user?.id) { | ||
await signIn('guest', { redirect: false }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improvement: Add error handling for the case where signIn('guest')
fails. Currently, if sign-in fails, the code will still try to redirect.
redirect('/'); | ||
} | ||
|
||
return new Response('Unauthorized', { status: 401 }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logic Issue: This response will never be reached because of the redirect above. If the user is not authenticated, they'll be redirected, and if they are authenticated, this endpoint shouldn't return an error.
if (users.length === 0) return null; | ||
// biome-ignore lint: Forbidden non-null assertion. | ||
const passwordsMatch = await compare(password, users[0].password!); | ||
const [user] = await getUser(email); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improvement: Consider destructuring the user object directly from the result of getUser(email)
for cleaner code: const [user = null] = await getUser(email);
@@ -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'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing Import: The useSession
hook is imported but not used at the module level. This should be moved inside the component function.
@@ -36,6 +39,7 @@ export default function Page() { | |||
}); | |||
} else if (state.status === 'success') { | |||
setIsSuccessful(true); | |||
updateSession(); | |||
router.refresh(); | |||
} | |||
}, [state.status]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dependency Warning: You're missing router
and possibly toast
in the dependency array of this useEffect.
@@ -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'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing Import: The useSession
hook is imported but not used at the module level. This should be moved inside the component function.
@@ -37,6 +40,7 @@ export default function Page() { | |||
toast({ type: 'success', description: 'Account created successfully!' }); | |||
|
|||
setIsSuccessful(true); | |||
updateSession(); | |||
router.refresh(); | |||
} | |||
}, [state]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dependency Warning: You're missing router
in the dependency array of this useEffect.
return new Response('Unauthorized', { status: 401 }); | ||
} | ||
|
||
const membershipTier: MembershipTier = anonymousRegex.test( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improvement: Consider extracting the membership tier determination logic to a separate function for better reusability.
messageCount > | ||
entitlementsByMembershipTier[membershipTier].maxMessagesPerDay | ||
) { | ||
return new Response( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UX Suggestion: Consider providing more detailed error information in the 429 response, such as when the user can try again or how many messages they've used.
Loading auth status | ||
</span> | ||
</div> | ||
<div className="animate-spin text-zinc-500"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accessibility: Consider adding an aria-label to the loading spinner for better accessibility.
<ChevronUp className="ml-auto" /> | ||
</SidebarMenuButton> | ||
{status === 'loading' ? ( | ||
<SidebarMenuButton className="data-[state=open]:bg-sidebar-accent bg-background data-[state=open]:text-sidebar-accent-foreground h-10 justify-between"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Performance: The loading state could be optimized by using a skeleton component instead of animating multiple elements.
} else { | ||
signOut({ | ||
redirectTo: '/', | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dependency Warning: You should include isGuest
and possibly status
in the dependency array of the onClick callback to ensure it always has the latest values.
|
||
export const entitlementsByMembershipTier: Record< | ||
MembershipTier, | ||
Entitlements |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Documentation: Consider adding JSDoc comments to explain the purpose and constraints of each membership tier.
@@ -5,3 +5,5 @@ export const isTestEnvironment = Boolean( | |||
process.env.PLAYWRIGHT || | |||
process.env.CI_PLAYWRIGHT, | |||
); | |||
|
|||
export const anonymousRegex = /^anonymous-\d+$/; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Security: The anonymous regex pattern might be too simple. Consider a more robust pattern to ensure it only matches the expected format.
@@ -48,6 +60,22 @@ export async function createUser(email: string, password: string) { | |||
} | |||
} | |||
|
|||
export async function createAnonymousUser() { | |||
const salt = genSaltSync(10); | |||
const hash = hashSync(generateUUID(), salt); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Security: Consider adding a more secure method of generating passwords for anonymous users, possibly using a cryptographically secure random generator.
@@ -405,3 +433,30 @@ export async function updateChatVisiblityById({ | |||
throw error; | |||
} | |||
} | |||
|
|||
export async function getMessageCountByUserId({ | |||
id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Performance: The getMessageCountByUserId
function might benefit from an index on message.createdAt
and chat.userId
for better query performance.
@@ -405,3 +433,30 @@ export async function updateChatVisiblityById({ | |||
throw error; | |||
} | |||
} | |||
|
|||
export async function getMessageCountByUserId({ | |||
id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improvement: Consider using a more descriptive name for differenceInHours
parameter, such as lookbackHours
to better indicate its purpose.
|
||
import { authConfig } from '@/app/(auth)/auth.config'; | ||
export async function middleware(request: NextRequest) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Security: The middleware should check for CSRF tokens for sensitive operations. Consider implementing CSRF protection.
matcher: ['/', '/:id', '/api/:path*', '/login', '/register'], | ||
matcher: [ | ||
'/', | ||
'/chat/:id', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optimization: The matcher pattern is quite broad. Consider being more specific about which routes need authentication to improve performance.
/codehelp