import { auth, db } from "./firebase.js"; import { signInWithEmailAndPassword, createUserWithEmailAndPassword, signOut, sendPasswordResetEmail, 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"; /** * Handle Redirect Result (for OAuth flows like Google Sign In) */ export async function handleRedirectResult() { try { const result = await getRedirectResult(auth); return result ? result.user : null; } catch (error) { console.error("Redirect Result Error:", error); throw error; } } /** * Sign in with Email/Password */ export async function loginWithEmail(email, password) { try { const result = await signInWithEmailAndPassword(auth, email, password); return result.user; } catch (error) { console.error("Login Error:", error); throw error; } } /** * Register with Email/Password * (Used for new instructors to create their auth account matching their whitelisted email) */ export async function registerWithEmail(email, password) { try { const result = await createUserWithEmailAndPassword(auth, email, password); return result.user; } catch (error) { console.error("Register Error:", error); throw error; } } /** * Send Password Reset Email */ export async function resetPassword(email) { try { await sendPasswordResetEmail(auth, email); } catch (error) { console.error("Reset Password Error:", error); throw error; } } /** * 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} 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); let snap; try { console.log(`[Permission Check] Checking whitelist for email: '${email}'`); snap = await getDoc(instructorRef); console.log(`[Permission Check] Result for '${email}': exists=${snap.exists()}`); } catch (error) { console.warn(`[Permission Check] Failed for '${email}'. Error:`, error); console.warn("Instructor Permission Check Failed (likely not whitelisted):", error.code); // If permission denied, it means they are not allowed to read the doc => likely not in whitelist return null; } // 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(); try { await updateDoc(instructorRef, { lastLogin: serverTimestamp() }); } catch (e) { console.warn("Failed to update lastLogin (likely permission), proceeding anyway.", e); } 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 safeEmail = email.trim(); // Ensure no leading/trailing spaces const instructorRef = doc(db, INSTRUCTORS_COLLECTION, safeEmail); await setDoc(instructorRef, { email: safeEmail, 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)); }