2021-10-26 16:38:55 +02:00
import { AxiosInstance , AxiosResponse } from 'axios'
2022-01-01 20:42:25 +01:00
import { GetServerSideProps , GetServerSidePropsContext } from 'next'
2021-10-24 06:09:43 +02:00
2021-10-26 16:38:55 +02:00
import { api } from '../api'
import { Cookies } from '../cookies'
2021-10-24 06:09:43 +02:00
import { RefreshTokenResponse , Tokens } from './index'
import { Authentication } from './Authentication'
2021-10-26 16:38:55 +02:00
import { UserCurrent } from '../../models/User'
2021-10-24 06:09:43 +02:00
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 ,
2022-01-01 20:42:25 +01:00
api : AxiosInstance
2021-10-24 06:09:43 +02:00
) = > 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 = { }
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-01-01 20:42:25 +01:00
return { props : data }
2021-10-24 06:09:43 +02:00
}
} else {
if ( tokens == null ) {
return {
redirect : {
destination : '/authentication/signin' ,
permanent : false
}
}
} else {
2022-01-01 20:42:25 +01:00
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 . redirect != null ) {
return data
}
return {
props : { authentication : { tokens , . . . currentUser } , . . . data }
}
} catch {
return {
redirect : {
destination : '/404' ,
permanent : false
}
}
2021-10-24 06:09:43 +02:00
}
}
}
}
}