From 240e36f15aea39d570ce18f16554b670b2b89ebd Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Thu, 12 Dec 2024 15:06:00 +0000 Subject: [PATCH] ENCOA-279 --- src/pages/action.tsx | 24 ++++---- src/pages/api/register.ts | 5 +- src/pages/dashboard/admin.tsx | 2 +- src/pages/dashboard/corporate.tsx | 2 +- src/pages/dashboard/developer.tsx | 2 +- src/pages/dashboard/index.tsx | 10 ++-- src/pages/dashboard/mastercorporate.tsx | 2 +- src/pages/dashboard/student.tsx | 74 +++++++++++++------------ src/pages/dashboard/teacher.tsx | 2 +- src/pages/index.tsx | 10 ++-- src/pages/login.tsx | 11 ++-- 11 files changed, 71 insertions(+), 73 deletions(-) diff --git a/src/pages/action.tsx b/src/pages/action.tsx index c6cf8cbb..8e74bc14 100644 --- a/src/pages/action.tsx +++ b/src/pages/action.tsx @@ -1,15 +1,15 @@ /* eslint-disable @next/next/no-img-element */ -import {toast, ToastContainer} from "react-toastify"; +import { toast, ToastContainer } from "react-toastify"; import axios from "axios"; -import {FormEvent, useEffect, useState} from "react"; +import { FormEvent, useEffect, useState } from "react"; import Head from "next/head"; import useUser from "@/hooks/useUser"; -import {Divider} from "primereact/divider"; +import { Divider } from "primereact/divider"; import Button from "@/components/Low/Button"; -import {BsArrowRepeat} from "react-icons/bs"; +import { BsArrowRepeat } from "react-icons/bs"; import Link from "next/link"; import Input from "@/components/Low/Input"; -import {useRouter} from "next/router"; +import { useRouter } from "next/router"; export function getServerSideProps({ query, @@ -35,12 +35,12 @@ export function getServerSideProps({ props: { code: query.oobCode, mode: query.mode, - ...(query.continueUrl ? {continueUrl: query.continueUrl} : {}), + ...(query.continueUrl ? { continueUrl: query.continueUrl } : {}), }, }; } -export default function Reset({code, mode, continueUrl}: {code: string; mode: string; continueUrl?: string}) { +export default function Reset({ code, mode, continueUrl }: { code: string; mode: string; continueUrl?: string }) { const [password, setPassword] = useState(""); const [isLoading, setIsLoading] = useState(false); @@ -54,7 +54,7 @@ export default function Reset({code, mode, continueUrl}: {code: string; mode: st useEffect(() => { if (mode === "signIn") { axios - .post<{ok: boolean}>("/api/reset/verify", { + .post<{ ok: boolean }>("/api/reset/verify", { email: continueUrl?.replace("https://platform.encoach.com/", "").replace("https://staging.encoach.com/", ""), }) .then((response) => { @@ -64,7 +64,7 @@ export default function Reset({code, mode, continueUrl}: {code: string; mode: st }); setTimeout(() => { router.push("/"); - }, 1000); + }, 500); return; } @@ -86,7 +86,7 @@ export default function Reset({code, mode, continueUrl}: {code: string; mode: st setIsLoading(true); axios - .post<{ok: boolean}>("/api/reset/confirm", {code, password}) + .post<{ ok: boolean }>("/api/reset/confirm", { code, password }) .then((response) => { if (response.data.ok) { toast.success("Your password has been reset!", { @@ -98,10 +98,10 @@ export default function Reset({code, mode, continueUrl}: {code: string; mode: st return; } - toast.error("Something went wrong! Please make sure to click the link in your e-mail again!", {toastId: "reset-error"}); + toast.error("Something went wrong! Please make sure to click the link in your e-mail again!", { toastId: "reset-error" }); }) .catch(() => { - toast.error("Something went wrong! Please make sure to click the link in your e-mail again!", {toastId: "reset-error"}); + toast.error("Something went wrong! Please make sure to click the link in your e-mail again!", { toastId: "reset-error" }); }) .finally(() => setIsLoading(false)); }; diff --git a/src/pages/api/register.ts b/src/pages/api/register.ts index b5dc4d1f..6e9238e0 100644 --- a/src/pages/api/register.ts +++ b/src/pages/api/register.ts @@ -73,9 +73,8 @@ async function registerIndividual(req: NextApiRequest, res: NextApiResponse) { ...(passport_id ? { demographicInformation: { passport_id } } : {}), registrationDate: new Date().toISOString(), status: code ? "active" : "paymentDue", - // apparently there's an issue with the verification email system - // therefore we will skip this requirement for now - isVerified: true, + entities: [], + isVerified: !!codeDoc, }; await db.collection("users").insertOne(user); diff --git a/src/pages/dashboard/admin.tsx b/src/pages/dashboard/admin.tsx index 187e0332..2e53d579 100644 --- a/src/pages/dashboard/admin.tsx +++ b/src/pages/dashboard/admin.tsx @@ -47,7 +47,7 @@ interface Props { export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => { const user = await requestUser(req, res) - if (!user) return redirect("/login") + if (!user || !user.isVerified) return redirect("/login") if (!checkAccess(user, ["admin", "developer"])) return redirect("/") diff --git a/src/pages/dashboard/corporate.tsx b/src/pages/dashboard/corporate.tsx index 4ef1e2ff..7b786bc6 100644 --- a/src/pages/dashboard/corporate.tsx +++ b/src/pages/dashboard/corporate.tsx @@ -46,7 +46,7 @@ interface Props { export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => { const user = await requestUser(req, res) - if (!user) return redirect("/login") + if (!user || !user.isVerified) return redirect("/login") if (!checkAccess(user, ["admin", "developer", "corporate"])) return redirect("/") diff --git a/src/pages/dashboard/developer.tsx b/src/pages/dashboard/developer.tsx index 187e0332..2e53d579 100644 --- a/src/pages/dashboard/developer.tsx +++ b/src/pages/dashboard/developer.tsx @@ -47,7 +47,7 @@ interface Props { export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => { const user = await requestUser(req, res) - if (!user) return redirect("/login") + if (!user || !user.isVerified) return redirect("/login") if (!checkAccess(user, ["admin", "developer"])) return redirect("/") diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx index abefdaad..d73c8f29 100644 --- a/src/pages/dashboard/index.tsx +++ b/src/pages/dashboard/index.tsx @@ -1,12 +1,12 @@ -import {User} from "@/interfaces/user"; -import {sessionOptions} from "@/lib/session"; +import { User } from "@/interfaces/user"; +import { sessionOptions } from "@/lib/session"; import { redirect } from "@/utils"; import { requestUser } from "@/utils/api"; -import {withIronSessionSsr} from "iron-session/next"; +import { withIronSessionSsr } from "iron-session/next"; -export const getServerSideProps = withIronSessionSsr(async ({req, res}) => { +export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => { const user = await requestUser(req, res) - if (!user) return redirect("/login") + if (!user || !user.isVerified) return redirect("/login") return redirect(`/dashboard/${user.type}`) }, sessionOptions); diff --git a/src/pages/dashboard/mastercorporate.tsx b/src/pages/dashboard/mastercorporate.tsx index 6e887bfd..8e7d5378 100644 --- a/src/pages/dashboard/mastercorporate.tsx +++ b/src/pages/dashboard/mastercorporate.tsx @@ -52,7 +52,7 @@ interface Props { export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => { const user = await requestUser(req, res) - if (!user) return redirect("/login") + if (!user || !user.isVerified) return redirect("/login") if (!checkAccess(user, ["admin", "developer", "mastercorporate"])) return redirect("/") diff --git a/src/pages/dashboard/student.tsx b/src/pages/dashboard/student.tsx index dc46e5ee..2a1f000c 100644 --- a/src/pages/dashboard/student.tsx +++ b/src/pages/dashboard/student.tsx @@ -5,38 +5,38 @@ import ProgressBar from "@/components/Low/ProgressBar"; import InviteWithUserCard from "@/components/Medium/InviteWithUserCard"; import ModuleBadge from "@/components/ModuleBadge"; import ProfileSummary from "@/components/ProfileSummary"; -import {Session} from "@/hooks/useSessions"; -import {Grading} from "@/interfaces"; -import {EntityWithRoles} from "@/interfaces/entity"; -import {Exam} from "@/interfaces/exam"; +import { Session } from "@/hooks/useSessions"; +import { Grading } from "@/interfaces"; +import { EntityWithRoles } from "@/interfaces/entity"; +import { Exam } from "@/interfaces/exam"; import { InviteWithEntity } from "@/interfaces/invite"; -import {Assignment} from "@/interfaces/results"; -import {Stat, User} from "@/interfaces/user"; -import {sessionOptions} from "@/lib/session"; +import { Assignment } from "@/interfaces/results"; +import { Stat, User } from "@/interfaces/user"; +import { sessionOptions } from "@/lib/session"; import useExamStore from "@/stores/exam"; -import {findBy, mapBy, redirect, serialize} from "@/utils"; +import { findBy, mapBy, redirect, serialize } from "@/utils"; import { requestUser } from "@/utils/api"; -import {activeAssignmentFilter} from "@/utils/assignments"; -import {getAssignmentsByAssignee} from "@/utils/assignments.be"; -import {getEntitiesWithRoles, getEntityWithRoles} from "@/utils/entities.be"; -import {getExamsByIds} from "@/utils/exams.be"; -import {getGradingSystemByEntity} from "@/utils/grading.be"; -import {convertInvitersToEntity, getInvitesByInvitee} from "@/utils/invites.be"; -import {countExamModules, countFullExams, MODULE_ARRAY, sortByModule, sortByModuleName} from "@/utils/moduleUtils"; -import {checkAccess} from "@/utils/permissions"; -import {getGradingLabel} from "@/utils/score"; -import {getSessionsByUser} from "@/utils/sessions.be"; -import {averageScore} from "@/utils/stats"; -import {getStatsByUser} from "@/utils/stats.be"; +import { activeAssignmentFilter } from "@/utils/assignments"; +import { getAssignmentsByAssignee } from "@/utils/assignments.be"; +import { getEntitiesWithRoles, getEntityWithRoles } from "@/utils/entities.be"; +import { getExamsByIds } from "@/utils/exams.be"; +import { getGradingSystemByEntity } from "@/utils/grading.be"; +import { convertInvitersToEntity, getInvitesByInvitee } from "@/utils/invites.be"; +import { countExamModules, countFullExams, MODULE_ARRAY, sortByModule, sortByModuleName } from "@/utils/moduleUtils"; +import { checkAccess } from "@/utils/permissions"; +import { getGradingLabel } from "@/utils/score"; +import { getSessionsByUser } from "@/utils/sessions.be"; +import { averageScore } from "@/utils/stats"; +import { getStatsByUser } from "@/utils/stats.be"; import clsx from "clsx"; -import {withIronSessionSsr} from "iron-session/next"; -import {capitalize, uniqBy} from "lodash"; +import { withIronSessionSsr } from "iron-session/next"; +import { capitalize, uniqBy } from "lodash"; import moment from "moment"; import Head from "next/head"; -import {useRouter} from "next/router"; +import { useRouter } from "next/router"; import { useMemo } from "react"; -import {BsBook, BsClipboard, BsFileEarmarkText, BsHeadphones, BsMegaphone, BsPen, BsPencil, BsStar} from "react-icons/bs"; -import {ToastContainer} from "react-toastify"; +import { BsBook, BsClipboard, BsFileEarmarkText, BsHeadphones, BsMegaphone, BsPen, BsPencil, BsStar } from "react-icons/bs"; +import { ToastContainer } from "react-toastify"; interface Props { user: User; @@ -49,9 +49,9 @@ interface Props { grading: Grading; } -export const getServerSideProps = withIronSessionSsr(async ({req, res}) => { +export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => { const user = await requestUser(req, res) - if (!user) return redirect("/login") + if (!user || !user.isVerified) return redirect("/login") if (!checkAccess(user, ["admin", "developer", "student"])) return redirect("/") @@ -59,7 +59,7 @@ export const getServerSideProps = withIronSessionSsr(async ({req, res}) => { const entityIDS = mapBy(user.entities, "id") || []; const entities = await getEntitiesWithRoles(entityIDS); - const assignments = await getAssignmentsByAssignee(user.id, {archived: {$ne: true}}); + const assignments = await getAssignmentsByAssignee(user.id, { archived: { $ne: true } }); const stats = await getStatsByUser(user.id); const sessions = await getSessionsByUser(user.id, 10); const invites = await getInvitesByInvitee(user.id); @@ -69,16 +69,16 @@ export const getServerSideProps = withIronSessionSsr(async ({req, res}) => { const examIDs = uniqBy( assignments.flatMap((a) => - a.exams.filter((e) => e.assignee === user.id).map((e) => ({module: e.module, id: e.id, key: `${e.module}_${e.id}`})), + a.exams.filter((e) => e.assignee === user.id).map((e) => ({ module: e.module, id: e.id, key: `${e.module}_${e.id}` })), ), "key", ); const exams = await getExamsByIds(examIDs); - return {props: serialize({user, entities, assignments, stats, exams, sessions, invites: formattedInvites, grading})}; + return { props: serialize({ user, entities, assignments, stats, exams, sessions, invites: formattedInvites, grading }) }; }, sessionOptions); -export default function Dashboard({user, entities, assignments, stats, invites, grading, sessions, exams}: Props) { +export default function Dashboard({ user, entities, assignments, stats, invites, grading, sessions, exams }: Props) { const router = useRouter(); const dispatch = useExamStore((state) => state.dispatch); @@ -90,11 +90,13 @@ export default function Dashboard({user, entities, assignments, stats, invites, }) if (assignmentExams.every((x) => !!x)) { - dispatch({type: "INIT_EXAM", payload: { - exams: assignmentExams.sort(sortByModule), - modules: mapBy(assignmentExams.sort(sortByModule), 'module'), - assignment - }}) + dispatch({ + type: "INIT_EXAM", payload: { + exams: assignmentExams.sort(sortByModule), + modules: mapBy(assignmentExams.sort(sortByModule), 'module'), + assignment + } + }) router.push("/exam"); } diff --git a/src/pages/dashboard/teacher.tsx b/src/pages/dashboard/teacher.tsx index 5843ac7d..0d3a880c 100644 --- a/src/pages/dashboard/teacher.tsx +++ b/src/pages/dashboard/teacher.tsx @@ -39,7 +39,7 @@ interface Props { export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => { const user = await requestUser(req, res) - if (!user) return redirect("/login") + if (!user || !user.isVerified) return redirect("/login") if (!checkAccess(user, ["admin", "developer", "teacher"])) return redirect("/") diff --git a/src/pages/index.tsx b/src/pages/index.tsx index abefdaad..d73c8f29 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,12 +1,12 @@ -import {User} from "@/interfaces/user"; -import {sessionOptions} from "@/lib/session"; +import { User } from "@/interfaces/user"; +import { sessionOptions } from "@/lib/session"; import { redirect } from "@/utils"; import { requestUser } from "@/utils/api"; -import {withIronSessionSsr} from "iron-session/next"; +import { withIronSessionSsr } from "iron-session/next"; -export const getServerSideProps = withIronSessionSsr(async ({req, res}) => { +export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => { const user = await requestUser(req, res) - if (!user) return redirect("/login") + if (!user || !user.isVerified) return redirect("/login") return redirect(`/dashboard/${user.type}`) }, sessionOptions); diff --git a/src/pages/login.tsx b/src/pages/login.tsx index 09fee825..8cc49f98 100644 --- a/src/pages/login.tsx +++ b/src/pages/login.tsx @@ -23,7 +23,7 @@ const EMAIL_REGEX = new RegExp(/^[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*@[a-zA-Z0-9]+(?: export const getServerSideProps = withIronSessionSsr(async ({ req, res, query }) => { const destination = !query.destination ? "/" : Buffer.from(query.destination as string, 'base64').toString() const user = await requestUser(req, res) - if (user) return redirect(destination) + if (user && user.isVerified) return redirect(destination) return { props: { user: null, destination }, @@ -39,13 +39,10 @@ export default function Login({ destination = "/" }: { destination?: string }) { const router = useRouter(); const isOfficialExamLogin = useMemo(() => destination.startsWith("/official-exam"), [destination]) - const { user, mutateUser } = useUser({ - redirectTo: destination, - redirectIfFound: true, - }); + const { user, mutateUser } = useUser(); useEffect(() => { - if (user) router.push(destination); + if (user && user.isVerified) router.push(destination); }, [router, user, destination]); const forgotPassword = () => { @@ -173,7 +170,7 @@ export default function Login({ destination = "/" }: { destination?: string }) { )} - {/* {user && !user.isVerified && } */} + {user && !user.isVerified && }