80 lines
2.2 KiB
TypeScript
80 lines
2.2 KiB
TypeScript
import { ref, watchEffect, computed } from 'vue'
|
|
import { auth, db } from '../firebase'
|
|
import { GoogleAuthProvider, signInWithPopup, signOut, type User } from 'firebase/auth'
|
|
import { doc, onSnapshot } from 'firebase/firestore'
|
|
|
|
// Global state
|
|
const user = ref<User | null>(null)
|
|
const isAllowed = ref(false)
|
|
const isLoading = ref(true)
|
|
const error = ref<string | null>(null)
|
|
|
|
// Watch auth state
|
|
auth.onAuthStateChanged((u) => {
|
|
console.log("🔥 Auth State Changed:", u ? u.email : "Logged Out")
|
|
user.value = u
|
|
if (!u) {
|
|
isAllowed.value = false
|
|
isLoading.value = false
|
|
}
|
|
})
|
|
|
|
// Check allowlist
|
|
watchEffect((onCleanup) => {
|
|
if (!user.value) return
|
|
|
|
// Subscribe to the config/allowlist document
|
|
const allowlistRef = doc(db, 'config', 'allowlist')
|
|
const unsubscribe = onSnapshot(allowlistRef, (docSnap) => {
|
|
isLoading.value = false
|
|
if (docSnap.exists()) {
|
|
const data = docSnap.data()
|
|
const emails = data.emails || []
|
|
isAllowed.value = emails.includes(user.value?.email)
|
|
} else {
|
|
isAllowed.value = false // Config doc missing -> deny all
|
|
}
|
|
}, (err) => {
|
|
console.error("Failed to check allowlist", err)
|
|
error.value = "Failed to check allowlist: " + err.message
|
|
isLoading.value = false
|
|
})
|
|
|
|
onCleanup(() => unsubscribe())
|
|
})
|
|
|
|
export function useAuth() {
|
|
const login = async () => {
|
|
error.value = null
|
|
try {
|
|
const provider = new GoogleAuthProvider()
|
|
await signInWithPopup(auth, provider)
|
|
} catch (e: any) {
|
|
console.error("Login failed", e)
|
|
error.value = e.message
|
|
throw e
|
|
}
|
|
}
|
|
|
|
const logout = async () => {
|
|
error.value = null
|
|
try {
|
|
await signOut(auth)
|
|
user.value = null
|
|
isAllowed.value = false
|
|
} catch (e: any) {
|
|
console.error("Logout failed", e)
|
|
error.value = e.message
|
|
}
|
|
}
|
|
|
|
return {
|
|
user,
|
|
isAllowed: computed(() => isAllowed.value),
|
|
isLoading: computed(() => isLoading.value),
|
|
error: computed(() => error.value),
|
|
login,
|
|
logout
|
|
}
|
|
}
|