mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2024-09-20 15:26:15 +08:00
moved firebase admin into its own module
not initialising if ther eis no service account this allows the backend server to be ran without firebase (all though it will throw errors) closes #4190
This commit is contained in:
parent
942df911bd
commit
c6d0070dd3
|
@ -20,6 +20,7 @@ import { v4 as uuidv4 } from "uuid";
|
|||
import { ObjectId } from "mongodb";
|
||||
import * as ReportDAL from "../../dal/report";
|
||||
import emailQueue from "../../queues/email-queue";
|
||||
import FirebaseAdmin from "../../init/firebase-admin";
|
||||
|
||||
async function verifyCaptcha(captcha: string): Promise<void> {
|
||||
if (!(await verify(captcha))) {
|
||||
|
@ -37,7 +38,7 @@ export async function createNewUser(
|
|||
await verifyCaptcha(captcha);
|
||||
} catch (e) {
|
||||
try {
|
||||
await admin.auth().deleteUser(uid);
|
||||
await FirebaseAdmin().auth().deleteUser(uid);
|
||||
} catch (e) {
|
||||
// user might be deleted on the frontend
|
||||
}
|
||||
|
@ -84,12 +85,14 @@ export async function sendVerificationEmail(
|
|||
|
||||
let link = "";
|
||||
try {
|
||||
link = await admin.auth().generateEmailVerificationLink(email, {
|
||||
url:
|
||||
process.env.MODE === "dev"
|
||||
? "http://localhost:3000"
|
||||
: "https://monkeytype.com",
|
||||
});
|
||||
link = await FirebaseAdmin()
|
||||
.auth()
|
||||
.generateEmailVerificationLink(email, {
|
||||
url:
|
||||
process.env.MODE === "dev"
|
||||
? "http://localhost:3000"
|
||||
: "https://monkeytype.com",
|
||||
});
|
||||
} catch (e) {
|
||||
if (
|
||||
e.code === "auth/internal-error" &&
|
||||
|
@ -121,7 +124,7 @@ export async function sendForgotPasswordEmail(
|
|||
|
||||
let auth;
|
||||
try {
|
||||
auth = await admin.auth().getUserByEmail(email);
|
||||
auth = await FirebaseAdmin().auth().getUserByEmail(email);
|
||||
} catch (e) {
|
||||
if (e.code === "auth/user-not-found") {
|
||||
throw new MonkeyError(404, "User not found");
|
||||
|
@ -134,12 +137,14 @@ export async function sendForgotPasswordEmail(
|
|||
"request forgot password email"
|
||||
);
|
||||
|
||||
const link = await admin.auth().generatePasswordResetLink(email, {
|
||||
url:
|
||||
process.env.MODE === "dev"
|
||||
? "http://localhost:3000"
|
||||
: "https://monkeytype.com",
|
||||
});
|
||||
const link = await FirebaseAdmin()
|
||||
.auth()
|
||||
.generatePasswordResetLink(email, {
|
||||
url:
|
||||
process.env.MODE === "dev"
|
||||
? "http://localhost:3000"
|
||||
: "https://monkeytype.com",
|
||||
});
|
||||
await emailQueue.sendForgotPasswordEmail(email, userInfo.name, link);
|
||||
|
||||
return new MonkeyResponse("Email sent if user was found");
|
||||
|
@ -292,7 +297,7 @@ export async function getUser(
|
|||
if (e.status === 404) {
|
||||
let user;
|
||||
try {
|
||||
user = await admin.auth().getUser(uid);
|
||||
user = await FirebaseAdmin().auth().getUser(uid);
|
||||
//exists, recreate in db
|
||||
await UserDAL.addUser(user.displayName, user.email, uid);
|
||||
userInfo = await UserDAL.getUser(uid, "get user (recreated)");
|
||||
|
|
52
backend/src/init/firebase-admin.ts
Normal file
52
backend/src/init/firebase-admin.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
import admin, { ServiceAccount } from "firebase-admin";
|
||||
import Logger from "../utils/logger";
|
||||
import { readFileSync, existsSync } from "fs";
|
||||
import MonkeyError from "../utils/error";
|
||||
import path from "path";
|
||||
|
||||
const SERVICE_ACCOUNT_PATH = path.join(
|
||||
__dirname,
|
||||
"../credentials/serviceAccountKey.json"
|
||||
);
|
||||
|
||||
export function init(): void {
|
||||
if (!existsSync(SERVICE_ACCOUNT_PATH)) {
|
||||
if (process.env.MODE === "dev") {
|
||||
Logger.warning(
|
||||
"Firebase service account key not found! Continuing in dev mode, but authentication will throw errors."
|
||||
);
|
||||
} else {
|
||||
throw new MonkeyError(
|
||||
500,
|
||||
"Firebase service account key not found! Make sure generate a service account key and place it in credentials/serviceAccountKey.json.",
|
||||
"init() firebase-admin.ts"
|
||||
);
|
||||
}
|
||||
} else {
|
||||
const serviceAccount = JSON.parse(
|
||||
readFileSync(SERVICE_ACCOUNT_PATH, {
|
||||
encoding: "utf8",
|
||||
flag: "r",
|
||||
})
|
||||
);
|
||||
admin.initializeApp({
|
||||
credential: admin.credential.cert(
|
||||
serviceAccount as unknown as ServiceAccount
|
||||
),
|
||||
});
|
||||
Logger.success("Firebase app initialized");
|
||||
}
|
||||
}
|
||||
|
||||
function get(): typeof admin {
|
||||
if (admin.apps.length === 0) {
|
||||
throw new MonkeyError(
|
||||
500,
|
||||
"Firebase app not initialized! Make sure generate a service account key and place it in credentials/serviceAccountKey.json.",
|
||||
"get() firebase-admin.ts"
|
||||
);
|
||||
}
|
||||
return admin;
|
||||
}
|
||||
|
||||
export default get;
|
|
@ -1,7 +1,4 @@
|
|||
import "dotenv/config";
|
||||
import admin, { ServiceAccount } from "firebase-admin";
|
||||
// @ts-ignore
|
||||
import serviceAccount from "./credentials/serviceAccountKey.json"; // eslint-disable-line require-path-exists/exists
|
||||
import * as db from "./init/db";
|
||||
import jobs from "./jobs";
|
||||
import { getLiveConfiguration } from "./init/configuration";
|
||||
|
@ -15,6 +12,7 @@ import queues from "./queues";
|
|||
import workers from "./workers";
|
||||
import Logger from "./utils/logger";
|
||||
import * as EmailClient from "./init/email-client";
|
||||
import { init as initFirebaseAdmin } from "./init/firebase-admin";
|
||||
|
||||
async function bootServer(port: number): Promise<Server> {
|
||||
try {
|
||||
|
@ -25,12 +23,7 @@ async function bootServer(port: number): Promise<Server> {
|
|||
Logger.success("Connected to database");
|
||||
|
||||
Logger.info("Initializing Firebase app instance...");
|
||||
admin.initializeApp({
|
||||
credential: admin.credential.cert(
|
||||
serviceAccount as unknown as ServiceAccount
|
||||
),
|
||||
});
|
||||
Logger.success("Firebase app initialized");
|
||||
initFirebaseAdmin();
|
||||
|
||||
Logger.info("Fetching live configuration...");
|
||||
const liveConfiguration = await getLiveConfiguration();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import admin from "firebase-admin";
|
||||
import FirebaseAdmin from "./../init/firebase-admin";
|
||||
import { UserRecord } from "firebase-admin/lib/auth/user-record";
|
||||
import { DecodedIdToken } from "firebase-admin/lib/auth/token-verifier";
|
||||
import LRUCache from "lru-cache";
|
||||
|
@ -22,7 +22,7 @@ export async function verifyIdToken(
|
|||
noCache = false
|
||||
): Promise<DecodedIdToken> {
|
||||
if (noCache) {
|
||||
return await admin.auth().verifyIdToken(idToken, true);
|
||||
return await FirebaseAdmin().auth().verifyIdToken(idToken, true);
|
||||
}
|
||||
|
||||
setTokenCacheLength(tokenCache.size);
|
||||
|
@ -44,7 +44,7 @@ export async function verifyIdToken(
|
|||
recordTokenCacheAccess("miss");
|
||||
}
|
||||
|
||||
const decoded = await admin.auth().verifyIdToken(idToken, true);
|
||||
const decoded = await FirebaseAdmin().auth().verifyIdToken(idToken, true);
|
||||
tokenCache.set(idToken, decoded);
|
||||
return decoded;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ export async function updateUserEmail(
|
|||
uid: string,
|
||||
email: string
|
||||
): Promise<UserRecord> {
|
||||
return await admin.auth().updateUser(uid, {
|
||||
return await FirebaseAdmin().auth().updateUser(uid, {
|
||||
email,
|
||||
emailVerified: false,
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue