feat: add protect routes

This commit is contained in:
Daniel Soares
2021-12-21 01:16:26 -03:00
parent be9758fd57
commit f977de999d
5 changed files with 99 additions and 8 deletions

View File

@@ -2,8 +2,9 @@ import { useState } from 'react'
import { useAuth } from 'hooks/useAuth'
import { fetchData } from 'services/fetchData'
import { guestUserRoute } from 'utils/guestUserRoute'
import type { GetStaticProps } from 'next'
import type { GetServerSideProps } from 'next'
export default function AuthPage() {
const { signIn } = useAuth()
@@ -36,7 +37,7 @@ export default function AuthPage() {
)
}
export const getStaticProps: GetStaticProps = async () => {
export const getServerSideProps: GetServerSideProps = guestUserRoute(async () => {
const initialData = await fetchData()
return { props: { initialData }, revalidate: 1 }
}
return { props: { initialData } }
})

View File

@@ -1,5 +1,6 @@
import { Dash } from 'components/Dash'
import { fetchData } from 'services/fetchData'
import { authenticatedUserRoute } from 'utils/authenticatedUserRoute'
import type { GetServerSideProps } from 'next'
import type { Data } from 'types/Data'
@@ -12,7 +13,10 @@ export default function DashPage({ initialData }: DashPageProps) {
return <Dash initialData={initialData} />
}
export const getServerSideProps: GetServerSideProps = async () => {
const initialData = await fetchData()
return { props: { initialData } }
}
export const getServerSideProps: GetServerSideProps = authenticatedUserRoute(
async () => {
const initialData = await fetchData()
return { props: { initialData } }
},
{ roles: ['ADMIN', 'EDITOR'] }
)

View File

@@ -0,0 +1,46 @@
import { GetServerSideProps, GetServerSidePropsContext } from 'next'
import { parseCookies } from 'nookies'
import { decode } from 'jsonwebtoken'
import { validateUserPermissions } from 'utils/validateUserPermissions'
import type { Role } from '@prisma/client'
type Options = {
roles: Role[]
}
export function authenticatedUserRoute(fn: GetServerSideProps, options?: Options) {
return async (ctx: GetServerSidePropsContext) => {
const { accessToken } = parseCookies(ctx)
if (!accessToken) {
return {
redirect: {
destination: '/auth',
permanent: false
}
}
}
const { role: userRole } = decode(accessToken) as { role: Role }
if (options) {
const userHasValidPermissions = validateUserPermissions({
userRole,
roles: options.roles
})
if (!userHasValidPermissions) {
return {
redirect: {
destination: '/',
permanent: false
}
}
}
}
return await fn(ctx)
}
}

View File

@@ -0,0 +1,20 @@
import { parseCookies } from 'nookies'
import type { GetStaticProps, GetServerSidePropsContext } from 'next'
export function guestUserRoute(fn: GetStaticProps) {
return async (ctx: GetServerSidePropsContext) => {
const { accessToken } = parseCookies(ctx)
if (accessToken) {
return {
redirect: {
destination: '/dash',
permanent: false
}
}
}
return await fn(ctx)
}
}

View File

@@ -0,0 +1,20 @@
import type { Role } from '@prisma/client'
type ValidateUserPermissionsParams = {
userRole: Role
roles?: Role[]
}
export function validateUserPermissions({ userRole, roles }: ValidateUserPermissionsParams) {
if (roles && roles.length > 0) {
const hasPermission = roles.some(role => {
return userRole.includes(role)
})
if (!hasPermission) {
return false
}
}
return true
}