Email magic link login working

This commit is contained in:
Cal Corum 2025-05-07 09:38:46 -05:00
parent 0155b8db90
commit a372724f65
7 changed files with 56 additions and 169 deletions

View File

@ -10,9 +10,7 @@ export default defineNuxtConfig({
},
},
modules: [
// '@nuxtjs/supabase'
],
modules: ['@nuxtjs/supabase'],
css: ['@picocss/pico'],
@ -31,12 +29,16 @@ export default defineNuxtConfig({
runtimeConfig: {
public: {
supabaseKey: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNucGhwbnV2aGp2cXprY2J3emRrIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDU4MTE3ODQsImV4cCI6MjA2MTM4Nzc4NH0.k3V9c2oiG8kufPa3_a4v6UdiGI6ML6-5lH2oifStB3I',
supabaseUrl: 'https://cnphpnuvhjvqzkcbwzdk.supabase.co/rest/v1/'
supabaseUrl: 'https://cnphpnuvhjvqzkcbwzdk.supabase.co'
}
},
// supabase: {
// url: 'https://cnphpnuvhjvqzkcbwzdk.supabase.co',
// key: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNucGhwbnV2aGp2cXprY2J3emRrIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDU4MTE3ODQsImV4cCI6MjA2MTM4Nzc4NH0.k3V9c2oiG8kufPa3_a4v6UdiGI6ML6-5lH2oifStB3I',
// },
supabase: {
redirectOptions: {
login: '/login',
callback: '/confirm',
exclude: ['/'],
saveRedirectToCookie: true,
},
},
})

158
package-lock.json generated
View File

