Implemented a simple authentication scheme with Firebase and Iron Session

This commit is contained in:
Tiago Ribeiro
2023-04-12 16:53:36 +01:00
parent cb1a67de23
commit 58bdc745e4
16 changed files with 1371 additions and 33 deletions

View File

@@ -4,22 +4,38 @@ import Navbar from "@/components/Navbar";
import {useEffect, useState} from "react";
import {Module} from "@/interfaces";
// TODO: Remove this import
import JSON_USER from "@/demo/user.json";
import JSON_READING from "@/demo/reading.json";
import JSON_LISTENING from "@/demo/listening.json";
import JSON_WRITING from "@/demo/writing.json";
import Selection from "@/exams/Selection";
import Reading from "@/exams/Reading";
import {Exam, ListeningExam, ReadingExam, UserSolution, WritingExam} from "@/interfaces/exam";
import Listening from "@/exams/Listening";
import Writing from "@/exams/Writing";
import {ToastContainer} from "react-toastify";
import Link from "next/link";
import {ToastContainer, toast} from "react-toastify";
import Finish from "@/exams/Finish";
import axios from "axios";
import {withIronSessionSsr} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import {User} from "@/interfaces/user";
export default function Home() {
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
const user = req.session.user;
if (!user) {
res.setHeader("location", "/login");
res.statusCode = 302;
res.end();
return {
props: {
user: null,
},
};
}
return {
props: {user: req.session.user},
};
}, sessionOptions);
export default function Page({user}: {user: User}) {
const [selectedModules, setSelectedModules] = useState<Module[]>([]);
const [moduleIndex, setModuleIndex] = useState(0);
const [exam, setExam] = useState<Exam>();
@@ -27,21 +43,31 @@ export default function Home() {
const [showSolutions, setShowSolutions] = useState(false);
useEffect(() => {
if (selectedModules.length > 0 && moduleIndex < selectedModules.length) {
const nextExam = getExam(selectedModules[moduleIndex]);
setExam(nextExam ? updateExamWithUserSolutions(nextExam) : undefined);
}
(async () => {
if (selectedModules.length > 0 && moduleIndex < selectedModules.length) {
const nextExam = await getExam(selectedModules[moduleIndex]);
setExam(nextExam ? updateExamWithUserSolutions(nextExam) : undefined);
}
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedModules, moduleIndex]);
const getExam = (module: Module): Exam | undefined => {
const getExam = async (module: Module): Promise<Exam | undefined> => {
const examRequest = await axios<Exam[]>(`/api/exam/${module}`);
if (examRequest.status !== 200) {
toast.error("Something went wrong!");
return undefined;
}
const newExam = examRequest.data;
switch (module) {
case "reading":
return JSON_READING as ReadingExam;
return newExam.shift() as ReadingExam;
case "listening":
return JSON_LISTENING as ListeningExam;
return newExam.shift() as ListeningExam;
case "writing":
return JSON_WRITING as WritingExam;
return newExam.shift() as WritingExam;
}
return undefined;
@@ -63,13 +89,13 @@ export default function Home() {
const renderScreen = () => {
if (selectedModules.length === 0) {
return <Selection user={JSON_USER} onStart={setSelectedModules} />;
return <Selection user={user} onStart={setSelectedModules} />;
}
if (moduleIndex >= selectedModules.length) {
return (
<Finish
user={JSON_USER}
user={user}
modules={selectedModules}
onViewResults={() => {
setShowSolutions(true);
@@ -110,7 +136,7 @@ export default function Home() {
</Head>
<main className="w-full h-screen flex flex-col items-center bg-neutral-100 text-black">
<ToastContainer />
<Navbar profilePicture={JSON_USER.profilePicture} />
<Navbar profilePicture={user.profilePicture} />
{renderScreen()}
</main>
</>