Solved some problems, bypassed some stuff

This commit is contained in:
Tiago Ribeiro
2024-09-08 11:35:09 +01:00
parent e3847baadb
commit 620e4dd787
23 changed files with 1259 additions and 1538 deletions

View File

@@ -1,17 +1,17 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from "next";
import { app, storage } from "@/firebase";
import { withIronSessionApiRoute } from "iron-session/next";
import { sessionOptions } from "@/lib/session";
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 type {NextApiRequest, NextApiResponse} from "next";
import {app, storage} from "@/firebase";
import {withIronSessionApiRoute} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
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 { propagateExpiryDateChanges, propagateStatusChange } from "@/utils/propagate.user.changes";
import {Payment} from "@/interfaces/paypal";
import {toFixedNumber} from "@/utils/number";
import {propagateExpiryDateChanges, propagateStatusChange} from "@/utils/propagate.user.changes";
import client from "@/lib/mongodb";
const db = client.db(process.env.MONGODB_DB);
@@ -41,7 +41,7 @@ const managePaymentRecords = async (user: User, userId: string | undefined): Pro
date: new Date().toISOString(),
};
const corporatePayments = await db.collection("payments").find({ corporate: userId }).toArray();
const corporatePayments = await db.collection("payments").find({corporate: userId}).toArray();
if (corporatePayments.length === 0) {
await addPaymentRecord(data);
return true;
@@ -71,20 +71,17 @@ const managePaymentRecords = async (user: User, userId: string | undefined): Pro
async function handler(req: NextApiRequest, res: NextApiResponse) {
if (!req.session.user) {
res.status(401).json({ ok: false });
res.status(401).json({ok: false});
return;
}
const queryId = req.query.id as string;
let user = await db.collection("users").findOne<User>({ id: queryId ? (queryId as string) : req.session.user.id });
const updatedUser = req.body as User & { password?: string; newPassword?: string };
let user = await db.collection("users").findOne<User>({id: queryId ? (queryId as string) : req.session.user.id});
const updatedUser = req.body as User & {password?: string; newPassword?: string};
if (!!queryId) {
await db.collection("users").updateOne(
{ id: queryId },
{ $set: updatedUser }
);
await db.collection("users").updateOne({id: queryId}, {$set: updatedUser});
await managePaymentRecords(updatedUser, updatedUser.id);
if (updatedUser.status || updatedUser.type === "corporate") {
@@ -93,7 +90,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
propagateExpiryDateChanges(queryId, user?.subscriptionExpirationDate, updatedUser.subscriptionExpirationDate || null);
}
res.status(200).json({ ok: true });
res.status(200).json({ok: true});
return;
}
@@ -113,17 +110,17 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
const credential = await signInWithEmailAndPassword(auth, req.session.user.email, updatedUser.password);
await updatePassword(credential.user, updatedUser.newPassword);
} catch {
res.status(400).json({ error: "E001", message: errorMessages.E001 });
res.status(400).json({error: "E001", message: errorMessages.E001});
return;
}
}
if (updatedUser.email !== req.session.user.email && updatedUser.password) {
try {
const usersWithSameEmail = await db.collection("users").find({ email: updatedUser.email.toLowerCase() }).toArray();
const usersWithSameEmail = await db.collection("users").find({email: updatedUser.email.toLowerCase()}).toArray();
if (usersWithSameEmail.length > 0) {
res.status(400).json({ error: "E003", message: errorMessages.E003 });
res.status(400).json({error: "E003", message: errorMessages.E003});
return;
}
@@ -131,22 +128,24 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
await updateEmail(credential.user, updatedUser.email);
if (req.session.user.type === "student") {
const corporateAdmins = (await db.collection("users").find<User>({ type: "corporate" }).toArray()).map((x) => x.id);
const corporateAdmins = (await db.collection("users").find<User>({type: "corporate"}).toArray()).map((x) => x.id);
const groups = await db.collection("groups").find<Group>({
participants: req.session.user!.id,
admin: { $in: corporateAdmins }
}).toArray();
const groups = await db
.collection("groups")
.find<Group>({
participants: req.session.user!.id,
admin: {$in: corporateAdmins},
})
.toArray();
groups.forEach(async (group) => {
await db.collection("groups").updateOne(
{ id: group.id },
{ $set: { participants: group.participants.filter((x) => x !== req.session.user!.id) } }
);
await db
.collection("groups")
.updateOne({id: group.id}, {$set: {participants: group.participants.filter((x) => x !== req.session.user!.id)}});
});
}
} catch {
res.status(400).json({ error: "E002", message: errorMessages.E002 });
res.status(400).json({error: "E002", message: errorMessages.E002});
return;
}
}
@@ -159,22 +158,18 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
delete updatedUser.password;
delete updatedUser.newPassword;
await db.collection("users").updateOne(
{ id: queryId },
{ $set: updatedUser }
);
user = await db.collection("users").findOne<User>({ id: req.session.user.id });
await db.collection("users").updateOne({id: queryId}, {$set: updatedUser});
if (!queryId) {
req.session.user = user ? user : null;
req.session.user = updatedUser ? {...updatedUser, id: req.session.user.id} : null;
await req.session.save();
}
if (user) {
await managePaymentRecords(user, queryId);
if ({...updatedUser, id: req.session.user!.id}) {
await managePaymentRecords({...updatedUser, id: req.session.user!.id}, queryId);
}
res.status(200).json({ user });
res.status(200).json({user: {...updatedUser, id: req.session.user!.id}});
}
export const config = {

View File

@@ -10,7 +10,7 @@ import {User} from "@/interfaces/user";
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
const user = req.session.user;
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",

View File

@@ -10,7 +10,7 @@ import {User} from "@/interfaces/user";
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
const user = req.session.user;
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",

View File

@@ -27,7 +27,7 @@ import {User} from "@/interfaces/user";
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
const user = req.session.user;
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",

View File

@@ -43,7 +43,7 @@ import {getUsers} from "@/utils/users.be";
export const getServerSideProps = withIronSessionSsr(async ({req, res}) => {
const user = req.session.user;
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",

View File

@@ -46,7 +46,7 @@ export const getServerSideProps = withIronSessionSsr(async ({req, res}) => {
envVariables[x] = process.env[x]!;
});
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",
@@ -78,12 +78,8 @@ export default function Home({linkedCorporate}: Props) {
useEffect(() => {
if (user) {
setShowDemographicInput(
!user.demographicInformation ||
!user.demographicInformation.country ||
!user.demographicInformation.gender ||
!user.demographicInformation.phone,
);
console.log(user.demographicInformation);
setShowDemographicInput(!user.demographicInformation || !user.demographicInformation.country || !user.demographicInformation.phone);
setShowDiagnostics(user.isFirstLogin && user.type === "student");
}
}, [user]);

View File

@@ -21,7 +21,7 @@ export const getServerSideProps = withIronSessionSsr(({req, res}) => {
envVariables[x] = process.env[x]!;
});
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",

View File

@@ -28,7 +28,7 @@ export const getServerSideProps = withIronSessionSsr(({req, res}) => {
envVariables[x] = process.env[x]!;
});
if (user && user.isVerified) {
if (user) {
return {
redirect: {
destination: "/",
@@ -56,7 +56,7 @@ export default function Login() {
});
useEffect(() => {
if (user && user.isVerified) router.push("/");
if (user) router.push("/");
}, [router, user]);
const forgotPassword = () => {
@@ -173,7 +173,7 @@ export default function Login() {
</span>
</>
)}
{user && !user.isVerified && <EmailVerification user={user} isLoading={isLoading} setIsLoading={setIsLoading} />}
{/* {user && !user.isVerified && <EmailVerification user={user} isLoading={isLoading} setIsLoading={setIsLoading} />} */}
</section>
</main>
</>

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,7 @@ export const getServerSideProps = withIronSessionSsr(({req, res}) => {
envVariables[x] = process.env[x]!;
});
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",

View File

@@ -32,7 +32,7 @@ export const getServerSideProps = withIronSessionSsr(async (context) => {
const {req, params} = context;
const user = req.session.user;
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",

View File

@@ -12,7 +12,7 @@ import PermissionList from "@/components/PermissionList";
export const getServerSideProps = withIronSessionSsr(async ({req}) => {
const user = req.session.user;
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",

View File

@@ -50,7 +50,7 @@ import {getUsers} from "@/utils/users.be";
export const getServerSideProps = withIronSessionSsr(async ({req, res}) => {
const user = req.session.user;
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",

View File

@@ -29,7 +29,7 @@ import useGradingSystem from "@/hooks/useGrading";
export const getServerSideProps = withIronSessionSsr(async ({req, res}) => {
const user = req.session.user;
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",

View File

@@ -121,7 +121,7 @@ export default function Register({code: queryCode}: {code: string}) {
</Link>
</>
)}
{user && !user.isVerified && <EmailVerification user={user} isLoading={isLoading} setIsLoading={setIsLoading} />}
{/* {user && !user.isVerified && <EmailVerification user={user} isLoading={isLoading} setIsLoading={setIsLoading} />} */}
</section>
</main>
</>

View File

@@ -31,7 +31,7 @@ import useUsers from "@/hooks/useUsers";
export const getServerSideProps = withIronSessionSsr(async ({req, res}) => {
const user = req.session.user;
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",

View File

@@ -34,7 +34,7 @@ const COLORS = ["#1EB3FF", "#FF790A", "#3D9F11", "#EF5DA8", "#414288"];
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
const user = req.session.user;
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",

View File

@@ -22,7 +22,7 @@ const columnHelper = createColumnHelper<TicketWithCorporate>();
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
const user = req.session.user;
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",

View File

@@ -35,7 +35,7 @@ import {sortByModule} from "@/utils/moduleUtils";
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
const user = req.session.user;
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",

View File

@@ -1,30 +1,30 @@
/* eslint-disable @next/next/no-img-element */
import Head from "next/head";
import { withIronSessionSsr } from "iron-session/next";
import { sessionOptions } from "@/lib/session";
import { User } from "@/interfaces/user";
import { ToastContainer } from "react-toastify";
import {withIronSessionSsr} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import {User} from "@/interfaces/user";
import {ToastContainer} from "react-toastify";
import Layout from "@/components/High/Layout";
import { shouldRedirectHome } from "@/utils/navigation.disabled";
import { useEffect, useState } from "react";
import {shouldRedirectHome} from "@/utils/navigation.disabled";
import {useEffect, useState} from "react";
import clsx from "clsx";
import { FaPlus } from "react-icons/fa";
import {FaPlus} from "react-icons/fa";
import useRecordStore from "@/stores/recordStore";
import router from "next/router";
import useTrainingContentStore from "@/stores/trainingContentStore";
import axios from "axios";
import { ITrainingContent } from "@/training/TrainingInterfaces";
import {ITrainingContent} from "@/training/TrainingInterfaces";
import moment from "moment";
import { uuidv4 } from "@firebase/util";
import {uuidv4} from "@firebase/util";
import TrainingScore from "@/training/TrainingScore";
import ModuleBadge from "@/components/ModuleBadge";
import RecordFilter from "@/components/Medium/RecordFilter";
import useFilterRecordsByUser from "@/hooks/useFilterRecordsByUser";
export const getServerSideProps = withIronSessionSsr(({ req, res }) => {
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
const user = req.session.user;
if (!user || !user.isVerified) {
if (!user) {
return {
redirect: {
destination: "/login",
@@ -43,22 +43,23 @@ export const getServerSideProps = withIronSessionSsr(({ req, res }) => {
}
return {
props: { user: req.session.user },
props: {user: req.session.user},
};
}, sessionOptions);
const Training: React.FC<{ user: User }> = ({ user }) => {
const [recordUserId, setRecordTraining] = useRecordStore((state) => [
state.selectedUser,
state.setTraining,
]);
const Training: React.FC<{user: User}> = ({user}) => {
const [recordUserId, setRecordTraining] = useRecordStore((state) => [state.selectedUser, state.setTraining]);
const [filter, setFilter] = useState<"months" | "weeks" | "days" | "assignments">();
const [stats, setTrainingStats] = useTrainingContentStore((state) => [state.stats, state.setStats]);
const [isNewContentLoading, setIsNewContentLoading] = useState(stats.length != 0);
const [groupedByTrainingContent, setGroupedByTrainingContent] = useState<{ [key: string]: ITrainingContent }>();
const [groupedByTrainingContent, setGroupedByTrainingContent] = useState<{[key: string]: ITrainingContent}>();
const { data: trainingContent, isLoading: areRecordsLoading } = useFilterRecordsByUser<ITrainingContent[]>(recordUserId || user?.id, undefined, "training");
const {data: trainingContent, isLoading: areRecordsLoading} = useFilterRecordsByUser<ITrainingContent[]>(
recordUserId || user?.id,
undefined,
"training",
);
useEffect(() => {
const handleRouteChange = (url: string) => {
@@ -74,7 +75,7 @@ const Training: React.FC<{ user: User }> = ({ user }) => {
useEffect(() => {
const postStats = async () => {
try {
const response = await axios.post<{ id: string }>(`/api/training`, { userID: user.id, stats: stats });
const response = await axios.post<{id: string}>(`/api/training`, {userID: user.id, stats: stats});
return response.data.id;
} catch (error) {
setIsNewContentLoading(false);
@@ -97,12 +98,12 @@ const Training: React.FC<{ user: User }> = ({ user }) => {
router.push("/record");
};
const filterTrainingContentByDate = (trainingContent: { [key: string]: ITrainingContent }) => {
const filterTrainingContentByDate = (trainingContent: {[key: string]: ITrainingContent}) => {
if (filter) {
const filterDate = moment()
.subtract({ [filter as string]: 1 })
.subtract({[filter as string]: 1})
.format("x");
const filteredTrainingContent: { [key: string]: ITrainingContent } = {};
const filteredTrainingContent: {[key: string]: ITrainingContent} = {};
Object.keys(trainingContent).forEach((timestamp) => {
if (timestamp >= filterDate) filteredTrainingContent[timestamp] = trainingContent[timestamp];
@@ -117,10 +118,10 @@ const Training: React.FC<{ user: User }> = ({ user }) => {
const grouped = trainingContent.reduce((acc, content) => {
acc[content.created_at] = content;
return acc;
}, {} as { [key: number]: ITrainingContent });
}, {} as {[key: number]: ITrainingContent});
setGroupedByTrainingContent(grouped);
}else {
} else {
setGroupedByTrainingContent(undefined);
}
}, [trainingContent]);
@@ -138,7 +139,7 @@ const Training: React.FC<{ user: User }> = ({ user }) => {
const trainingContentContainer = (timestamp: string) => {
if (!groupedByTrainingContent) return <></>;
const trainingContent: ITrainingContent = groupedByTrainingContent[timestamp];
const uniqueModules = [...new Set(trainingContent.exams.map((exam) => exam.module))];
@@ -192,7 +193,7 @@ const Training: React.FC<{ user: User }> = ({ user }) => {
</div>
) : (
<>
<RecordFilter user={user} filterState={{ filter: filter, setFilter: setFilter }} assignments={false} >
<RecordFilter user={user} filterState={{filter: filter, setFilter: setFilter}} assignments={false}>
{user.type === "student" && (
<>
<div className="flex items-center">