All files / src/lib firebase-admin.ts

43.33% Statements 13/30
55.55% Branches 5/9
100% Functions 2/2
43.33% Lines 13/30

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 481x             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;
    }
  };
}