pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: https://github.com/payloadcms/payload/commit/9c58e7c

ets.com/assets/github-cf976967feea1e66.css" /> fix(plugin-multi-tenant): forbidden error when logging in as a user w… · payloadcms/payload@9c58e7c · GitHub
Skip to content

Commit 9c58e7c

Browse files
authored
fix(plugin-multi-tenant): forbidden error when logging in as a user with no tenant and no access to all tenants (#16047)
Previously, if you logged in as a user without: * Any tenant value * `userHasAccessToAllTenants` is not defined / the condition does not meet for this user You'd see this error (the admin panel crashes): <img width="1904" height="600" alt="image" src="https://github.com/user-attachments/assets/ff4f3358-8697-400c-adae-5e512369f386" /> Why? because the call uses `overrideAccess: false` and that user does not have access to the `tenants` collection. Now we early return `[]` in that case Added an E2E test that previously failed. --- - To see the specific tasks where the Asana app for GitHub is being used, see below: - https://app.asana.com/0/0/1213815640035525
1 parent db4b00e commit 9c58e7c

6 files changed

Lines changed: 52 additions & 1 deletion

File tree

packages/plugin-multi-tenant/src/utilities/getTenantOptions.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ export const getTenantOptions = async ({
3939
})
4040
: undefined
4141

42+
if (userTenantIds !== undefined && userTenantIds.length === 0) {
43+
return tenantOptions
44+
}
45+
4246
const tenants = await payload.find({
4347
collection: tenantsCollectionSlug,
4448
depth: 0,

test/plugin-multi-tenant/collections/Tenants.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@ const tenantAccess: Access = ({ req }) => {
3333
],
3434
}
3535
}
36+
37+
// authenticated user with no tenants has no access
38+
return false
3639
}
3740

38-
// if the user has no assigned tenants, return a filter that allows access to public tenants
41+
// unauthenticated — allow access to public tenants only
3942
return {
4043
isPublic: {
4144
equals: true,

test/plugin-multi-tenant/credentials.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ export const credentials = {
77
88
password: 'test',
99
},
10+
noTenant: {
11+
12+
password: 'test',
13+
},
1014
owner: {
1115
1216
password: 'test',

test/plugin-multi-tenant/e2e.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,24 @@ test.describe('Multi Tenant', () => {
703703
.toEqual(['Blue Dog', 'Anchor Bar'].sort())
704704
})
705705

706+
test('should not throw forbidden error when user has no tenants assigned', async () => {
707+
await loginClientSide({
708+
data: credentials.noTenant,
709+
page,
710+
serverURL,
711+
})
712+
713+
// Navigate to a page that triggers getTenantOptions - previously caused a
714+
// "Runtime Forbidden" error because payload.find() was called with an empty
715+
// userTenantIds array and overrideAccess: false
716+
await page.goto(menuItemsURL.list)
717+
718+
// Ensure the Next.js runtime error overlay is not shown
719+
await expect(page.locator('body')).not.toContainText(
720+
'You are not allowed to perform this action.',
721+
)
722+
})
723+
706724
test('should not show public tenants to users with assigned tenants', async () => {
707725
await loginClientSide({
708726
data: credentials.owner,

test/plugin-multi-tenant/payload-types.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ export interface Config {
106106
globals: {};
107107
globalsSelect: {};
108108
locale: 'en' | 'es' | 'fr';
109+
widgets: {
110+
collections: CollectionsWidget;
111+
};
109112
user: User;
110113
jobs: {
111114
tasks: unknown;
@@ -543,6 +546,16 @@ export interface PayloadMigrationsSelect<T extends boolean = true> {
543546
updatedAt?: T;
544547
createdAt?: T;
545548
}
549+
/**
550+
* This interface was referenced by `Config`'s JSON-Schema
551+
* via the `definition` "collections_widget".
552+
*/
553+
export interface CollectionsWidget {
554+
data?: {
555+
[k: string]: unknown;
556+
};
557+
width: 'full';
558+
}
546559
/**
547560
* This interface was referenced by `Config`'s JSON-Schema
548561
* via the `definition` "auth".

test/plugin-multi-tenant/seed/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,4 +227,13 @@ export const seed = async (payload: Payload) => {
227227
],
228228
},
229229
})
230+
231+
await payload.create({
232+
collection: usersSlug,
233+
data: {
234+
...credentials.noTenant,
235+
roles: ['user'],
236+
// tenants: [],
237+
},
238+
})
230239
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy