ENCOA-147: Uploading a batch of multiple users is now unrestricted by firebase auth request quotas
This commit is contained in:
62
package-lock.json
generated
62
package-lock.json
generated
@@ -41,6 +41,7 @@
|
||||
"express-handlebars": "^7.1.2",
|
||||
"firebase": "9.19.1",
|
||||
"firebase-admin": "^11.10.1",
|
||||
"firebase-scrypt": "^2.2.0",
|
||||
"formidable": "^3.5.0",
|
||||
"formidable-serverless": "^1.1.1",
|
||||
"framer-motion": "^9.0.2",
|
||||
@@ -4056,6 +4057,20 @@
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
|
||||
"integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw=="
|
||||
},
|
||||
"node_modules/babel-runtime": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||
"integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
|
||||
"dependencies": {
|
||||
"core-js": "^2.4.0",
|
||||
"regenerator-runtime": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/babel-runtime/node_modules/regenerator-runtime": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
@@ -4619,6 +4634,13 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/core-js": {
|
||||
"version": "2.6.12",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
|
||||
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
|
||||
"deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
|
||||
"hasInstallScript": true
|
||||
},
|
||||
"node_modules/core-util-is": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||
@@ -6224,6 +6246,17 @@
|
||||
"@google-cloud/storage": "^6.9.5"
|
||||
}
|
||||
},
|
||||
"node_modules/firebase-scrypt": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/firebase-scrypt/-/firebase-scrypt-2.2.0.tgz",
|
||||
"integrity": "sha512-36vJZVPFepErsNw+nBjb9cpM9wYPtcxk1bKN//vLdVkNPhaw1cogzwxtMs0s+dYg1gvBDakg2Q4ch8zAWAvnxA==",
|
||||
"dependencies": {
|
||||
"babel-runtime": "^6.26.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/firebase/node_modules/@firebase/util": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.9.3.tgz",
|
||||
@@ -14697,6 +14730,22 @@
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
|
||||
"integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw=="
|
||||
},
|
||||
"babel-runtime": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||
"integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
|
||||
"requires": {
|
||||
"core-js": "^2.4.0",
|
||||
"regenerator-runtime": "^0.11.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"regenerator-runtime": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
@@ -15083,6 +15132,11 @@
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
|
||||
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="
|
||||
},
|
||||
"core-js": {
|
||||
"version": "2.6.12",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
|
||||
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||
@@ -16352,6 +16406,14 @@
|
||||
"uuid": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"firebase-scrypt": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/firebase-scrypt/-/firebase-scrypt-2.2.0.tgz",
|
||||
"integrity": "sha512-36vJZVPFepErsNw+nBjb9cpM9wYPtcxk1bKN//vLdVkNPhaw1cogzwxtMs0s+dYg1gvBDakg2Q4ch8zAWAvnxA==",
|
||||
"requires": {
|
||||
"babel-runtime": "^6.26.0"
|
||||
}
|
||||
},
|
||||
"flat-cache": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
"express-handlebars": "^7.1.2",
|
||||
"firebase": "9.19.1",
|
||||
"firebase-admin": "^11.10.1",
|
||||
"firebase-scrypt": "^2.2.0",
|
||||
"formidable": "^3.5.0",
|
||||
"formidable-serverless": "^1.1.1",
|
||||
"framer-motion": "^9.0.2",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {initializeApp} from "firebase/app";
|
||||
import * as admin from "firebase-admin/app";
|
||||
import {getStorage} from "firebase/storage";
|
||||
import { base64 } from "@firebase/util";
|
||||
|
||||
const stagingServiceAccount = require("@/constants/staging.json");
|
||||
const platformServiceAccount = require("@/constants/platform.json");
|
||||
@@ -22,3 +23,10 @@ export const adminApp = admin.initializeApp(
|
||||
Math.random().toString(),
|
||||
);
|
||||
export const storage = getStorage(app);
|
||||
|
||||
export const firebaseAuthScryptParams = {
|
||||
memCost: Number(process.env.FIREBASE_SCRYPT_MEM_COST),
|
||||
rounds: Number(process.env.FIREBASE_SCRYPT_ROUNDS),
|
||||
saltSeparator: process.env.FIREBASE_SCRYPT_B64_SALT_SEPARATOR!,
|
||||
signerKey: process.env.FIREBASE_SCRYPT_B64_SIGNER_KEY!,
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ export default function BatchCreateUser({user, users, permissions, onFinish}: Pr
|
||||
demographicInformation: {
|
||||
country: countryItem?.countryCode,
|
||||
passport_id: passport_id?.toString().trim() || undefined,
|
||||
phone,
|
||||
phone: phone.toString(),
|
||||
},
|
||||
}
|
||||
: undefined;
|
||||
@@ -161,7 +161,7 @@ export default function BatchCreateUser({user, users, permissions, onFinish}: Pr
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
for (const newUser of newUsers) await axios.post("/api/make_user", {...newUser, type, expiryDate});
|
||||
await axios.post("/api/batch_users", { users: newUsers.map(user => ({...user, type, expiryDate})) });
|
||||
toast.success(`Successfully added ${newUsers.length} user(s)!`);
|
||||
onFinish();
|
||||
} catch {
|
||||
|
||||
61
src/pages/api/batch_users.ts
Normal file
61
src/pages/api/batch_users.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import type {NextApiRequest, NextApiResponse} from "next";
|
||||
import {withIronSessionApiRoute} from "iron-session/next";
|
||||
import {sessionOptions} from "@/lib/session";
|
||||
import { FirebaseScrypt } from 'firebase-scrypt';
|
||||
import { firebaseAuthScryptParams } from "@/firebase";
|
||||
import crypto from 'crypto';
|
||||
import axios from "axios";
|
||||
|
||||
export default withIronSessionApiRoute(handler, sessionOptions);
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
if (req.method === "POST") return post(req, res);
|
||||
|
||||
return res.status(404).json({ok: false});
|
||||
}
|
||||
|
||||
async function post(req: NextApiRequest, res: NextApiResponse) {
|
||||
const maker = req.session.user;
|
||||
if (!maker) {
|
||||
return res.status(401).json({ok: false, reason: "You must be logged in to make user!"});
|
||||
}
|
||||
|
||||
const scrypt = new FirebaseScrypt(firebaseAuthScryptParams)
|
||||
|
||||
const users = req.body.users as {
|
||||
email: string;
|
||||
name: string;
|
||||
type: string;
|
||||
passport_id: string;
|
||||
groupName?: string;
|
||||
corporate?: string;
|
||||
studentID?: string;
|
||||
expiryDate?: string;
|
||||
demographicInformation: {
|
||||
country?: string;
|
||||
passport_id?: string;
|
||||
phone: string;
|
||||
};
|
||||
passwordHash: string | undefined;
|
||||
passwordSalt: string | undefined;
|
||||
}[];
|
||||
|
||||
const usersWithPasswordHashes = await Promise.all(users.map(async (user) => {
|
||||
const currentUser = { ...user };
|
||||
const salt = crypto.randomBytes(16).toString('base64');
|
||||
const hash = await scrypt.hash(user.passport_id, salt);
|
||||
|
||||
currentUser.email = currentUser.email.toLowerCase();
|
||||
currentUser.passwordHash = hash;
|
||||
currentUser.passwordSalt = salt;
|
||||
return currentUser;
|
||||
}));
|
||||
|
||||
const backendRequest = await axios.post(`${process.env.BACKEND_URL}/batch_users`, { makerID: maker.id, users: usersWithPasswordHashes }, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${process.env.BACKEND_JWT}`,
|
||||
},
|
||||
});
|
||||
|
||||
return res.status(backendRequest.status).json(backendRequest.data)
|
||||
}
|
||||
25
yarn.lock
25
yarn.lock
@@ -2344,6 +2344,14 @@ babel-plugin-syntax-jsx@^6.18.0:
|
||||
resolved "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz"
|
||||
integrity sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==
|
||||
|
||||
babel-runtime@^6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz"
|
||||
integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==
|
||||
dependencies:
|
||||
core-js "^2.4.0"
|
||||
regenerator-runtime "^0.11.0"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
|
||||
@@ -2744,6 +2752,11 @@ cookie@^0.5.0:
|
||||
resolved "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz"
|
||||
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
|
||||
|
||||
core-js@^2.4.0:
|
||||
version "2.6.12"
|
||||
resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz"
|
||||
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz"
|
||||
@@ -3676,6 +3689,13 @@ firebase-admin@^11.10.1:
|
||||
"@google-cloud/firestore" "^6.8.0"
|
||||
"@google-cloud/storage" "^6.9.5"
|
||||
|
||||
firebase-scrypt@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.npmjs.org/firebase-scrypt/-/firebase-scrypt-2.2.0.tgz"
|
||||
integrity sha512-36vJZVPFepErsNw+nBjb9cpM9wYPtcxk1bKN//vLdVkNPhaw1cogzwxtMs0s+dYg1gvBDakg2Q4ch8zAWAvnxA==
|
||||
dependencies:
|
||||
babel-runtime "^6.26.0"
|
||||
|
||||
firebase@9.19.1:
|
||||
version "9.19.1"
|
||||
resolved "https://registry.npmjs.org/firebase/-/firebase-9.19.1.tgz"
|
||||
@@ -6139,6 +6159,11 @@ readdirp@~3.6.0:
|
||||
dependencies:
|
||||
picomatch "^2.2.1"
|
||||
|
||||
regenerator-runtime@^0.11.0:
|
||||
version "0.11.1"
|
||||
resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz"
|
||||
integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
|
||||
|
||||
regenerator-runtime@^0.13.11:
|
||||
version "0.13.11"
|
||||
resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz"
|
||||
|
||||
Reference in New Issue
Block a user