-
|
I need to store many different settings related to the user, like:
I think storing all these directly in the So, the first idea that came to mind is to create a separate collection But I got stuck with the permission control for the I have no user id value or any other relation to a concrete user in the I can add a relationship field back to the user, but this will duplicate the information and make things more complex! Also, I can add a "join" field that will provide a reference to the user, but the join field is mostly for one-to-many relationships, and will slow down loading the settings by an additional database join. But I want to keep it as simple as possible! So, asking for experience from the Payload community, how do you usually handle this? Please share your recommendations and the best approaches! |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
|
I found that Payload provides a local API to get and set the per-user preferences ( So, for example, if we need to load the user, the appearance settings, notification settings, and the pinned items, there will be 4 separate database queries. Also, reading these preferences does not seem to be available via the REST and GraphQL API, and it's not easy to update the preference of another user, because the function |
Beta Was this translation helpful? Give feedback.
-
|
The cleanest approach for per-user settings in Payload — without duplicating data or incurring expensive joins — is to store the relationship on the Recommended pattern// collections/UserSettings.ts
import type { CollectionConfig } from 'payload'
export const UserSettings: CollectionConfig = {
slug: 'user-settings',
access: {
create: ({ req }) => Boolean(req.user), // logged-in users only
read: ({ req }) => {
if (!req.user) return false
// Only return docs where `owner` matches the logged-in user
return {
owner: { equals: req.user.id },
}
},
update: ({ req }) => {
if (!req.user) return false
return {
owner: { equals: req.user.id },
}
},
delete: () => false, // or admin-only
},
fields: [
{
name: 'owner',
type: 'relationship',
relationTo: 'users',
required: true,
// Hide from admin UI list view if you want
admin: { position: 'sidebar' },
},
{
name: 'notifications',
type: 'group',
fields: [
{ name: 'enabled', type: 'checkbox', defaultValue: true },
{ name: 'categories', type: 'array', fields: [{ name: 'category', type: 'text' }] },
],
},
{
name: 'pinnedItems',
type: 'array',
fields: [{ name: 'itemId', type: 'text' }],
},
{
name: 'appearance',
type: 'select',
options: ['light', 'dark', 'system'],
defaultValue: 'system',
},
],
}Why this works well
On the User collectionYou can optionally add a // In your Users collection fields:
{
name: 'settings',
type: 'join',
collection: 'user-settings',
on: 'owner',
maxDepth: 0, // don't auto-populate in list queries
}Setting Creating settings on user creationUse an afterChange: [
async ({ doc, operation, req }) => {
if (operation === 'create') {
await req.payload.create({
collection: 'user-settings',
data: { owner: doc.id },
})
}
},
],This is the pattern most Payload apps use for per-user data — it's simple, performant, and Payload's access control constraint syntax handles all the security. |
Beta Was this translation helpful? Give feedback.
The cleanest approach for per-user settings in Payload — without duplicating data or incurring expensive joins — is to store the relationship on the
UserSettingsdocument pointing back to the user, then use access control functions that check that field.Recommended pattern