Merge branch 'develop' into feature-report-export

This commit is contained in:
Joao Ramos
2024-01-09 23:33:57 +00:00
41 changed files with 1490 additions and 899 deletions

View File

@@ -0,0 +1,23 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type {NextApiRequest, NextApiResponse} from "next";
import {app} from "@/firebase";
import {getFirestore, collection, getDocs, query, where, setDoc, doc, getDoc, deleteDoc} from "firebase/firestore";
import {withIronSessionApiRoute} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import {uuidv4} from "@firebase/util";
const db = getFirestore(app);
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === "GET") return GET(req, res);
res.status(404).json({ok: false});
}
async function GET(req: NextApiRequest, res: NextApiResponse) {
const {id} = req.query;
const snapshot = await getDoc(doc(db, "codes", id as string));
res.status(200).json({...snapshot.data(), id: snapshot.id});
}

View File

@@ -48,6 +48,8 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
await setDoc(codeRef, {type, code, creator: req.session.user!.id, expiryDate});
if (emails && emails.length > index) {
await setDoc(codeRef, {email: emails[index]}, {merge: true});
const transport = prepareMailer();
const mailOptions = prepareMailOptions(
{

View File

@@ -2,12 +2,16 @@
import type {NextApiRequest, NextApiResponse} from "next";
import {withIronSessionApiRoute} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import axios from "axios";
import axios, {AxiosResponse} from "axios";
import formidable from "formidable-serverless";
import {ref, uploadBytes} from "firebase/storage";
import fs from "fs";
import {storage} from "@/firebase";
import {app, storage} from "@/firebase";
import {doc, getDoc, getFirestore, setDoc} from "firebase/firestore";
import {Stat} from "@/interfaces/user";
import {speakingReverseMarking} from "@/utils/score";
const db = getFirestore(app);
export default withIronSessionApiRoute(handler, sessionOptions);
async function handler(req: NextApiRequest, res: NextApiResponse) {
@@ -36,20 +40,41 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
}),
);
const backendRequest = await axios.post(
`${process.env.BACKEND_URL}/speaking_task_3`,
{answers: uploadingAudios},
res.status(200).json(null);
console.log("🌱 - Still processing");
const backendRequest = await evaluate({answers: uploadingAudios});
console.log("🌱 - Process complete");
const correspondingStat = (await getDoc(doc(db, "stats", fields.id))).data() as Stat;
const solutions = correspondingStat.solutions.map((x) => ({...x, evaluation: backendRequest.data, solution: uploadingAudios}));
await setDoc(
doc(db, "stats", fields.id),
{
headers: {
Authorization: `Bearer ${process.env.BACKEND_JWT}`,
solutions,
score: {
correct: speakingReverseMarking[backendRequest.data.overall],
missing: 0,
total: 100,
},
},
{merge: true},
);
res.status(200).json({...backendRequest.data, answer: uploadingAudios});
console.log("🌱 - Updated the DB");
});
}
async function evaluate(body: {answers: object[]}): Promise<AxiosResponse> {
const backendRequest = await axios.post(`${process.env.BACKEND_URL}/speaking_task_3`, body, {
headers: {
Authorization: `Bearer ${process.env.BACKEND_JWT}`,
},
});
if (typeof backendRequest.data === "string") return evaluate(body);
return backendRequest;
}
export const config = {
api: {
bodyParser: false,

View File

@@ -2,12 +2,16 @@
import type {NextApiRequest, NextApiResponse} from "next";
import {withIronSessionApiRoute} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import axios from "axios";
import axios, {AxiosResponse} from "axios";
import formidable from "formidable-serverless";
import {ref, uploadBytes} from "firebase/storage";
import fs from "fs";
import {storage} from "@/firebase";
import {app, storage} from "@/firebase";
import {doc, getDoc, getFirestore, setDoc} from "firebase/firestore";
import {Stat} from "@/interfaces/user";
import {speakingReverseMarking} from "@/utils/score";
const db = getFirestore(app);
export default withIronSessionApiRoute(handler, sessionOptions);
async function handler(req: NextApiRequest, res: NextApiResponse) {
@@ -26,21 +30,46 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
const binary = fs.readFileSync((audioFile as any).path).buffer;
const snapshot = await uploadBytes(audioFileRef, binary);
const backendRequest = await axios.post(
`${process.env.BACKEND_URL}/speaking_task_3`,
{answers: [{question: fields.question, answer: snapshot.metadata.fullPath}]},
res.status(200).json(null);
console.log("🌱 - Still processing");
const backendRequest = await evaluate({answers: [{question: fields.question, answer: snapshot.metadata.fullPath}]});
fs.rmSync((audioFile as any).path);
console.log("🌱 - Process complete");
const correspondingStat = (await getDoc(doc(db, "stats", fields.id))).data() as Stat;
const solutions = correspondingStat.solutions.map((x) => ({
...x,
evaluation: backendRequest.data,
solution: snapshot.metadata.fullPath,
}));
await setDoc(
doc(db, "stats", fields.id),
{
headers: {
Authorization: `Bearer ${process.env.BACKEND_JWT}`,
solutions,
score: {
correct: speakingReverseMarking[backendRequest.data.overall],
total: 100,
missing: 0,
},
},
{merge: true},
);
fs.rmSync((audioFile as any).path);
res.status(200).json({...backendRequest.data, fullPath: snapshot.metadata.fullPath});
console.log("🌱 - Updated the DB");
});
}
async function evaluate(body: {answers: object[]}): Promise<AxiosResponse> {
const backendRequest = await axios.post(`${process.env.BACKEND_URL}/speaking_task_3`, body, {
headers: {
Authorization: `Bearer ${process.env.BACKEND_JWT}`,
},
});
if (typeof backendRequest.data === "string") return evaluate(body);
return backendRequest;
}
export const config = {
api: {
bodyParser: false,

View File

@@ -1,15 +1,20 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type {NextApiRequest, NextApiResponse} from "next";
import {getFirestore, doc, getDoc} from "firebase/firestore";
import {getFirestore, doc, getDoc, setDoc} from "firebase/firestore";
import {withIronSessionApiRoute} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import axios from "axios";
import axios, {AxiosResponse} from "axios";
import {app} from "@/firebase";
import {Stat} from "@/interfaces/user";
import {writingReverseMarking} from "@/utils/score";
interface Body {
question: string;
answer: string;
id: string;
}
const db = getFirestore(app);
export default withIronSessionApiRoute(handler, sessionOptions);
async function handler(req: NextApiRequest, res: NextApiResponse) {
@@ -18,11 +23,36 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
return;
}
const backendRequest = await axios.post(`${process.env.BACKEND_URL}/writing_task2`, req.body as Body, {
res.status(200).json(null);
console.log("🌱 - Still processing");
const backendRequest = await evaluate(req.body as Body);
console.log("🌱 - Process complete");
const correspondingStat = (await getDoc(doc(db, "stats", req.body.id))).data() as Stat;
const solutions = correspondingStat.solutions.map((x) => ({...x, evaluation: backendRequest.data}));
await setDoc(
doc(db, "stats", (req.body as Body).id),
{
solutions,
score: {
correct: writingReverseMarking[backendRequest.data.overall],
total: 100,
missing: 0,
},
},
{merge: true},
);
console.log("🌱 - Updated the DB");
}
async function evaluate(body: Body): Promise<AxiosResponse> {
const backendRequest = await axios.post(`${process.env.BACKEND_URL}/writing_task2`, body as Body, {
headers: {
Authorization: `Bearer ${process.env.BACKEND_JWT}`,
},
});
res.status(backendRequest.status).json(backendRequest.data);
if (typeof backendRequest.data === "string") return evaluate(body);
return backendRequest;
}

View File

@@ -1,10 +1,12 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type {NextApiRequest, NextApiResponse} from "next";
import {app} from "@/firebase";
import {app, storage} from "@/firebase";
import {getFirestore, collection, getDocs, getDoc, doc, deleteDoc, setDoc} from "firebase/firestore";
import {withIronSessionApiRoute} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import {Group} from "@/interfaces/user";
import {Payment} from "@/interfaces/paypal";
import {deleteObject, ref} from "firebase/storage";
const db = getFirestore(app);
@@ -44,11 +46,14 @@ async function del(req: NextApiRequest, res: NextApiResponse) {
const {id} = req.query as {id: string};
const snapshot = await getDoc(doc(db, "payments", id));
const data = snapshot.data() as Payment;
const user = req.session.user;
if (user.type === "admin" || user.type === "developer") {
await deleteDoc(snapshot.ref);
if (data.commissionTransfer) await deleteObject(ref(storage, data.commissionTransfer));
if (data.corporateTransfer) await deleteObject(ref(storage, data.corporateTransfer));
await deleteDoc(snapshot.ref);
res.status(200).json({ok: true});
return;
}

View File

@@ -1,194 +1,180 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from "next";
import { app, storage } from "@/firebase";
import {
getFirestore,
getDoc,
doc,
updateDoc,
deleteField,
} from "firebase/firestore";
import { withIronSessionApiRoute } from "iron-session/next";
import { sessionOptions } from "@/lib/session";
import { FilesStorage } from "@/interfaces/storage.files";
import type {NextApiRequest, NextApiResponse} from "next";
import {app, storage} from "@/firebase";
import {getFirestore, getDoc, doc, updateDoc, deleteField, setDoc} from "firebase/firestore";
import {withIronSessionApiRoute} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import {FilesStorage} from "@/interfaces/storage.files";
import { Payment } from "@/interfaces/paypal";
import {Payment} from "@/interfaces/paypal";
import fs from "fs";
import {
ref,
uploadBytes,
deleteObject,
getDownloadURL,
} from "firebase/storage";
import {ref, uploadBytes, deleteObject, getDownloadURL} from "firebase/storage";
import formidable from "formidable-serverless";
const db = getFirestore(app);
const getPaymentField = (type: FilesStorage) => {
switch (type) {
case "commission":
return "commissionTransfer";
case "corporate":
return "corporateTransfer";
default:
return null;
}
switch (type) {
case "commission":
return "commissionTransfer";
case "corporate":
return "corporateTransfer";
default:
return null;
}
};
const handleDelete = async (
paymentId: string,
paymentField: "commissionTransfer" | "corporateTransfer"
) => {
const paymentRef = doc(db, "payments", paymentId);
const paymentDoc = await getDoc(paymentRef);
const { [paymentField]: paymentFieldPath } = paymentDoc.data() as Payment;
// Create a reference to the file to delete
const documentRef = ref(storage, paymentFieldPath);
await deleteObject(documentRef);
await updateDoc(paymentRef, {
[paymentField]: deleteField(),
});
const handleDelete = async (paymentId: string, paymentField: "commissionTransfer" | "corporateTransfer") => {
const paymentRef = doc(db, "payments", paymentId);
const paymentDoc = await getDoc(paymentRef);
const {[paymentField]: paymentFieldPath} = paymentDoc.data() as Payment;
// Create a reference to the file to delete
const documentRef = ref(storage, paymentFieldPath);
await deleteObject(documentRef);
await updateDoc(paymentRef, {
[paymentField]: deleteField(),
isPaid: false,
});
};
const handleUpload = async (
req: NextApiRequest,
paymentId: string,
paymentField: "commissionTransfer" | "corporateTransfer"
) =>
new Promise((resolve, reject) => {
const form = formidable({ keepExtensions: true });
form.parse(req, async (err: any, fields: any, files: any) => {
if (err) {
reject(err);
return;
}
try {
const { file } = files;
const fileName = Date.now() + "-" + file.name;
const fileRef = ref(storage, fileName);
const handleUpload = async (req: NextApiRequest, paymentId: string, paymentField: "commissionTransfer" | "corporateTransfer") =>
new Promise((resolve, reject) => {
const form = formidable({keepExtensions: true});
form.parse(req, async (err: any, fields: any, files: any) => {
if (err) {
reject(err);
return;
}
try {
const {file} = files;
const fileName = Date.now() + "-" + file.name;
const fileRef = ref(storage, fileName);
const binary = fs.readFileSync(file.path).buffer;
const snapshot = await uploadBytes(fileRef, binary);
fs.rmSync(file.path);
const binary = fs.readFileSync(file.path).buffer;
const snapshot = await uploadBytes(fileRef, binary);
fs.rmSync(file.path);
const paymentRef = doc(db, "payments", paymentId);
const paymentRef = doc(db, "payments", paymentId);
await updateDoc(paymentRef, {
[paymentField]: snapshot.ref.fullPath,
});
resolve(snapshot.ref.fullPath);
} catch (err) {
reject(err);
}
});
});
await updateDoc(paymentRef, {
[paymentField]: snapshot.ref.fullPath,
});
resolve(snapshot.ref.fullPath);
} catch (err) {
reject(err);
}
});
});
export default withIronSessionApiRoute(handler, sessionOptions);
async function handler(req: NextApiRequest, res: NextApiResponse) {
if (!req.session.user) {
res.status(401).json({ ok: false });
return;
}
if (!req.session.user) {
res.status(401).json({ok: false});
return;
}
if (req.method === "GET") return await get(req, res);
if (req.method === "POST") return await post(req, res);
if (req.method === "DELETE") return await del(req, res);
if (req.method === "PATCH") return await patch(req, res);
if (req.method === "GET") return await get(req, res);
if (req.method === "POST") return await post(req, res);
if (req.method === "DELETE") return await del(req, res);
if (req.method === "PATCH") return await patch(req, res);
res.status(404).json(undefined);
res.status(404).json(undefined);
}
async function get(req: NextApiRequest, res: NextApiResponse) {
const { type, paymentId } = req.query as {
type: FilesStorage;
paymentId: string;
};
const paymentField = getPaymentField(type);
const {type, paymentId} = req.query as {
type: FilesStorage;
paymentId: string;
};
const paymentField = getPaymentField(type);
if (paymentField === null) {
res.status(500).json({ error: "Failed to identify payment field" });
return;
}
const paymentRef = doc(db, "payments", paymentId);
const { [paymentField]: paymentFieldPath } = (
await getDoc(paymentRef)
).data() as Payment;
if (paymentField === null) {
res.status(500).json({error: "Failed to identify payment field"});
return;
}
const paymentRef = doc(db, "payments", paymentId);
const {[paymentField]: paymentFieldPath} = (await getDoc(paymentRef)).data() as Payment;
// Create a reference to the file to delete
const documentRef = ref(storage, paymentFieldPath);
const url = await getDownloadURL(documentRef);
res.status(200).json({ url, name: documentRef.name });
// Create a reference to the file to delete
const documentRef = ref(storage, paymentFieldPath);
const url = await getDownloadURL(documentRef);
res.status(200).json({url, name: documentRef.name});
}
async function post(req: NextApiRequest, res: NextApiResponse) {
const { type, paymentId } = req.query as {
type: FilesStorage;
paymentId: string;
};
const paymentField = getPaymentField(type);
const {type, paymentId} = req.query as {
type: FilesStorage;
paymentId: string;
};
const paymentField = getPaymentField(type);
if (paymentField === null) {
res.status(500).json({ error: "Failed to identify payment field" });
return;
}
if (paymentField === null) {
res.status(500).json({error: "Failed to identify payment field"});
return;
}
try {
const ref = await handleUpload(req, paymentId, paymentField);
res.status(200).json({ ref });
} catch (error) {
res.status(500).json({ error });
}
try {
const ref = await handleUpload(req, paymentId, paymentField);
const updatedDoc = (await getDoc(doc(db, "payments", paymentId))).data() as Payment;
if (updatedDoc.commissionTransfer && updatedDoc.corporateTransfer) {
await setDoc(doc(db, "payments", paymentId), {isPaid: true}, {merge: true});
}
res.status(200).json({ref});
} catch (error) {
res.status(500).json({error});
}
}
async function del(req: NextApiRequest, res: NextApiResponse) {
const { type, paymentId } = req.query as {
type: FilesStorage;
paymentId: string;
};
const paymentField = getPaymentField(type);
if (paymentField === null) {
res.status(500).json({ error: "Failed to identify payment field" });
return;
}
const {type, paymentId} = req.query as {
type: FilesStorage;
paymentId: string;
};
const paymentField = getPaymentField(type);
if (paymentField === null) {
res.status(500).json({error: "Failed to identify payment field"});
return;
}
try {
await handleDelete(paymentId, paymentField);
res.status(200).json({ ok: true });
} catch (err) {
console.error(err);
res.status(500).json({ error: "Failed to delete file" });
}
try {
await handleDelete(paymentId, paymentField);
res.status(200).json({ok: true});
} catch (err) {
console.error(err);
res.status(500).json({error: "Failed to delete file"});
}
}
async function patch(req: NextApiRequest, res: NextApiResponse) {
const { type, paymentId } = req.query as {
type: FilesStorage;
paymentId: string;
};
const paymentField = getPaymentField(type);
if (paymentField === null) {
res.status(500).json({ error: "Failed to identify payment field" });
return;
}
const {type, paymentId} = req.query as {
type: FilesStorage;
paymentId: string;
};
const paymentField = getPaymentField(type);
if (paymentField === null) {
res.status(500).json({error: "Failed to identify payment field"});
return;
}
try {
await handleDelete(paymentId, paymentField);
} catch (err) {
console.error(err);
res.status(500).json({ error: "Failed to delete file" });
return;
}
try {
await handleDelete(paymentId, paymentField);
} catch (err) {
console.error(err);
res.status(500).json({error: "Failed to delete file"});
return;
}
try {
const ref = await handleUpload(req, paymentId, paymentField);
res.status(200).json({ ref });
} catch (err) {
res.status(500).json({ error: "Failed to upload file" });
}
try {
const ref = await handleUpload(req, paymentId, paymentField);
res.status(200).json({ref});
} catch (err) {
res.status(500).json({error: "Failed to upload file"});
}
}
export const config = {
api: {
bodyParser: false,
},
api: {
bodyParser: false,
},
};

View File

@@ -0,0 +1,23 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type {NextApiRequest, NextApiResponse} from "next";
import {app} from "@/firebase";
import {getFirestore, collection, getDocs, query, where, setDoc, doc, getDoc, deleteDoc} from "firebase/firestore";
import {withIronSessionApiRoute} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import {uuidv4} from "@firebase/util";
const db = getFirestore(app);
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === "GET") return GET(req, res);
res.status(404).json({ok: false});
}
async function GET(req: NextApiRequest, res: NextApiResponse) {
const {id} = req.query;
const snapshot = await getDoc(doc(db, "stats", id as string));
res.status(200).json({...snapshot.data(), id: snapshot.id});
}

View File

@@ -1,29 +1,23 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type {NextApiRequest, NextApiResponse} from "next";
import {app} from "@/firebase";
import {getFirestore, collection, getDocs, query, where, doc, setDoc, addDoc} from "firebase/firestore";
import {getFirestore, collection, getDocs, query, where, setDoc, doc, getDoc, deleteDoc} from "firebase/firestore";
import {withIronSessionApiRoute} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import {uuidv4} from "@firebase/util";
const db = getFirestore(app);
export default withIronSessionApiRoute(handler, sessionOptions);
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === "GET") return GET(req, res);
async function handler(req: NextApiRequest, res: NextApiResponse) {
if (!req.session.user) {
res.status(401).json({ok: false});
return;
}
const {id: user} = req.query;
const q = query(collection(db, "stats"), where("user", "==", user));
const snapshot = await getDocs(q);
res.status(200).json(
snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
})),
);
res.status(404).json({ok: false});
}
async function GET(req: NextApiRequest, res: NextApiResponse) {
const {id} = req.query;
const snapshot = await getDoc(doc(db, "stats", id as string));
res.status(200).json({...snapshot.data(), id: snapshot.id});
}

View File

@@ -42,7 +42,7 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
}
const stats = req.body as Stat[];
await stats.forEach(async (stat) => await addDoc(collection(db, "stats"), stat));
await stats.forEach(async (stat) => await setDoc(doc(db, "stats", stat.id), stat));
const groupedStatsByAssignment = groupBy(
stats.filter((x) => !!x.assignment),

View File

@@ -25,8 +25,8 @@ async function update(req: NextApiRequest, res: NextApiResponse) {
const q = query(collection(db, "stats"), where("user", "==", req.session.user.id));
const stats = (await getDocs(q)).docs.map((doc) => ({
id: doc.id,
...(doc.data() as Stat),
id: doc.id,
})) as Stat[];
const groupedStats = groupBySession(stats);

View File

@@ -0,0 +1,29 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type {NextApiRequest, NextApiResponse} from "next";
import {app} from "@/firebase";
import {getFirestore, collection, getDocs, query, where, doc, setDoc, addDoc} from "firebase/firestore";
import {withIronSessionApiRoute} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
const db = getFirestore(app);
export default withIronSessionApiRoute(handler, sessionOptions);
async function handler(req: NextApiRequest, res: NextApiResponse) {
if (!req.session.user) {
res.status(401).json({ok: false});
return;
}
const {user} = req.query;
const q = query(collection(db, "stats"), where("user", "==", user));
const snapshot = await getDocs(q);
res.status(200).json(
snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
})),
);
}

