feat: access control

This commit is contained in:
Yehoshua Sandler 2025-05-03 23:54:25 -05:00
parent 31b2180726
commit 461df9d7ba
12 changed files with 63 additions and 30 deletions

7
src/access/admin.ts Normal file
View File

@ -0,0 +1,7 @@
import { User } from '@/payload-types'
import type { AccessArgs } from 'payload'
type isAdmin = (args: AccessArgs<User>) => boolean
export const admin: isAdmin = ({ req: { user } }) => user?.role === 'admin'

3
src/access/anyone.ts Normal file
View File

@ -0,0 +1,3 @@
import type { Access } from 'payload'
export const anyone: Access = () => true

View File

@ -0,0 +1,9 @@
import type { AccessArgs } from 'payload'
import type { User } from '@/payload-types'
type isAuthenticated = (args: AccessArgs<User>) => boolean
export const authenticated: isAuthenticated = ({ req: { user } }) => {
return Boolean(user)
}

View File

@ -1,3 +1,5 @@
import { admin } from '@/access/admin'
import { authenticated } from '@/access/authenticated'
import type { CollectionConfig } from 'payload' import type { CollectionConfig } from 'payload'
export const Authors: CollectionConfig = { export const Authors: CollectionConfig = {
@ -10,9 +12,9 @@ export const Authors: CollectionConfig = {
}, },
access: { access: {
read: () => true, read: () => true,
update: () => true, update: admin,
create: () => true, create: authenticated,
admin: () => true, delete: admin,
}, },
fields: [ fields: [
{ {

View File

@ -1,3 +1,5 @@
import { admin } from "@/access/admin";
import { authenticated } from "@/access/authenticated";
import { CollectionConfig } from "payload"; import { CollectionConfig } from "payload";
export const Books: CollectionConfig = { export const Books: CollectionConfig = {
@ -7,9 +9,9 @@ export const Books: CollectionConfig = {
}, },
access: { access: {
read: () => true, read: () => true,
update: () => true, update: admin,
create: () => true, create: authenticated,
admin: () => true, delete: admin,
}, },
fields: [ fields: [
{ {

View File

@ -1,3 +1,4 @@
import { admin } from "@/access/admin";
import { CollectionConfig } from "payload"; import { CollectionConfig } from "payload";
export const Genre: CollectionConfig = { export const Genre: CollectionConfig = {
@ -7,9 +8,9 @@ export const Genre: CollectionConfig = {
}, },
access: { access: {
read: () => true, read: () => true,
update: () => true, update: admin,
create: () => true, create: () => true,
admin: () => true, delete: admin,
}, },
fields: [ fields: [
{ {

View File

@ -1,7 +1,15 @@
import { admin } from "@/access/admin";
import { authenticated } from "@/access/authenticated";
import { CollectionConfig } from "payload"; import { CollectionConfig } from "payload";
const Checkouts: CollectionConfig = { const Checkouts: CollectionConfig = {
slug: 'checkouts', slug: 'checkouts',
access: {
read: () => true,
update: admin,
create: authenticated,
delete: admin,
},
fields: [ fields: [
{ {
name: 'fromHold', name: 'fromHold',

View File

@ -1,7 +1,15 @@
import { admin } from "@/access/admin";
import { authenticated } from "@/access/authenticated";
import { CollectionConfig } from "payload"; import { CollectionConfig } from "payload";
const HoldRequests: CollectionConfig = { const HoldRequests: CollectionConfig = {
slug: 'holdRequests', slug: 'holdRequests',
access: {
read: () => true,
update: admin,
create: authenticated,
delete: admin,
},
fields: [ fields: [
{ {
name: 'copy', name: 'copy',

View File

@ -28,17 +28,10 @@ const beforeValidate: CollectionBeforeValidateHook = async ({ data, req }) => {
} else return doc } else return doc
return { ...doc, label: `[${repositoryName}] ${bookName}` } return { ...doc, label: `[${repositoryName}] ${bookName}` }
} }
export const Copies: CollectionConfig = { export const Copies: CollectionConfig = {
slug: 'copies', slug: 'copies',
access: {
read: () => true,
update: () => true,
create: () => true,
admin: () => true,
},
admin: { admin: {
useAsTitle: 'label', useAsTitle: 'label',
pagination: { pagination: {
@ -96,6 +89,7 @@ export const Copies: CollectionConfig = {
} }
], ],
hooks: { hooks: {
beforeValidate: [beforeValidate] beforeValidate: [beforeValidate],
//beforeRead: [beforeRead],
}, },
} }

View File

@ -1,3 +1,5 @@
import { admin } from "@/access/admin";
import { authenticated } from "@/access/authenticated";
import { CollectionConfig } from "payload"; import { CollectionConfig } from "payload";
export const Repositories: CollectionConfig = { export const Repositories: CollectionConfig = {
@ -5,6 +7,12 @@ export const Repositories: CollectionConfig = {
admin: { admin: {
useAsTitle: 'name' useAsTitle: 'name'
}, },
access: {
read: () => true,
update: admin,
create: authenticated,
delete: admin,
},
fields: [ fields: [
{ {
name: 'name', name: 'name',

View File

@ -1,4 +1,4 @@
import { defaultAccess } from '@/lib/utils' import { admin } from '@/access/admin'
import type { CollectionConfig } from 'payload' import type { CollectionConfig } from 'payload'
const expirationInMinutes = parseInt(process.env.PASSWORD_RESET_EXPIRATION_IN_MINUTES || '30') const expirationInMinutes = parseInt(process.env.PASSWORD_RESET_EXPIRATION_IN_MINUTES || '30')
@ -9,6 +9,9 @@ export const Users: CollectionConfig = {
admin: { admin: {
useAsTitle: 'email', useAsTitle: 'email',
}, },
access: {
admin: admin
},
auth: { auth: {
// verify: { // verify: {
// generateEmailSubject: () => { // generateEmailSubject: () => {
@ -26,7 +29,6 @@ export const Users: CollectionConfig = {
// </body> // </body>
// </html> // </html>
// ` // `
//
// }, // },
// }, // },
forgotPassword: { forgotPassword: {
@ -54,14 +56,6 @@ export const Users: CollectionConfig = {
}, },
} }
}, },
access: {
...defaultAccess,
update: ({ req, data }) => {
if (req.user?.role === 'admin') return true
else if (data?.user.id === req.user?.id) return true
else return false
}
},
fields: [ fields: [
// Email added by default // Email added by default
// Add more fields as needed // Add more fields as needed

View File

@ -88,10 +88,7 @@ export function ForgotPasswordForm({ className, ...props }: React.ComponentProps
</CardDescription> </CardDescription>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<form <form onSubmit={token ? handleResetPasswordSubmit : handleForgotPasswordSubmit}>
onSubmit={token ? handleResetPasswordSubmit : handleForgotPasswordSubmit}
aria-disabled={isLoading}
>
<div className="grid gap-6"> <div className="grid gap-6">
<div className="grid gap-6"> <div className="grid gap-6">
{!token ? ( {!token ? (