@ -7,7 +7,6 @@
"name": "nuxt-app",
"hasInstallScript": true,
"dependencies": {
"@nuxtjs/axios": "^5.13.6",
"@nuxtjs/supabase": "^1.5.0",
"@picocss/pico": "^2.1.1",
"nuxt": "^3.17.1",
@ -371,15 +370,6 @@
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/runtime": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz",
"integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/template": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.1.tgz",
@ -2515,40 +2505,6 @@
"vue": "^3.3.4"
}
},
"node_modules/@nuxtjs/axios": {
"version": "5.13.6",
"resolved": "https://registry.npmjs.org/@nuxtjs/axios/-/axios-5.13.6.tgz",
"integrity": "sha512-XS+pOE0xsDODs1zAIbo95A0LKlilvJi8YW0NoXYuq3/jjxGgWDxizZ6Yx0AIIjZOoGsXJOPc0/BcnSEUQ2mFBA==",
"license": "MIT",
"dependencies": {
"@nuxtjs/proxy": "^2.1.0",
"axios": "^0.21.1",
"axios-retry": "^3.1.9",
"consola": "^2.15.3",
"defu": "^5.0.0"
}
},
"node_modules/@nuxtjs/axios/node_modules/consola": {
"version": "2.15.3",
"resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz",
"integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==",
"license": "MIT"
},
"node_modules/@nuxtjs/axios/node_modules/defu": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/defu/-/defu-5.0.1.tgz",
"integrity": "sha512-EPS1carKg+dkEVy3qNTqIdp2qV7mUP08nIsupfwQpz++slCVRw7qbQyWvSTig+kFPwz2XXp5/kIIkH+CwrJKkQ==",
"license": "MIT"
},
"node_modules/@nuxtjs/proxy": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@nuxtjs/proxy/-/proxy-2.1.0.tgz",
"integrity": "sha512-/qtoeqXgZ4Mg6LRg/gDUZQrFpOlOdHrol/vQYMnKu3aN3bP90UfOUB3QSDghUUK7OISAJ0xp8Ld78aHyCTcKCQ==",
"license": "MIT",
"dependencies": {
"http-proxy-middleware": "^1.0.6"
}
},
"node_modules/@nuxtjs/supabase": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@nuxtjs/supabase/-/supabase-1.5.0.tgz",
@ -3734,15 +3690,6 @@
"integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
"license": "MIT"
},
"node_modules/@types/http-proxy": {
"version": "1.17.16",
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.16.tgz",
"integrity": "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==",
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/node": {
"version": "22.15.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz",
@ -4625,25 +4572,6 @@
"postcss": "^8.1.0"
}
},
"node_modules/axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.14.0"
}
},
"node_modules/axios-retry": {
"version": "3.9.1",
"resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.9.1.tgz",
"integrity": "sha512-8PJDLJv7qTTMMwdnbMvrLYuvB47M81wRtxQmEdV5w4rgbTXTt+vtPkXwajOfOdSyv/wZICJOC+/UhXH4aQ/R+w==",
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.15.4",
"is-retry-allowed": "^2.2.0"
}
},
"node_modules/b4a": {
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz",
@ -6264,12 +6192,6 @@
"node": ">=6"
}
},
"node_modules/eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
"license": "MIT"
},
"node_modules/events": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
@ -6530,26 +6452,6 @@
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==",
"license": "MIT"
},
"node_modules/follow-redirects": {
"version": "1.15.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"license": "MIT",
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/foreground-child": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
@ -7073,48 +6975,6 @@
"node": ">= 0.8"
}
},
"node_modules/http-proxy": {
"version": "1.18.1",
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
"license": "MIT",
"dependencies": {
"eventemitter3": "^4.0.0",
"follow-redirects": "^1.0.0",
"requires-port": "^1.0.0"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/http-proxy-middleware": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz",
"integrity": "sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg==",
"license": "MIT",
"dependencies": {
"@types/http-proxy": "^1.17.5",
"http-proxy": "^1.18.1",
"is-glob": "^4.0.1",
"is-plain-obj": "^3.0.0",
"micromatch": "^4.0.2"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/http-proxy-middleware/node_modules/is-plain-obj": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
"integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==",
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/http-shutdown": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/http-shutdown/-/http-shutdown-1.2.2.tgz",
@ -7441,18 +7301,6 @@
"@types/estree": "*"
}
},
"node_modules/is-retry-allowed": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz",
"integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==",
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-ssh": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.1.tgz",
@ -9978,12 +9826,6 @@
"integrity": "sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==",
"license": "MIT"
},
"node_modules/requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
"license": "MIT"
},
"node_modules/resolve": {
"version": "2.0.0-next.5",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",

View File

@ -10,6 +10,7 @@
"postinstall": "nuxt prepare"
},
"dependencies": {
"@nuxtjs/supabase": "^1.5.0",
"@picocss/pico": "^2.1.1",
"nuxt": "^3.17.1",
"vue": "^3.5.13",

17
pages/confirm.vue Normal file
View File

@ -0,0 +1,17 @@
<script setup lang="ts">
const user = useSupabaseUser()
const redirectInfo = useSupabaseCookieRedirect()
watch(user, () => {
if (user.value) {
// Get redirect path, and clear it from the cookie
const path = redirectInfo.pluck()
// Redirect to the saved path, or fallback to home
return navigateTo(path || '/')
}
}, { immediate: true })
</script>
<template>
<div>Waiting for login...</div>
</template>

25
pages/login.vue Normal file
View File

@ -0,0 +1,25 @@
<script setup lang="ts">
const supabase = useSupabaseClient()
const email = ref('')
const signInWithOtp = async () => {
const { error } = await supabase.auth.signInWithOtp({
email: email.value,
options: {
emailRedirectTo: 'http://localhost:3000/confirm',
}
})
if (error) console.log(error)
}
</script>
<template>
<div>
<button @click="signInWithOtp">
Sign In with E-Mail
</button>
<input
v-model="email"
type="email"
/>
</div>
</template>

View File

@ -7,7 +7,7 @@
const playerId = route.params.id
const { data, pending, error } = await useFetch<Player[]>(
`${config.public.supabaseUrl}/players?select=*,rarity!inner(*)&id=eq.${playerId}`,
`${config.public.supabaseUrl}/rest/v1/players?select=*,rarity!inner(*)&id=eq.${playerId}`,
{
method: 'GET',
headers: {
@ -17,7 +17,7 @@
}
)
const player = computed(() => data.value?.[0] ?? null)
const player = computed(() => data.value?.[0] ?? {})
console.log('data:')
console.log(data)

View File

@ -4,7 +4,7 @@
const config = useRuntimeConfig()
const { data, pending, error } = await useFetch<Player[]>(
`${config.public.supabaseUrl}/random_player`,
`${config.public.supabaseUrl}/rest/v1/random_player`,
{
method: 'GET',
headers: {