View File

@@ -4,14 +4,14 @@ import {app, storage} from "@/firebase";
import {getFirestore, collection, getDocs, getDoc, doc, setDoc, query, where} from "firebase/firestore";
import {withIronSessionApiRoute} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import {User} from "@/interfaces/user";
import {Group, User} from "@/interfaces/user";
import {getDownloadURL, getStorage, ref, uploadBytes} from "firebase/storage";
import {getAuth, signInWithEmailAndPassword, updateEmail, updatePassword} from "firebase/auth";
import {errorMessages} from "@/constants/errors";
import moment from "moment";
import ShortUniqueId from "short-unique-id";
import {Payment} from "@/interfaces/paypal";
import { toFixedNumber } from "@/utils/number";
import {toFixedNumber} from "@/utils/number";
const db = getFirestore(app);
const auth = getAuth(app);
@@ -22,10 +22,10 @@ export default withIronSessionApiRoute(handler, sessionOptions);
// but if it is not inserted as a string, some UI components will not work (Invalid Date)
const addPaymentRecord = async (data: any) => {
await setDoc(doc(db, "payments", data.id), data);
}
};
const managePaymentRecords = async (user: User, userId: string | undefined): Promise<boolean> => {
try {
if(user.type === 'corporate' && userId) {
if (user.type === "corporate" && userId) {
const shortUID = new ShortUniqueId();
const data: Payment = {
id: shortUID.randomUUID(8),
@@ -38,34 +38,35 @@ const managePaymentRecords = async (user: User, userId: string | undefined): Pro
isPaid: false,
date: new Date().toISOString(),
};
const corporatePayments = await getDocs(query(collection(db, "payments"), where("corporate", "==", userId)));
if(corporatePayments.docs.length === 0) {
if (corporatePayments.docs.length === 0) {
await addPaymentRecord(data);
return true;
}
const hasPaymentPaidAndExpiring = corporatePayments.docs.filter((doc) => {
const data = doc.data();
return data.isPaid
&& moment().isAfter(moment(user.subscriptionExpirationDate).subtract(30, "days"))
&& moment().isBefore(moment(user.subscriptionExpirationDate));
return (
data.isPaid &&
moment().isAfter(moment(user.subscriptionExpirationDate).subtract(30, "days")) &&
moment().isBefore(moment(user.subscriptionExpirationDate))
);
});
if(hasPaymentPaidAndExpiring.length > 0) {
if (hasPaymentPaidAndExpiring.length > 0) {
await addPaymentRecord(data);
return true;
}
}
return false;
} catch(e) {
} catch (e) {
// if this process fails it should not stop the rest of the process
console.log(e);
return false;
}
}
};
async function handler(req: NextApiRequest, res: NextApiResponse) {
if (!req.session.user) {
@@ -108,6 +109,23 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const credential = await signInWithEmailAndPassword(auth, req.session.user.email, updatedUser.password);
await updateEmail(credential.user, updatedUser.email);
if (req.session.user.type === "student") {
const corporateAdmins = ((await getDocs(collection(db, "users"))).docs.map((x) => ({...x.data(), id: x.id})) as User[])
.filter((x) => x.type === "corporate")
.map((x) => x.id);
const groups = ((await getDocs(collection(db, "groups"))).docs.map((x) => ({...x.data(), id: x.id})) as Group[]).filter(
(x) => x.participants.includes(req.session.user!.id) && corporateAdmins.includes(x.admin),
);
groups.forEach(async (group) => {
await setDoc(
doc(db, "groups", group.id),
{participants: group.participants.filter((x) => x !== req.session.user!.id)},
{merge: true},
);
});
}
} catch {
res.status(400).json({error: "E002", message: errorMessages.E002});
return;