diff --git a/app/collection/items/[slug]/components/carousel.tsx b/app/collection/items/[slug]/components/carousel.tsx
index 6d6896fa..f05d649a 100644
--- a/app/collection/items/[slug]/components/carousel.tsx
+++ b/app/collection/items/[slug]/components/carousel.tsx
@@ -7,6 +7,7 @@ import NextImage from 'next/image'
import clsx from 'clsx'
import { ImagesEdit } from './edit-fields/images-edit'
import { type BarometerDTO } from '@/app/types'
+import { IsAdmin } from '@/app/components/is-admin'
import 'swiper/css'
import 'swiper/css/zoom'
import 'swiper/css/navigation'
@@ -16,13 +17,14 @@ import './styles.css'
interface ImageCarouselProps {
images: string[]
barometer: BarometerDTO
- isAdmin: boolean
}
-export function ImageCarousel({ images, barometer, isAdmin }: ImageCarouselProps) {
+export function ImageCarousel({ images, barometer }: ImageCarouselProps) {
return (
- {isAdmin && }
+
+
+
1}
diff --git a/app/collection/items/[slug]/page.tsx b/app/collection/items/[slug]/page.tsx
index fc5dba21..3c7efe9b 100644
--- a/app/collection/items/[slug]/page.tsx
+++ b/app/collection/items/[slug]/page.tsx
@@ -1,9 +1,6 @@
import { type Metadata } from 'next'
-import { getServerSession } from 'next-auth'
import capitalize from 'lodash/capitalize'
import { Container, Title, Text, Box, Divider, Tooltip } from '@mantine/core'
-import { AccessRole } from '@prisma/client'
-import { authConfig, getUserByEmail } from '@/utils/auth'
import { googleStorageImagesFolder, barometerRoute } from '@/app/constants'
import { ImageCarousel } from './components/carousel'
import { Condition } from './components/condition'
@@ -19,6 +16,7 @@ import { title, openGraph, twitter } from '@/app/metadata'
import { Dimensions } from '@/app/types'
import { withPrisma } from '@/prisma/prismaClient'
import { getBarometer } from '@/app/api/v2/barometers/[slug]/getters'
+import { IsAdmin } from '@/app/components/is-admin'
export const dynamic = 'force-static'
@@ -71,20 +69,7 @@ export const generateStaticParams = withPrisma(prisma =>
prisma.barometer.findMany({ select: { slug: true } }),
)
-async function isAuthorized(): Promise {
- try {
- const session = await getServerSession(authConfig)
- const email = session?.user?.email
- if (!email) return false
- const { role } = await getUserByEmail(email)
- return role === AccessRole.ADMIN
- } catch (error) {
- return false
- }
-}
-
export default async function BarometerItem({ params: { slug } }: BarometerItemProps) {
- const isAdmin = await isAuthorized()
const barometer = await getBarometer(slug)
const { name, images, description, manufacturer, dateDescription, condition, collectionId } =
barometer
@@ -94,7 +79,6 @@ export default async function BarometerItem({ params: { slug } }: BarometerItemP
googleStorageImagesFolder + image)}
/>
@@ -102,7 +86,9 @@ export default async function BarometerItem({ params: { slug } }: BarometerItemP
{`${name.split(' ').slice(0, -1).join(' ')} `}
{name.split(' ').at(-1)}
- {isAdmin && }
+
+
+
{collectionId}
@@ -116,7 +102,9 @@ export default async function BarometerItem({ params: { slug } }: BarometerItemP
{`${manufacturer.name}${manufacturer.city ? `, ${manufacturer.city}` : ''}`}
- {isAdmin && }
+
+
+
)}
@@ -127,7 +115,9 @@ export default async function BarometerItem({ params: { slug } }: BarometerItemP
{dateDescription}
- {isAdmin && }
+
+
+
@@ -141,28 +131,38 @@ export default async function BarometerItem({ params: { slug } }: BarometerItemP
{index < arr.length - 1 ? ', ' : ''}
))}
- {isAdmin && }
+
+
+
)}
}
+ editButton={
+
+
+
+ }
/>
,
- labelPosition: 'right',
- })}
+ labelPosition="right"
+ label={
+
+
+
+ }
/>
{description ? (
) : (
- isAdmin && Add description
+
+ Add description
+
)}
diff --git a/app/components/header/menudata.ts b/app/components/header/menudata.ts
index a4652c74..f197f9d3 100644
--- a/app/components/header/menudata.ts
+++ b/app/components/header/menudata.ts
@@ -1,9 +1,10 @@
-type UserType = 'Simple' | 'Admin'
+import { AccessRole } from '@prisma/client'
+
interface MenuItem {
id: number
label: string
link: string
- visibleFor?: UserType
+ visibleFor?: AccessRole
}
export const menuData: MenuItem[] = [
@@ -36,6 +37,6 @@ export const menuData: MenuItem[] = [
id: 10,
label: 'Admin',
link: 'admin',
- visibleFor: 'Admin',
+ visibleFor: AccessRole.ADMIN,
},
]
diff --git a/app/components/header/mobile-menu/mobile-menu.tsx b/app/components/header/mobile-menu/mobile-menu.tsx
index e1437c56..a027c01b 100644
--- a/app/components/header/mobile-menu/mobile-menu.tsx
+++ b/app/components/header/mobile-menu/mobile-menu.tsx
@@ -19,13 +19,14 @@ import * as motion from 'framer-motion/client'
import { SiMaildotru, SiInstagram } from 'react-icons/si'
import { IoIosArrowForward as Arrow } from 'react-icons/io'
import { useSession } from 'next-auth/react'
+import { AccessRole } from '@prisma/client'
import { instagram, email, barometerTypesRoute } from '@/app/constants'
import { menuData } from '../menudata'
import { useBarometers } from '@/app/hooks/useBarometers'
+import { isAdmin } from '../../is-admin'
export const MobileMenu: FC = props => {
- const { status } = useSession()
- const isLoggedId = status === 'authenticated'
+ const { data: session } = useSession()
const [opened, setOpened] = useState>({})
const toggle = (index: number) => setOpened(old => ({ ...old, [index]: !old[index] }))
const { categories } = useBarometers()
@@ -57,7 +58,8 @@ export const MobileMenu: FC = props => {
{menuData
.filter(
({ visibleFor }) =>
- typeof visibleFor === 'undefined' || (isLoggedId && visibleFor === 'Admin'),
+ typeof visibleFor === 'undefined' ||
+ (isAdmin(session) && visibleFor === AccessRole.ADMIN),
)
.map((outer, i, arr) => (
diff --git a/app/components/header/tabs/tabs.tsx b/app/components/header/tabs/tabs.tsx
index 6d48dfe4..615386cb 100644
--- a/app/components/header/tabs/tabs.tsx
+++ b/app/components/header/tabs/tabs.tsx
@@ -7,15 +7,16 @@ import clsx from 'clsx'
import dynamic from 'next/dynamic'
import Link from 'next/link'
import { useSession } from 'next-auth/react'
+import { AccessRole } from '@prisma/client'
import sx from './tabs.module.scss'
import { menuData } from '../menudata'
import { useBarometers } from '@/app/hooks/useBarometers'
import { barometerTypesRoute } from '@/app/constants'
+import { isAdmin } from '../../is-admin'
const WideScreenTabs = ({ className, ...props }: CenterProps) => {
const { categories: types } = useBarometers()
- const { status } = useSession()
- const isLoggedId = status === 'authenticated'
+ const { data: session } = useSession()
const router = useRouter()
const pathname = usePathname()
const [activeTab, setActiveTab] = useState(-1)
@@ -45,7 +46,8 @@ const WideScreenTabs = ({ className, ...props }: CenterProps) => {
{menuData
.filter(
({ visibleFor }) =>
- typeof visibleFor === 'undefined' || (isLoggedId && visibleFor === 'Admin'),
+ typeof visibleFor === 'undefined' ||
+ (isAdmin(session) && visibleFor === AccessRole.ADMIN),
)
.map((menuitem, i) => {
const renderTab = (key?: Key) => (
diff --git a/app/components/is-admin/index.ts b/app/components/is-admin/index.ts
new file mode 100644
index 00000000..fb765b4e
--- /dev/null
+++ b/app/components/is-admin/index.ts
@@ -0,0 +1 @@
+export { IsAdmin, isAdmin } from './is-admin'
diff --git a/app/components/is-admin/is-admin.tsx b/app/components/is-admin/is-admin.tsx
new file mode 100644
index 00000000..73de619e
--- /dev/null
+++ b/app/components/is-admin/is-admin.tsx
@@ -0,0 +1,16 @@
+'use client'
+
+import { type PropsWithChildren } from 'react'
+import { useSession } from 'next-auth/react'
+import { AccessRole } from '@prisma/client'
+import { Session } from 'next-auth'
+
+export function isAdmin(session: Session | null): boolean {
+ const user = session?.user
+ return user?.role === AccessRole.ADMIN
+}
+
+export function IsAdmin({ children }: PropsWithChildren) {
+ const { data } = useSession()
+ return isAdmin(data) ? <>{children}> : <>>
+}
diff --git a/env.d.ts b/env.d.ts
index 6d0c8a23..b9f9f94b 100644
--- a/env.d.ts
+++ b/env.d.ts
@@ -1,3 +1,5 @@
+import { AccessRole } from '@prisma/client'
+
declare namespace NodeJS {
interface ProcessEnv {
AUTH_SECRET: string
@@ -9,3 +11,18 @@ declare namespace NodeJS {
GCP_PRIVATE_KEY: string
}
}
+
+declare module 'next-auth' {
+ interface User {
+ role?: AccessRole
+ }
+ interface Session {
+ user: User
+ }
+}
+
+declare module 'next-auth/jwt' {
+ interface JWT {
+ role?: AccessRole
+ }
+}
diff --git a/utils/auth.ts b/utils/auth.ts
index 2519dfcd..f0df4bd9 100644
--- a/utils/auth.ts
+++ b/utils/auth.ts
@@ -27,6 +27,7 @@ export const authConfig: AuthOptions = {
email: user.email,
name: user.name,
image: user.avatarURL,
+ role: user.role,
} as User
},
}),
@@ -38,4 +39,20 @@ export const authConfig: AuthOptions = {
session: {
strategy: 'jwt',
},
+ callbacks: {
+ async jwt({ token, user }) {
+ // Adding Role to token if it exists in User
+ if (user?.role) {
+ token.role = user.role
+ }
+ return token
+ },
+ async session({ session, token }) {
+ // Passing role from token to session
+ if (token.role) {
+ session.user.role = token.role
+ }
+ return session
+ },
+ },
}