2023-10-23 23:33:39 +02:00
import type { AxiosInstance , AxiosResponse } from "axios"
import type { GetServerSideProps , GetServerSidePropsContext } from "next"
2021-10-24 06:09:43 +02:00
2023-10-23 23:33:39 +02:00
import { api } from "../api"
import { Cookies } from "../cookies"
import type { RefreshTokenResponse , Tokens } from "./index"
import { Authentication } from "./Authentication"
import type { UserCurrent } from "../../models/User"
2021-10-24 06:09:43 +02:00
export const fetchRefreshToken = async (
2023-10-23 23:33:39 +02:00
refreshToken : string ,
2021-10-24 06:09:43 +02:00
) : Promise < Tokens > = > {
const { data } = await api . post < RefreshTokenResponse > (
2023-10-23 23:33:39 +02:00
"/users/refresh-token" ,
2021-10-24 06:09:43 +02:00
{
2023-10-23 23:33:39 +02:00
refreshToken ,
} ,
2021-10-24 06:09:43 +02:00
)
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 ,
2023-10-23 23:33:39 +02:00
api : AxiosInstance ,
2021-10-24 06:09:43 +02:00
) = > Promise < { [ key : string ] : any } >
}
export const authenticationFromServerSide = (
2023-10-23 23:33:39 +02:00
options : AuthenticationFromServerSideOptions ,
2021-10-24 06:09:43 +02:00
) : GetServerSideProps = > {
const { shouldBeAuthenticated , fetchData } = options
return async ( context ) = > {
const cookies = new Cookies ( context . req . headers . cookie )
2023-10-23 23:33:39 +02:00
const refreshToken = cookies . get ( "refreshToken" )
2021-10-24 06:09:43 +02:00
let tokens : Tokens | null = null
if ( refreshToken != null ) {
try {
tokens = await fetchRefreshToken ( refreshToken )
} catch {
2023-10-23 23:33:39 +02:00
cookies . remove ( "refreshToken" )
2021-10-24 06:09:43 +02:00
}
}
if ( ! shouldBeAuthenticated ) {
if ( tokens != null ) {
return {
redirect : {
2023-10-23 23:33:39 +02:00
destination : "/application" ,
permanent : false ,
} ,
2021-10-24 06:09:43 +02:00
}
} else {
2022-08-30 21:30:06 +02:00
let data : any = { }
2021-10-24 06:09:43 +02:00
if ( fetchData != null ) {
2022-01-01 20:42:25 +01:00
data = await fetchData ( context , api )
2021-10-24 06:09:43 +02:00
}
2022-08-30 21:30:06 +02:00
if ( data . notFound != null ) {
return data
}
2022-01-01 20:42:25 +01:00
return { props : data }
2021-10-24 06:09:43 +02:00
}
} else {
if ( tokens == null ) {
return {
redirect : {
2023-10-23 23:33:39 +02:00
destination : "/authentication/signin" ,
permanent : false ,
} ,
2021-10-24 06:09:43 +02:00
}
} else {
2022-01-01 20:42:25 +01:00
try {
let data : any = { }
2022-08-30 21:30:06 +02:00
const authentication = new Authentication ( tokens )
2022-01-01 20:42:25 +01:00
const { data : currentUser } = await authentication . api . get <
unknown ,
AxiosResponse < UserCurrent >
2023-10-23 23:33:39 +02:00
> ( "/users/current" )
2022-01-01 20:42:25 +01:00
if ( fetchData != null ) {
data = await fetchData ( context , authentication . api )
}
2022-08-30 21:30:06 +02:00
if ( data . notFound != null ) {
2022-01-01 20:42:25 +01:00
return data
}
return {
2023-10-23 23:33:39 +02:00
props : { authentication : { tokens , . . . currentUser } , . . . data } ,
2022-01-01 20:42:25 +01:00
}
} catch {
return {
2023-10-23 23:33:39 +02:00
notFound : true ,
2022-01-01 20:42:25 +01:00
}
2021-10-24 06:09:43 +02:00
}
}
}
}
}