Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 1x 1x 26x 26x 7x 7x 7x 7x 26x 26x 1x 26x 26x | import { readFileSync } from "node:fs";
import { type App, cert, getApps, initializeApp } from "firebase-admin/app";
import { getAuth } from "firebase-admin/auth";
/** Живая проверка подтверждения email по uid (источник правды — Firebase Auth). */
export type EmailVerifiedChecker = (uid: string) => Promise<boolean>;
let cached: App | null | undefined;
/** Ленивая инициализация Admin SDK из service-account JSON. null — если не настроено/ошибка. */
function getApp(path: string | undefined): App | null {
if (cached !== undefined) return cached;
if (!path) {
cached = null;
return cached;
}
try {
const json = JSON.parse(readFileSync(path, "utf8")) as Record<string, unknown>;
cached = getApps().length > 0 ? getApps()[0]! : initializeApp({ credential: cert(json) });
} catch (err) {
console.error("firebase-admin init failed:", err);
cached = null;
}
return cached;
}
/**
* Возвращает функцию живой проверки `email_verified` по uid, либо null, если Admin SDK
* не настроен (тогда гейт работает только по claim из токена).
*
* Нужна, потому что `email_verified` в уже выданном ID-токене не обновляется после
* подтверждения почты (по ссылке из письма ИЛИ админом) — только при ре-логине. Сверка
* с Firebase сразу разблокирует лайки/избранное/загрузку без перелогина.
*/
export function createEmailVerifiedChecker(path: string | undefined): EmailVerifiedChecker | null {
const app = getApp(path);
if (!app) return null;
const auth = getAuth(app);
return async (uid: string): Promise<boolean> => {
try {
const user = await auth.getUser(uid);
return user.emailVerified;
} catch {
return false;
}
};
}
|