feat(auth): general auth improvements, added signin/up with google

This commit is contained in:
Waleed Latif
2025-02-16 18:16:05 -08:00
parent fcf2fe5a2d
commit 3db68629ec
3 changed files with 115 additions and 47 deletions

View File

@@ -3,7 +3,7 @@
import { useState } from 'react'
import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { Github } from 'lucide-react'
import { GithubIcon, GoogleIcon } from '@/components/icons'
import { Button } from '@/components/ui/button'
import {
Card,
@@ -49,6 +49,14 @@ export default function LoginPage() {
}
}
async function signInWithGoogle() {
try {
await client.signIn.social({ provider: 'google' })
} catch (err) {
setError('Failed to sign in with Google')
}
}
return (
<main className="flex min-h-screen flex-col items-center justify-center bg-gray-50">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
@@ -60,10 +68,16 @@ export default function LoginPage() {
</CardHeader>
<CardContent>
<div className="grid gap-6">
<Button variant="outline" onClick={signInWithGithub} className="w-full">
<Github className="mr-2 h-4 w-4" />
Continue with GitHub
</Button>
<div className="grid gap-2">
<Button variant="outline" onClick={signInWithGithub} className="w-full">
<GithubIcon className="mr-2 h-4 w-4" />
Continue with GitHub
</Button>
<Button variant="outline" onClick={signInWithGoogle} className="w-full">
<GoogleIcon className="mr-2 h-4 w-4" />
Continue with Google
</Button>
</div>
<div className="relative">
<div className="absolute inset-0 flex items-center">
<span className="w-full border-t" />

View File

@@ -3,6 +3,7 @@
import { useState } from 'react'
import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { GithubIcon, GoogleIcon } from '@/components/icons'
import { Button } from '@/components/ui/button'
import {
Card,
@@ -51,6 +52,22 @@ export default function SignupPage() {
}
}
async function signUpWithGithub() {
try {
await client.signIn.social({ provider: 'github' })
} catch (err) {
addNotification('error', 'Failed to sign up with GitHub', null)
}
}
async function signUpWithGoogle() {
try {
await client.signIn.social({ provider: 'google' })
} catch (err) {
addNotification('error', 'Failed to sign up with Google', null)
}
}
return (
<main className="flex min-h-screen flex-col items-center justify-center bg-gray-50">
<NotificationList />
@@ -61,39 +78,61 @@ export default function SignupPage() {
<CardTitle>Create an account</CardTitle>
<CardDescription>Enter your details to get started</CardDescription>
</CardHeader>
<form onSubmit={onSubmit}>
<CardContent className="space-y-4">
<div className="space-y-2">
<Label htmlFor="name">Name</Label>
<Input id="name" name="name" type="text" required />
<CardContent>
<div className="grid gap-6">
<div className="grid gap-2">
<Button variant="outline" onClick={signUpWithGithub} className="w-full">
<GithubIcon className="mr-2 h-4 w-4" />
Continue with GitHub
</Button>
<Button variant="outline" onClick={signUpWithGoogle} className="w-full">
<GoogleIcon className="mr-2 h-4 w-4" />
Continue with Google
</Button>
</div>
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
name="email"
type="email"
placeholder="name@example.com"
required
/>
<div className="relative">
<div className="absolute inset-0 flex items-center">
<span className="w-full border-t" />
</div>
<div className="relative flex justify-center text-xs uppercase">
<span className="bg-background px-2 text-muted-foreground">Or continue with</span>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="password">Password</Label>
<Input id="password" name="password" type="password" required />
</div>
</CardContent>
<CardFooter className="flex flex-col space-y-4">
<Button type="submit" className="w-full" disabled={isLoading}>
{isLoading ? 'Creating account...' : 'Create account'}
</Button>
<p className="text-sm text-gray-500">
Already have an account?{' '}
<Link href="/login" className="text-primary hover:underline">
Sign in
</Link>
</p>
</CardFooter>
</form>
<form onSubmit={onSubmit}>
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="name">Name</Label>
<Input id="name" name="name" type="text" required />
</div>
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
name="email"
type="email"
placeholder="name@example.com"
required
/>
</div>
<div className="space-y-2">
<Label htmlFor="password">Password</Label>
<Input id="password" name="password" type="password" required />
</div>
<Button type="submit" className="w-full" disabled={isLoading}>
{isLoading ? 'Creating account...' : 'Create account'}
</Button>
</div>
</form>
</div>
</CardContent>
<CardFooter>
<p className="text-sm text-gray-500 text-center w-full">
Already have an account?{' '}
<Link href="/login" className="text-primary hover:underline">
Sign in
</Link>
</p>
</CardFooter>
</Card>
</div>
</main>

View File

@@ -22,6 +22,16 @@ export const auth = betterAuth({
provider: 'pg',
schema,
}),
socialProviders: {
github: {
clientId: process.env.GITHUB_CLIENT_ID as string,
clientSecret: process.env.GITHUB_CLIENT_SECRET as string,
},
google: {
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
},
},
emailAndPassword: {
enabled: true,
requireEmailVerification: true,
@@ -40,10 +50,12 @@ export const auth = betterAuth({
},
},
emailVerification: {
sendVerificationEmail: async ({ user, url }: EmailHandler) => {
console.log('Attempting to send verification email to:', user.email)
console.log('Verification URL:', url)
sendVerificationEmail: async ({ user, url, token }, request) => {
try {
if (!user.email) {
throw new Error('User email is required')
}
const result = await resend.emails.send({
from: 'Sim Studio <onboarding@simstudio.ai>',
to: user.email,
@@ -55,18 +67,21 @@ export const auth = betterAuth({
<p>If you didn't create an account, you can safely ignore this email.</p>
`,
})
console.log('Resend API response:', result)
if (!result) {
throw new Error('Failed to send verification email')
}
} catch (error) {
console.error('Error sending verification email:', error)
console.error('Error sending verification email:', {
error,
user: user.email,
url,
token,
})
throw error
}
},
},
socialProviders: {
github: {
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
},
},
plugins: [nextCookies()],
pages: {
signIn: '/login',