You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: move trash out of beta and delete access can now be limited to trash only (#15210)
### Access control can be limited to only trash
You can now limit users to only trash without being able to permanently
delete:
```ts
import type { CollectionConfig } from 'payload'
export const Posts: CollectionConfig = {
slug: 'posts',
trash: true,
access: {
delete: ({ req: { user }, data }) => {
// Not logged in - no access
if (!user) {
return false
}
// Admins can do anything (trash or permanently delete)
if (user.roles?.includes('admin')) {
return true
}
// Regular users: check what operation they're attempting
// If data.deletedAt is being set, it's a trash operation - allow it
if (data?.deletedAt) {
return true
}
// Otherwise it's a permanent delete - deny for non-admins
return false
},
},
fields: [
// ...
],
}
```
---------
Co-authored-by: Patrik Kozak <35232443+PatrikKozak@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
|**`req`**| The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object with additional `user` property, which is the currently logged in user. |
|**`req`**| The [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object with additional `user` property, which is the currently logged in user. |
264
+
|**`id`**|`id` of document requested to delete. |
265
+
|**`data`**| The data being set on the document. For [Trash-enabled](../trash/overview) collections, check `data.deletedAt` to differentiate between soft delete and permanent delete operations. |
266
+
267
+
<Bannertype="success">
268
+
**Tip:** For Collections with [Trash](../trash/overview) enabled, you can use
269
+
the `data` argument to allow users to soft delete (trash) documents while
270
+
restricting permanent deletion. See [Trash Access
271
+
Control](../trash/overview#access-control) for examples.
Copy file name to clipboardExpand all lines: docs/trash/overview.mdx
+74-6Lines changed: 74 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,11 +10,6 @@ Trash (also known as soft delete) allows documents to be marked as deleted witho
10
10
11
11
Soft delete is a safer way to manage content lifecycle, giving editors a chance to review and recover documents that may have been deleted by mistake.
12
12
13
-
<Bannertype="warning">
14
-
**Note:** The Trash feature is currently in beta and may be subject to change
15
-
in minor version updates.
16
-
</Banner>
17
-
18
13
## Collection Configuration
19
14
20
15
To enable soft deleting for a collection, set the `trash` property to `true`:
@@ -183,12 +178,85 @@ query {
183
178
184
179
## Access Control
185
180
186
-
All trash-related actions (delete, permanent delete) respect the `delete` access control defined in your collection config.
181
+
All trash-related actions (soft delete, permanent delete, restore) respect the `delete` access control defined in your collection config.
187
182
188
183
This means:
189
184
190
185
- If a user is denied delete access, they cannot soft delete or permanently delete documents
191
186
187
+
### Differentiating Between Trash and Permanent Delete
188
+
189
+
You can configure access control to allow some users to trash documents while restricting permanent deletion to admins only. This is useful when you want editors to be able to "delete" content (move to trash) but only allow administrators to permanently remove data.
190
+
191
+
The `delete` access control function receives a `data` argument that contains the document data being set during the operation:
192
+
193
+
-**When trashing:**`data.deletedAt` will be set to a timestamp
194
+
-**When permanently deleting:**`data` will be `undefined`
195
+
196
+
This pattern is similar to how `publish` access control works with `data._status`.
197
+
198
+
#### Example: Allow All Users to Trash, Only Admins to Permanently Delete
199
+
200
+
```ts
201
+
importtype { CollectionConfig } from'payload'
202
+
203
+
exportconst Posts:CollectionConfig= {
204
+
slug: 'posts',
205
+
trash: true,
206
+
access: {
207
+
delete: ({ req: { user }, data }) => {
208
+
// Not logged in - no access
209
+
if (!user) {
210
+
returnfalse
211
+
}
212
+
213
+
// Admins can do anything (trash or permanently delete)
214
+
if (user.roles?.includes('admin')) {
215
+
returntrue
216
+
}
217
+
218
+
// Regular users: check what operation they're attempting
219
+
// If data.deletedAt is being set, it's a trash operation - allow it
220
+
if (data?.deletedAt) {
221
+
returntrue
222
+
}
223
+
224
+
// Otherwise it's a permanent delete - deny for non-admins
225
+
returnfalse
226
+
},
227
+
},
228
+
fields: [
229
+
// ...
230
+
],
231
+
}
232
+
```
233
+
234
+
#### Example: Only Admins Can Delete (Both Trash and Permanent)
235
+
236
+
```ts
237
+
importtype { CollectionConfig } from'payload'
238
+
239
+
exportconst SensitiveData:CollectionConfig= {
240
+
slug: 'sensitive-data',
241
+
trash: true,
242
+
access: {
243
+
delete: ({ req: { user } }) => {
244
+
// Only allow admins to trash or permanently delete
245
+
returnBoolean(user?.roles?.includes('admin'))
246
+
},
247
+
},
248
+
fields: [
249
+
// ...
250
+
],
251
+
}
252
+
```
253
+
254
+
In the Admin Panel, when a user has permission to trash but not permanently delete:
255
+
256
+
- The delete button will be visible
257
+
- The "Delete permanently" checkbox in the confirmation modal will be hidden
0 commit comments