## What Before this PR, an internal link in the Lexical editor could reference a document from a different tenant than the active one. Reproduction: 1. `pnpm dev plugin-multi-tenant` 2. Log in with `dev@payloadcms.com` and password `test` 3. Go to `http://localhost:3000/admin/collections/food-items` and switch between the `Blue Dog` and `Steel Cat` tenants to see which food items each tenant has. 4. Go to http://localhost:3000/admin/collections/food-items/create, and in the new richtext field enter an internal link 5. In the relationship select menu, you will see the 6 food items at once (3 of each of those tenants). In the relationship select menu, you would previously see all 6 food items at once (3 from each of those tenants). Now, you'll only see the 3 from the active tenant. The new test verifies that this is fixed. ## How `baseListFilter` is used, but now it's called `baseFilter` for obvious reasons: it doesn't just filter the List View. Having two different properties where the same function was supposed to be placed wasn't feasible. `baseListFilter` is still supported for backwards compatibility. It's used as a fallback if `baseFilter` isn't defined, and it's documented as deprecated. `baseFilter` is injected into `filterOptions` of the internal link field in the Lexical Editor.
99 lines
2.1 KiB
TypeScript
99 lines
2.1 KiB
TypeScript
import type { Access, CollectionConfig, Where } from 'payload'
|
|
|
|
import { getUserTenantIDs } from '@payloadcms/plugin-multi-tenant/utilities'
|
|
|
|
import { menuItemsSlug } from '../shared.js'
|
|
|
|
const collectionTenantReadAccess: Access = ({ req }) => {
|
|
// admins can access all tenants
|
|
if (req?.user?.roles?.includes('admin')) {
|
|
return true
|
|
}
|
|
|
|
if (req.user) {
|
|
const assignedTenants = getUserTenantIDs(req.user, {
|
|
tenantsArrayFieldName: 'tenants',
|
|
tenantsArrayTenantFieldName: 'tenant',
|
|
})
|
|
|
|
// if the user has assigned tenants, add id constraint
|
|
if (assignedTenants.length > 0) {
|
|
return {
|
|
or: [
|
|
{
|
|
tenant: {
|
|
in: assignedTenants,
|
|
},
|
|
},
|
|
{
|
|
'tenant.isPublic': {
|
|
equals: true,
|
|
},
|
|
},
|
|
],
|
|
}
|
|
}
|
|
}
|
|
|
|
// if the user has no assigned tenants, return a filter that allows access to public tenants
|
|
return {
|
|
'tenant.isPublic': {
|
|
equals: true,
|
|
},
|
|
} as Where
|
|
}
|
|
|
|
const collectionTenantUpdateAccess: Access = ({ req }) => {
|
|
// admins can update all tenants
|
|
if (req?.user?.roles?.includes('admin')) {
|
|
return true
|
|
}
|
|
|
|
if (req.user) {
|
|
const assignedTenants = getUserTenantIDs(req.user, {
|
|
tenantsArrayFieldName: 'tenants',
|
|
tenantsArrayTenantFieldName: 'tenant',
|
|
})
|
|
|
|
// if the user has assigned tenants, add id constraint
|
|
if (assignedTenants.length > 0) {
|
|
return {
|
|
tenant: {
|
|
in: assignedTenants,
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
export const MenuItems: CollectionConfig = {
|
|
slug: menuItemsSlug,
|
|
access: {
|
|
read: collectionTenantReadAccess,
|
|
create: ({ req }) => {
|
|
return Boolean(req?.user?.roles?.includes('admin'))
|
|
},
|
|
update: collectionTenantUpdateAccess,
|
|
delete: ({ req }) => {
|
|
return Boolean(req?.user?.roles?.includes('admin'))
|
|
},
|
|
},
|
|
admin: {
|
|
useAsTitle: 'name',
|
|
group: 'Tenant Collections',
|
|
},
|
|
fields: [
|
|
{
|
|
name: 'name',
|
|
type: 'text',
|
|
required: true,
|
|
},
|
|
{
|
|
name: 'content',
|
|
type: 'richText',
|
|
},
|
|
],
|
|
}
|