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

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
}
}
}
}
}
}