refactor: add gssp hoc func for auth

gssp -> getServerSideProps
hoc -> Higher-Order Components
This commit is contained in:
Sonny
2023-06-10 18:57:07 +02:00
parent f562b7c433
commit 1c9c65e074
10 changed files with 161 additions and 234 deletions

View File

@@ -1,29 +0,0 @@
import PATHS from "constants/paths";
import { useSession } from "next-auth/react";
import { useRouter } from "next/router";
// Component used to access to the session client side
export default function Auth({ children }) {
const router = useRouter();
const { status } = useSession({
required: true,
onUnauthenticated: () =>
router.push(
`${PATHS.LOGIN}?info=${encodeURI(
"Vous devez être connecté pour accéder à cette page"
)}`
),
});
if (status === "loading") {
return (
<div className="App" style={{ alignItems: "center" }}>
<p style={{ height: "fit-content" }}>
Chargement de la session en cours
</p>
</div>
);
}
return children;
}

View File

@@ -5,7 +5,6 @@ import nProgress from "nprogress";
import { useEffect } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import AuthRequired from "components/AuthRequired";
import * as Keys from "constants/keys";
import PATHS from "constants/paths";
@@ -36,13 +35,7 @@ function MyApp({ Component, pageProps: { session, ...pageProps } }) {
return (
<SessionProvider session={session}>
<DefaultSeo titleTemplate="MyLinks — %s" defaultTitle="MyLinks" />
{Component.authRequired ? (
<AuthRequired>
<Component {...pageProps} />
</AuthRequired>
) : (
<Component {...pageProps} />
)}
<Component {...pageProps} />
</SessionProvider>
);
}

View File

