Spaces:
Running
Running
File size: 4,415 Bytes
90f7646 55c2535 90f7646 55c2535 90f7646 55c2535 90f7646 55c2535 90f7646 55c2535 34e0dbf 90f7646 34e0dbf 90f7646 34e0dbf 90f7646 34e0dbf 90f7646 34e0dbf 90f7646 8fbd913 55c2535 91301da 55c2535 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | import { auth, db } from "./firebase.js";
import {
signInWithEmailAndPassword,
createUserWithEmailAndPassword,
signOut
} 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 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;
}
}
/**
* 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));
}
|