优化密码找回流程、管理后台批量操作和上传体验 #2
+6
-1
@@ -7,4 +7,9 @@ if (!supabaseUrl || !supabaseKey) {
|
||||
throw new Error('Missing Supabase environment variables')
|
||||
}
|
||||
|
||||
export const supabase = createClient(supabaseUrl, supabaseKey)
|
||||
export const supabase = createClient(supabaseUrl, supabaseKey, {
|
||||
auth: {
|
||||
// Email confirmation and password recovery are handled by route components.
|
||||
detectSessionInUrl: false,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -22,32 +22,47 @@ function startCountdown() {
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const search = new URLSearchParams(window.location.search)
|
||||
const hash = window.location.hash.slice(1)
|
||||
const params = new URLSearchParams(hash)
|
||||
const code = search.get('code')
|
||||
const accessToken = params.get('access_token')
|
||||
const refreshToken = params.get('refresh_token')
|
||||
const type = params.get('type')
|
||||
const error = params.get('error')
|
||||
const error = search.get('error') ?? params.get('error')
|
||||
|
||||
if (error) {
|
||||
state.value = 'failed'
|
||||
return
|
||||
}
|
||||
|
||||
if (type === 'signup' && accessToken && refreshToken) {
|
||||
if (code || (type === 'signup' && accessToken && refreshToken)) {
|
||||
const confirmClient = createClient(
|
||||
import.meta.env.VITE_SUPABASE_URL,
|
||||
import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY,
|
||||
{
|
||||
auth: {
|
||||
detectSessionInUrl: false,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
const { error: setSessionError } = await confirmClient.auth.setSession({
|
||||
access_token: accessToken,
|
||||
refresh_token: refreshToken,
|
||||
})
|
||||
if (code) {
|
||||
const { error: exchangeError } = await confirmClient.auth.exchangeCodeForSession(code)
|
||||
if (exchangeError) {
|
||||
state.value = 'failed'
|
||||
return
|
||||
}
|
||||
} else {
|
||||
const { error: setSessionError } = await confirmClient.auth.setSession({
|
||||
access_token: accessToken!,
|
||||
refresh_token: refreshToken!,
|
||||
})
|
||||
|
||||
if (setSessionError) {
|
||||
state.value = 'failed'
|
||||
return
|
||||
if (setSessionError) {
|
||||
state.value = 'failed'
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
await confirmClient.auth.signOut()
|
||||
|
||||
@@ -23,6 +23,20 @@ function showInvalidRecoveryLink() {
|
||||
state.value = 'invalid'
|
||||
}
|
||||
|
||||
function getRecoveryParams() {
|
||||
const search = new URLSearchParams(window.location.search)
|
||||
const hash = new URLSearchParams(window.location.hash.slice(1))
|
||||
|
||||
return {
|
||||
code: search.get('code'),
|
||||
accessToken: hash.get('access_token'),
|
||||
refreshToken: hash.get('refresh_token'),
|
||||
type: hash.get('type'),
|
||||
error: search.get('error') ?? hash.get('error'),
|
||||
errorDescription: search.get('error_description') ?? hash.get('error_description'),
|
||||
}
|
||||
}
|
||||
|
||||
function getResetErrorMessage(value: unknown) {
|
||||
const message = value instanceof Error ? value.message : ''
|
||||
if (
|
||||
@@ -47,6 +61,47 @@ function startCountdown() {
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
async function initializeRecoverySession() {
|
||||
const {
|
||||
code,
|
||||
accessToken,
|
||||
refreshToken,
|
||||
type,
|
||||
error: recoveryError,
|
||||
errorDescription,
|
||||
} = getRecoveryParams()
|
||||
|
||||
if (recoveryError || errorDescription) {
|
||||
showInvalidRecoveryLink()
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
if (code) {
|
||||
const { error } = await supabase.auth.exchangeCodeForSession(code)
|
||||
if (error) throw error
|
||||
} else if (type === 'recovery' && accessToken && refreshToken) {
|
||||
const { error } = await supabase.auth.setSession({
|
||||
access_token: accessToken,
|
||||
refresh_token: refreshToken,
|
||||
})
|
||||
if (error) throw error
|
||||
}
|
||||
|
||||
const { data: { session }, error } = await supabase.auth.getSession()
|
||||
if (error || !session?.user) {
|
||||
showInvalidRecoveryLink()
|
||||
return
|
||||
}
|
||||
|
||||
window.history.replaceState(null, '', window.location.pathname)
|
||||
state.value = 'ready'
|
||||
} catch (e) {
|
||||
error.value = getResetErrorMessage(e)
|
||||
state.value = 'invalid'
|
||||
}
|
||||
}
|
||||
|
||||
async function handleResetPassword() {
|
||||
error.value = ''
|
||||
|
||||
@@ -85,14 +140,8 @@ async function handleResetPassword() {
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
const { data: { session }, error: sessionError } = await supabase.auth.getSession()
|
||||
if (sessionError || !session?.user) {
|
||||
showInvalidRecoveryLink()
|
||||
return
|
||||
}
|
||||
|
||||
state.value = 'ready'
|
||||
onMounted(() => {
|
||||
void initializeRecoverySession()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
|
||||
Reference in New Issue
Block a user