@@ -10,14 +10,17 @@ import TextBox from "components/TextBox";
import PATHS from "constants/paths";
import useAutoFocus from "hooks/useAutoFocus";
import getUserCategoriesCount from "lib/category/getUserCategoriesCount";
import getUser from "lib/user/getUser";
import { redirectWithoutClientCache } from "utils/client";
import { HandleAxiosError } from "utils/front";
import { getSession } from "utils/session";
import { withAuthentication } from "utils/session";
import styles from "styles/form.module.scss";
function CreateCategory({ categoriesCount }: { categoriesCount: number }) {
export default function PageCreateCategory({
categoriesCount,
}: {
categoriesCount: number;
}) {
const autoFocusRef = useAutoFocus();
const router = useRouter();
const info = useRouter().query?.info as string;
@@ -75,24 +78,14 @@ function CreateCategory({ categoriesCount }: { categoriesCount: number }) {
);
}
CreateCategory.authRequired = true;
export default CreateCategory;
export async function getServerSideProps({ req, res }) {
const session = await getSession(req, res);
const user = await getUser(session);
if (!user) {
export const getServerSideProps = withAuthentication(
async ({ session, user }) => {
const categoriesCount = await getUserCategoriesCount(user);
return {
redirect: {
destination: PATHS.HOME,
props: {
session,
categoriesCount,
},
};
}
const categoriesCount = await getUserCategoriesCount(user);
return {
props: {
categoriesCount,
},
};
}
);

View File

@@ -10,14 +10,13 @@ import TextBox from "components/TextBox";
import PATHS from "constants/paths";
import useAutoFocus from "hooks/useAutoFocus";
import getUserCategory from "lib/category/getUserCategory";
import getUser from "lib/user/getUser";
import { Category } from "types";
import { HandleAxiosError } from "utils/front";
import { getSession } from "utils/session";
import { withAuthentication } from "utils/session";
import styles from "styles/form.module.scss";
function EditCategory({ category }: { category: Category }) {
export default function PageEditCategory({ category }: { category: Category }) {
const autoFocusRef = useAutoFocus();
const router = useRouter();
@@ -73,34 +72,24 @@ function EditCategory({ category }: { category: Category }) {
);
}
EditCategory.authRequired = true;
export default EditCategory;
export const getServerSideProps = withAuthentication(
async ({ query, session, user }) => {
const { cid } = query;
export async function getServerSideProps({ req, res, query }) {
const { cid } = query;
const category = await getUserCategory(user, Number(cid));
if (!category) {
return {
redirect: {
destination: PATHS.HOME,
},
};
}
const session = await getSession(req, res);
const user = await getUser(session);
if (!user) {
return {
redirect: {
destination: PATHS.HOME,
props: {
session,
category: JSON.parse(JSON.stringify(category)),
},
};
}
const category = await getUserCategory(user, Number(cid));
if (!category) {
return {
redirect: {
destination: PATHS.HOME,
},
};
}
return {
props: {
category: JSON.parse(JSON.stringify(category)),
},
};
}
);

View File

@@ -10,14 +10,17 @@ import TextBox from "components/TextBox";
import PATHS from "constants/paths";
import getUserCategory from "lib/category/getUserCategory";
import getUser from "lib/user/getUser";
import { Category } from "types";
import { HandleAxiosError } from "utils/front";
import { getSession } from "utils/session";
import { withAuthentication } from "utils/session";
import styles from "styles/form.module.scss";
function RemoveCategory({ category }: { category: Category }) {
export default function PageRemoveCategory({
category,
}: {
category: Category;
}) {
const router = useRouter();
const [error, setError] = useState<string | null>(
category.links.length > 0
@@ -80,34 +83,24 @@ function RemoveCategory({ category }: { category: Category }) {
);
}
RemoveCategory.authRequired = true;
export default RemoveCategory;
export const getServerSideProps = withAuthentication(
async ({ query, session, user }) => {
const { cid } = query;
export async function getServerSideProps({ req, res, query }) {
const { cid } = query;
const category = await getUserCategory(user, Number(cid));
if (!category) {
return {
redirect: {
destination: PATHS.HOME,
},
};
}
const session = await getSession(req, res);
const user = await getUser(session);
if (!user) {
return {
redirect: {
destination: PATHS.HOME,
props: {
session,
category: JSON.parse(JSON.stringify(category)),
},
};
}
const category = await getUserCategory(user, Number(cid));
if (!category) {
return {
redirect: {
destination: PATHS.HOME,
},
};
}
return {
props: {
category: JSON.parse(JSON.stringify(category)),
},
};
}
);

View File

@@ -18,17 +18,16 @@ import PATHS from "constants/paths";
import { useMediaQuery } from "hooks/useMediaQuery";
import useModal from "hooks/useModal";
import getUserCategories from "lib/category/getUserCategories";
import getUser from "lib/user/getUser";
import { Category, Link, SearchItem } from "types";
import { pushStateVanilla } from "utils/link";
import { getSession } from "utils/session";
import { withAuthentication } from "utils/session";
interface HomePageProps {
categories: Category[];
currentCategory: Category | undefined;
}
function Home(props: HomePageProps) {
export default function HomePage(props: HomePageProps) {
const router = useRouter();
const searchModal = useModal();
@@ -193,40 +192,30 @@ function Home(props: HomePageProps) {
);
}
export async function getServerSideProps({ req, res, query }) {
const queryCategoryId = (query?.categoryId as string) || "";
export const getServerSideProps = withAuthentication(
async ({ query, session, user }) => {
const queryCategoryId = (query?.categoryId as string) || "";
const session = await getSession(req, res);
const user = await getUser(session);
if (!user) {
const categories = await getUserCategories(user);
if (categories.length === 0) {
return {
redirect: {
destination: PATHS.CATEGORY.CREATE,
},
};
}
const currentCategory = categories.find(
({ id }) => id === Number(queryCategoryId)
);
return {
redirect: {
destination: PATHS.LOGIN,
props: {
session,
categories: JSON.parse(JSON.stringify(categories)),
currentCategory: currentCategory
? JSON.parse(JSON.stringify(currentCategory))
: null,
},
};
}
const categories = await getUserCategories(user);
if (categories.length === 0) {
return {
redirect: {
destination: PATHS.CATEGORY.CREATE,
},
};
}
const currentCategory = categories.find(
({ id }) => id === Number(queryCategoryId)
);
return {
props: {
categories: JSON.parse(JSON.stringify(categories)),
currentCategory: currentCategory
? JSON.parse(JSON.stringify(currentCategory))
: null,
},
};
}
Home.authRequired = true;
export default Home;
);

View File

@@ -12,14 +12,17 @@ import TextBox from "components/TextBox";
import PATHS from "constants/paths";
import useAutoFocus from "hooks/useAutoFocus";
import getUserCategories from "lib/category/getUserCategories";
import getUser from "lib/user/getUser";
import { Category, Link } from "types";
import { HandleAxiosError, IsValidURL } from "utils/front";
import { getSession } from "utils/session";
import { withAuthentication } from "utils/session";
import styles from "styles/form.module.scss";
function CreateLink({ categories }: { categories: Category[] }) {
export default function PageCreateLink({
categories,
}: {
categories: Category[];
}) {
const autoFocusRef = useAutoFocus();
const router = useRouter();
const categoryIdQuery = router.query?.categoryId as string;
@@ -110,32 +113,22 @@ function CreateLink({ categories }: { categories: Category[] }) {
);
}
CreateLink.authRequired = true;
export default CreateLink;
export const getServerSideProps = withAuthentication(
async ({ session, user }) => {
const categories = await getUserCategories(user);
if (categories.length === 0) {
return {
redirect: {
destination: PATHS.HOME,
},
};
}
export async function getServerSideProps({ req, res }) {
const session = await getSession(req, res);
const user = await getUser(session);
if (!user) {
return {
redirect: {
destination: PATHS.HOME,
props: {
session,
categories: JSON.parse(JSON.stringify(categories)),
},
};
}
const categories = await getUserCategories(user);
if (categories.length === 0) {
return {
redirect: {
destination: PATHS.HOME,
},
};
}
return {
props: {
categories: JSON.parse(JSON.stringify(categories)),
},
};
}
);

View File

@@ -13,14 +13,13 @@ import PATHS from "constants/paths";
import useAutoFocus from "hooks/useAutoFocus";
import getUserCategories from "lib/category/getUserCategories";
import getUserLink from "lib/link/getUserLink";
import getUser from "lib/user/getUser";
import { Category, Link } from "types";
import { HandleAxiosError, IsValidURL } from "utils/front";
import { getSession } from "utils/session";
import { withAuthentication } from "utils/session";
import styles from "styles/form.module.scss";
function EditLink({
export default function PageEditLink({
link,
categories,
}: {
@@ -129,36 +128,26 @@ function EditLink({
);
}
EditLink.authRequired = true;
export default EditLink;
export const getServerSideProps = withAuthentication(
async ({ query, session, user }) => {
const { lid } = query;
export async function getServerSideProps({ req, res, query }) {
const { lid } = query;
const categories = await getUserCategories(user);
const link = await getUserLink(user, Number(lid));
if (!link) {
return {
redirect: {
destination: PATHS.HOME,
},
};
}
const session = await getSession(req, res);
const user = await getUser(session);
if (!user) {
return {
redirect: {
destination: PATHS.HOME,
props: {
session,
link: JSON.parse(JSON.stringify(link)),
categories: JSON.parse(JSON.stringify(categories)),
},
};
}
const categories = await getUserCategories(user);
const link = await getUserLink(user, Number(lid));
if (!link) {
return {
redirect: {
destination: PATHS.HOME,
},
};
}
return {
props: {
link: JSON.parse(JSON.stringify(link)),
categories: JSON.parse(JSON.stringify(categories)),
},
};
}
);

View File

@@ -10,14 +10,13 @@ import TextBox from "components/TextBox";
import PATHS from "constants/paths";
import getUserLink from "lib/link/getUserLink";
import getUser from "lib/user/getUser";
import { Link } from "types";
import { HandleAxiosError } from "utils/front";
import { getSession } from "utils/session";
import { withAuthentication } from "utils/session";
import styles from "styles/form.module.scss";
function RemoveLink({ link }: { link: Link }) {
export default function PageRemoveLink({ link }: { link: Link }) {
const router = useRouter();
const [error, setError] = useState<string | null>(null);
@@ -94,34 +93,24 @@ function RemoveLink({ link }: { link: Link }) {
);
}
RemoveLink.authRequired = true;
export default RemoveLink;
export const getServerSideProps = withAuthentication(
async ({ query, session, user }) => {
const { lid } = query;
export async function getServerSideProps({ req, res, query }) {
const { lid } = query;
const link = await getUserLink(user, Number(lid));
if (!link) {
return {
redirect: {
destination: PATHS.HOME,
},
};
}
const session = await getSession(req, res);
const user = await getUser(session);
if (!user) {
return {
redirect: {
destination: PATHS.HOME,
props: {
session,
link: JSON.parse(JSON.stringify(link)),
},
};
}
const link = await getUserLink(user, Number(lid));
if (!link) {
return {
redirect: {
destination: PATHS.HOME,
},
};
}
return {
props: {
link: JSON.parse(JSON.stringify(link)),
},
};
}
);

View File

@@ -1,8 +1,36 @@
import { NextApiRequest, NextApiResponse } from "next";
import {
GetServerSidePropsContext,
NextApiRequest,
NextApiResponse,
} from "next";
import { getServerSession } from "next-auth/next";
import PATHS from "constants/paths";
import getUser from "lib/user/getUser";
import { authOptions } from "pages/api/auth/[...nextauth]";
export async function getSession(req: NextApiRequest, res: NextApiResponse) {
return await getServerSession(req, res, authOptions);
}
export function withAuthentication(serverSidePropsFunc) {
return async (context: GetServerSidePropsContext) => {
const { req, res } = context;
const session = await getSession(
req as NextApiRequest,
res as NextApiResponse
);
const user = await getUser(session);
if (!session || !user) {
return {
redirect: {
destination: PATHS.LOGIN,
},
};
}
// Continue on to call `getServerSideProps` logic
return await serverSidePropsFunc({ ...context, session, user });
};
}