From 61e07dae95798ed5c3a4f3d61b207ffad71ada1b Mon Sep 17 00:00:00 2001 From: Carlos-Mesquita Date: Sun, 5 Jan 2025 19:04:08 +0000 Subject: [PATCH] ENCOA-308 --- src/pages/(admin)/Lists/BatchCreateUser.tsx | 34 ++++++++++----------- src/pages/api/batch_users.ts | 5 ++- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/pages/(admin)/Lists/BatchCreateUser.tsx b/src/pages/(admin)/Lists/BatchCreateUser.tsx index 6acc7921..78a4251f 100644 --- a/src/pages/(admin)/Lists/BatchCreateUser.tsx +++ b/src/pages/(admin)/Lists/BatchCreateUser.tsx @@ -22,6 +22,7 @@ import { IoInformationCircleOutline } from "react-icons/io5"; import { FaFileDownload } from "react-icons/fa"; import { HiOutlineDocumentText } from "react-icons/hi"; import UserImportSummary, { ExcelUserDuplicatesMap } from "@/components/ImportSummaries/User"; +import { v4 } from "uuid"; const EMAIL_REGEX = new RegExp(/^[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*@[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*$/); @@ -87,7 +88,7 @@ export default function BatchCreateUser({ user, entities = [], permissions, onFi const [isExpiryDateEnabled, setIsExpiryDateEnabled] = useState(true); const [type, setType] = useState("student"); const [showHelp, setShowHelp] = useState(false); - const [entity, setEntity] = useState<{id: string | null, label: string | null}| undefined>(() => { + const [entity, setEntity] = useState<{ id: string | null, label: string | null } | undefined>(() => { if (!entities?.length) { return undefined; } @@ -307,11 +308,11 @@ export default function BatchCreateUser({ user, entities = [], permissions, onFi })); setNewUsers(newUsersList); - const {data: emailEntityMap} = await axios.post("/api/users/controller?op=getEntities", { + const { data: emailEntityMap } = await axios.post("/api/users/controller?op=getEntities", { emails: dupes.map((x) => x.email) }); const withLabels = dupes.map((u) => ({ - ...u, + ...u, entityLabels: emailEntityMap.find((e: any) => e.email === u.email)?.entityLabels || [] })) setDuplicatedUsers(withLabels); @@ -339,18 +340,17 @@ export default function BatchCreateUser({ user, entities = [], permissions, onFi if (!confirm(`You are about to ${[newUsersSentence, existingUsersSentence].filter((x) => !!x).join(" and ")}, are you sure you want to continue?`)) return; - Promise.all(newUsers.map(async (u) => await axios.post(`/api/invites`, { to: u.id, entity, from: user.id }))) - .then(() => toast.success(`Successfully invited ${newUsers.length} registered student(s)!`)) - .finally(() => { - if (newUsers.length === 0) setIsLoading(false); - }); - if (newUsers.length > 0) { setIsLoading(true); - try { - await axios.post("/api/batch_users", { users: newUsers.map((user) => ({ ...user, type, expiryDate })) }); - toast.success(`Successfully added ${newUsers.length} user(s)!`); + const withIds = newUsers.map((user) => ({ ...user, type, expiryDate, id: v4() })); + await axios.post("/api/batch_users", { users: withIds}); + toast.success(`Successfully added ${withIds.length} user(s)!`); + Promise.all(withIds.map(async (u) => await axios.post(`/api/invites`, { to: u.id, entity: entity?.id, from: user.id }))) + .then(() => toast.success(`Successfully invited ${withIds.length} registered student(s)!`)) + .finally(() => { + if (withIds.length === 0) setIsLoading(false); + }); onFinish(); } catch (e) { console.error(e) @@ -486,14 +486,14 @@ export default function BatchCreateUser({ user, entities = [], permissions, onFi options={entities.map((e) => ({ value: e.id, label: e.label }))} onChange={(e) => { if (!e) { - setEntity(undefined); - return; + setEntity(undefined); + return; } setEntity({ - id: e?.value, - label: e?.label + id: e?.value, + label: e?.label }); - }} + }} isClearable={checkAccess(user, ["admin", "developer"])} /> diff --git a/src/pages/api/batch_users.ts b/src/pages/api/batch_users.ts index e6ca32c4..b64f342c 100644 --- a/src/pages/api/batch_users.ts +++ b/src/pages/api/batch_users.ts @@ -38,7 +38,7 @@ async function post(req: NextApiRequest, res: NextApiResponse) { passport_id?: string; phone: string; }; - entity?: string + entity: { id: string, label: string } entities: { id: string, role: string }[] passwordHash: string | undefined; passwordSalt: string | undefined; @@ -49,11 +49,10 @@ async function post(req: NextApiRequest, res: NextApiResponse) { const salt = crypto.randomBytes(16).toString('base64'); const hash = await scrypt.hash(user.passport_id, salt); - const entity = await getEntityWithRoles(currentUser.entity!) + const entity = await getEntityWithRoles(currentUser.entity!.id) const defaultRole = findBy(entity?.roles || [], "isDefault", true) currentUser.entities = [{ id: entity?.id || "", role: defaultRole?.id || "" }] - delete currentUser.entity currentUser.email = currentUser.email.toLowerCase(); currentUser.passwordHash = hash;