mirror of
https://github.com/dsoaress/link-free.git
synced 2026-08-18 23:46:04 +01:00
feat: add protect routes
This commit is contained in:
@@ -2,8 +2,9 @@ import { useState } from 'react'
|
|||||||
|
|
||||||
import { useAuth } from 'hooks/useAuth'
|
import { useAuth } from 'hooks/useAuth'
|
||||||
import { fetchData } from 'services/fetchData'
|
import { fetchData } from 'services/fetchData'
|
||||||
|
import { guestUserRoute } from 'utils/guestUserRoute'
|
||||||
|
|
||||||
import type { GetStaticProps } from 'next'
|
import type { GetServerSideProps } from 'next'
|
||||||
|
|
||||||
export default function AuthPage() {
|
export default function AuthPage() {
|
||||||
const { signIn } = useAuth()
|
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()
|
const initialData = await fetchData()
|
||||||
return { props: { initialData }, revalidate: 1 }
|
return { props: { initialData } }
|
||||||
}
|
})
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Dash } from 'components/Dash'
|
import { Dash } from 'components/Dash'
|
||||||
import { fetchData } from 'services/fetchData'
|
import { fetchData } from 'services/fetchData'
|
||||||
|
import { authenticatedUserRoute } from 'utils/authenticatedUserRoute'
|
||||||
|
|
||||||
import type { GetServerSideProps } from 'next'
|
import type { GetServerSideProps } from 'next'
|
||||||
import type { Data } from 'types/Data'
|
import type { Data } from 'types/Data'
|
||||||
@@ -12,7 +13,10 @@ export default function DashPage({ initialData }: DashPageProps) {
|
|||||||
return <Dash initialData={initialData} />
|
return <Dash initialData={initialData} />
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getServerSideProps: GetServerSideProps = async () => {
|
export const getServerSideProps: GetServerSideProps = authenticatedUserRoute(
|
||||||
const initialData = await fetchData()
|
async () => {
|
||||||
return { props: { initialData } }
|
const initialData = await fetchData()
|
||||||
}
|
return { props: { initialData } }
|
||||||
|
},
|
||||||
|
{ roles: ['ADMIN', 'EDITOR'] }
|
||||||
|
)
|
||||||
|
|||||||
46
src/utils/authenticatedUserRoute.ts
Normal file
46
src/utils/authenticatedUserRoute.ts
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/utils/guestUserRoute.ts
Normal file
20
src/utils/guestUserRoute.ts
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/utils/validateUserPermissions.ts
Normal file
20
src/utils/validateUserPermissions.ts
Normal 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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user