2
2
mirror of https://github.com/Thream/website.git synced 2024-07-21 09:28:32 +02:00
website/tools/authentication/authenticationFromServerSide.ts

100 lines
2.7 KiB
TypeScript

import type { AxiosInstance, AxiosResponse } from "axios"
import type { GetServerSideProps, GetServerSidePropsContext } from "next"
import { api } from "../api"
import { Cookies } from "../cookies"
import type { RefreshTokenResponse, Tokens } from "./index"
import { Authentication } from "./Authentication"
import type { UserCurrent } from "../../models/User"
export const fetchRefreshToken = async (
refreshToken: string,
): Promise<Tokens> => {
const { data } = await api.post<RefreshTokenResponse>(
"/users/refresh-token",
{
refreshToken,
},
)
return { ...data, refreshToken }
}
interface AuthenticationFromServerSideOptions {
shouldBeAuthenticated: boolean
/** allows to fetch data server side with the authenticated user, the callback should returns the data that will be transfer to the component as props */
fetchData?: (
context: GetServerSidePropsContext,
api: AxiosInstance,
) => Promise<{ [key: string]: any }>
}
export const authenticationFromServerSide = (
options: AuthenticationFromServerSideOptions,
): GetServerSideProps => {
const { shouldBeAuthenticated, fetchData } = options
return async (context) => {
const cookies = new Cookies(context.req.headers.cookie)
const refreshToken = cookies.get("refreshToken")
let tokens: Tokens | null = null
if (refreshToken != null) {
try {
tokens = await fetchRefreshToken(refreshToken)
} catch {
cookies.remove("refreshToken")
}
}
if (!shouldBeAuthenticated) {
if (tokens != null) {
return {
redirect: {
destination: "/application",
permanent: false,
},
}
} else {
let data: any = {}
if (fetchData != null) {
data = await fetchData(context, api)
}
if (data.notFound != null) {
return data
}
return { props: data }
}
} else {
if (tokens == null) {
return {
redirect: {
destination: "/authentication/signin",
permanent: false,
},
}
} else {
try {
let data: any = {}
const authentication = new Authentication(tokens)
const { data: currentUser } = await authentication.api.get<
unknown,
AxiosResponse<UserCurrent>
>("/users/current")
if (fetchData != null) {
data = await fetchData(context, authentication.api)
}
if (data.notFound != null) {
return data
}
return {
props: { authentication: { tokens, ...currentUser }, ...data },
}
} catch {
return {
notFound: true,
}
}
}
}
}
}