Added propagate status changes
This commit is contained in:
@@ -2,6 +2,7 @@ import {Module} from ".";
|
||||
import {InstructorGender} from "./exam";
|
||||
|
||||
export type User = StudentUser | TeacherUser | CorporateUser | AgentUser | AdminUser | DeveloperUser;
|
||||
export type UserStatus = "active" | "disabled" | "paymentDue";
|
||||
|
||||
export interface BasicUser {
|
||||
email: string;
|
||||
@@ -17,7 +18,7 @@ export interface BasicUser {
|
||||
isVerified: boolean;
|
||||
subscriptionExpirationDate?: null | Date;
|
||||
registrationDate?: Date;
|
||||
status: "active" | "disabled" | "paymentDue";
|
||||
status: UserStatus;
|
||||
}
|
||||
|
||||
export interface StudentUser extends BasicUser {
|
||||
|
||||
@@ -12,6 +12,8 @@ import moment from "moment";
|
||||
import ShortUniqueId from "short-unique-id";
|
||||
import {Payment} from "@/interfaces/paypal";
|
||||
import {toFixedNumber} from "@/utils/number";
|
||||
import { propagateStatusChange } from '@/utils/propagate.user.changes';
|
||||
|
||||
const db = getFirestore(app);
|
||||
const auth = getAuth(app);
|
||||
|
||||
@@ -74,12 +76,20 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
return;
|
||||
}
|
||||
|
||||
const userRef = doc(db, "users", req.query.id ? (req.query.id as string) : req.session.user.id);
|
||||
const queryId = req.query.id as string;
|
||||
|
||||
const userRef = doc(db, "users", queryId ? (queryId as string) : req.session.user.id);
|
||||
const updatedUser = req.body as User & {password?: string; newPassword?: string};
|
||||
|
||||
if (!!req.query.id) {
|
||||
if (!!queryId) {
|
||||
const user = await setDoc(userRef, updatedUser, {merge: true});
|
||||
await managePaymentRecords(updatedUser, updatedUser.id);
|
||||
|
||||
if(updatedUser.status) {
|
||||
// there's no await as this does not affect the user
|
||||
propagateStatusChange(queryId, updatedUser.status);
|
||||
}
|
||||
|
||||
res.status(200).json({ok: true});
|
||||
return;
|
||||
}
|
||||
@@ -132,6 +142,11 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
}
|
||||
}
|
||||
|
||||
if(updatedUser.status) {
|
||||
// there's no await as this does not affect the user
|
||||
propagateStatusChange(req.session.user.id, updatedUser.status);
|
||||
}
|
||||
|
||||
delete updatedUser.password;
|
||||
delete updatedUser.newPassword;
|
||||
|
||||
@@ -140,12 +155,12 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const docUser = await getDoc(doc(db, "users", req.session.user.id));
|
||||
const user = docUser.data() as User;
|
||||
|
||||
if (!req.query.id) {
|
||||
if (!queryId) {
|
||||
req.session.user = {...user, id: req.session.user.id};
|
||||
await req.session.save();
|
||||
}
|
||||
|
||||
await managePaymentRecords(user, req.query.id);
|
||||
await managePaymentRecords(user, queryId);
|
||||
|
||||
res.status(200).json({user});
|
||||
}
|
||||
|
||||
92
src/utils/propagate.user.changes.ts
Normal file
92
src/utils/propagate.user.changes.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
// updating specific user changes other users
|
||||
// for example, updating the status of a corporate user should update the status of all users in the same corporate group
|
||||
import { UserStatus, User } from "../interfaces/user";
|
||||
import {
|
||||
getFirestore,
|
||||
collection,
|
||||
getDocs,
|
||||
getDoc,
|
||||
doc,
|
||||
setDoc,
|
||||
query,
|
||||
where,
|
||||
} from "firebase/firestore";
|
||||
import { app } from "@/firebase";
|
||||
|
||||
const db = getFirestore(app);
|
||||
|
||||
export const propagateStatusChange = (userId: string, status: UserStatus) =>
|
||||
new Promise((resolve, reject) => {
|
||||
getDoc(doc(db, "users", userId))
|
||||
.then((docUser) => {
|
||||
const user = docUser.data() as User;
|
||||
|
||||
// only update the status of the user's groups if the user is a corporate user
|
||||
if (user.type === "corporate") {
|
||||
getDocs(
|
||||
query(collection(db, "groups"), where("admin", "==", userId))
|
||||
).then(async (userGroupsRef) => {
|
||||
const userGroups = userGroupsRef.docs.map((x) => x.data());
|
||||
|
||||
const targetUsers = [
|
||||
...new Set(
|
||||
userGroups.flatMap((g) => g.participants).filter((u) => u)
|
||||
),
|
||||
];
|
||||
|
||||
Promise.all(
|
||||
targetUsers.map(async (targetUserId) => {
|
||||
const ref = await getDoc(doc(db, "users", targetUserId));
|
||||
|
||||
if (!ref.exists()) return null;
|
||||
|
||||
const data = ref.data() as User;
|
||||
return { ...data, id: targetUserId };
|
||||
})
|
||||
)
|
||||
.then((data) => {
|
||||
const filtered = data.filter((x) => {
|
||||
if (x === null) return false;
|
||||
if (x.status === status) return false;
|
||||
if (x.type !== "student") return false;
|
||||
return true;
|
||||
}) as User[];
|
||||
|
||||
if (filtered.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Promise.all(
|
||||
filtered.map((user: User) =>
|
||||
setDoc(
|
||||
doc(db, "users", user.id),
|
||||
{ status },
|
||||
{ merge: true }
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(() => {
|
||||
resolve(true);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
reject(err);
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const error = new Error("User is not a corporate user");
|
||||
console.error(error);
|
||||
reject(error);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user