Spaces:
Running
Running
| import { auth, googleProvider, db } from "./firebase.js"; | |
| import { signInWithPopup, signInWithRedirect, signOut, getRedirectResult } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-auth.js"; | |
| import { | |
| doc, | |
| getDoc, | |
| setDoc, | |
| updateDoc, | |
| collection, | |
| getDocs, | |
| deleteDoc, | |
| serverTimestamp, | |
| query | |
| } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore.js"; | |
| const INSTRUCTORS_COLLECTION = "instructors"; | |
| const SUPER_ADMIN_EMAIL = "t92206@gmail.com"; | |
| /** | |
| * Sign in with Google | |
| */ | |
| export async function signInWithGoogle() { | |
| try { | |
| const result = await signInWithPopup(auth, googleProvider); | |
| return result.user; | |
| } catch (error) { | |
| console.error("Google Sign-In Error:", error); | |
| throw error; | |
| } | |
| } | |
| /** | |
| * Sign in with Google (Redirect Mode) | |
| * Use this if popup is blocked | |
| */ | |
| export async function signInWithGoogleRedirect() { | |
| try { | |
| await signInWithRedirect(auth, googleProvider); | |
| // Does not return value, page will redirect | |
| } catch (error) { | |
| console.error("Google Redirect Error:", error); | |
| throw error; | |
| } | |
| } | |
| /** | |
| * Check for Redirect Result | |
| * Call this on page load to handle redirect callback | |
| */ | |
| export async function handleRedirectResult() { | |
| console.log("Checking for redirect result..."); | |
| try { | |
| const result = await getRedirectResult(auth); | |
| if (result && result.user) { | |
| console.log("Redirect Sign-In Successful:", result.user.email); | |
| return result.user; | |
| } else { | |
| console.log("No redirect result found."); | |
| } | |
| } catch (error) { | |
| console.error("Redirect Result Error:", error); | |
| } | |
| return null; | |
| } | |
| /** | |
| * Sign out | |
| */ | |
| export async function signOutUser() { | |
| try { | |
| await signOut(auth); | |
| } catch (error) { | |
| console.error("Sign Out Error:", error); | |
| throw error; | |
| } | |
| } | |
| /** | |
| * Check if user is an instructor and get permissions | |
| * Bootstraps the Super Admin if not exists | |
| * @param {object} user - Firebase User object | |
| * @returns {Promise<object|null>} Instructor data or null if not authorized | |
| */ | |
| export async function checkInstructorPermission(user) { | |
| if (!user || !user.email) return null; | |
| const email = user.email; | |
| const instructorRef = doc(db, INSTRUCTORS_COLLECTION, email); | |
| const snap = await getDoc(instructorRef); | |
| // Bootstrap Super Admin | |
| if (email === SUPER_ADMIN_EMAIL) { | |
| const adminData = { | |
| name: user.displayName || "Super Admin", | |
| email: email, | |
| role: 'admin', | |
| permissions: ['create_room', 'add_question', 'manage_instructors'], | |
| lastLogin: serverTimestamp() | |
| }; | |
| try { | |
| if (!snap.exists()) { | |
| await setDoc(instructorRef, { | |
| ...adminData, | |
| createdAt: serverTimestamp() | |
| }); | |
| } else { | |
| // Ensure admin always has full permissions | |
| await updateDoc(instructorRef, { | |
| role: 'admin', | |
| permissions: ['create_room', 'add_question', 'manage_instructors'], | |
| lastLogin: serverTimestamp() | |
| }); | |
| } | |
| } catch (e) { | |
| console.warn("Admin bootstrap failed (likely permission issues), but allowing login as admin.", e); | |
| // We continue because we return adminData anyway, effectively granting admin rights in UI. | |
| } | |
| return adminData; | |
| } | |
| if (snap.exists()) { | |
| const data = snap.data(); | |
| await updateDoc(instructorRef, { lastLogin: serverTimestamp() }); | |
| return data; | |
| } | |
| return null; // Not an instructor | |
| } | |
| /** | |
| * Get all instructors (Admin Only) | |
| */ | |
| export async function getInstructors() { | |
| const q = query(collection(db, INSTRUCTORS_COLLECTION)); | |
| const snapshot = await getDocs(q); | |
| return snapshot.docs.map(doc => doc.data()); | |
| } | |
| /** | |
| * Add new instructor (Admin Only) | |
| */ | |
| export async function addInstructor(email, name, permissions) { | |
| const instructorRef = doc(db, INSTRUCTORS_COLLECTION, email); | |
| await setDoc(instructorRef, { | |
| email, | |
| name, | |
| role: 'instructor', | |
| permissions, | |
| createdAt: serverTimestamp() | |
| }); | |
| } | |
| /** | |
| * Update instructor (Admin Only) | |
| */ | |
| export async function updateInstructor(email, data) { | |
| const instructorRef = doc(db, INSTRUCTORS_COLLECTION, email); | |
| await updateDoc(instructorRef, data); | |
| } | |
| /** | |
| * Remove instructor (Admin Only) | |
| */ | |
| export async function removeInstructor(email) { | |
| if (email === SUPER_ADMIN_EMAIL) throw new Error("Cannot remove Super Admin"); | |
| await deleteDoc(doc(db, INSTRUCTORS_COLLECTION, email)); | |
| } | |