fix(examples): checks requested tenant matches user tenant permissions (#13012)
### What This PR updates the `create` access control functions in the `multi-tenant` example to ensure that any `tenant` specified in a create request matches a tenant the user has admin access to. ### Why Previously, while the admin panel UI restricted the tenant selection, it was still possible to bypass this by making a request directly to the API with a different `tenant`. This allowed users to create documents under tenants they shouldn't have access to. ### How The `access` functions on the `users` and `pages` collections now explicitly check whether the tenant(s) in the request are included in the user's tenant permissions. If not, access is denied by returning `false`. **Fixes: CMS2-Q225-03**
This commit is contained in:
@@ -14,9 +14,12 @@ export const superAdminOrTenantAdminAccess: Access = ({ req }) => {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
const adminTenantAccessIDs = getUserTenantIDs(req.user, 'tenant-admin')
|
||||||
tenant: {
|
const requestedTenant = req?.data?.tenant
|
||||||
in: getUserTenantIDs(req.user, 'tenant-admin'),
|
|
||||||
},
|
if (requestedTenant && adminTenantAccessIDs.includes(requestedTenant)) {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { Access } from 'payload'
|
import type { Access } from 'payload'
|
||||||
|
|
||||||
import type { User } from '../../../payload-types'
|
import type { Tenant, User } from '../../../payload-types'
|
||||||
|
|
||||||
import { isSuperAdmin } from '../../../access/isSuperAdmin'
|
import { isSuperAdmin } from '../../../access/isSuperAdmin'
|
||||||
import { getUserTenantIDs } from '../../../utilities/getUserTenantIDs'
|
import { getUserTenantIDs } from '../../../utilities/getUserTenantIDs'
|
||||||
@@ -16,7 +16,14 @@ export const createAccess: Access<User> = ({ req }) => {
|
|||||||
|
|
||||||
const adminTenantAccessIDs = getUserTenantIDs(req.user, 'tenant-admin')
|
const adminTenantAccessIDs = getUserTenantIDs(req.user, 'tenant-admin')
|
||||||
|
|
||||||
if (adminTenantAccessIDs.length) {
|
const requestedTenants: Tenant['id'][] =
|
||||||
|
req.data?.tenants?.map((t: { tenant: Tenant['id'] }) => t.tenant) ?? []
|
||||||
|
|
||||||
|
const hasAccessToAllRequestedTenants = requestedTenants.every((tenantID) =>
|
||||||
|
adminTenantAccessIDs.includes(tenantID),
|
||||||
|
)
|
||||||
|
|
||||||
|
if (hasAccessToAllRequestedTenants) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user