From 51297d807678c686a3bdbb84a8755c10cb17190a Mon Sep 17 00:00:00 2001
From: Boyan Bratvanov <6027160+bratvanov@users.noreply.github.com>
Date: Tue, 21 Jan 2025 16:43:35 +0200
Subject: [PATCH 1/5] examples(multi-tenant): seed script and readme updates
---
examples/multi-tenant/README.md | 24 ++++++++-----
examples/multi-tenant/src/app/(app)/page.tsx | 6 ++--
examples/multi-tenant/src/migrations/seed.ts | 38 +++++++++-----------
3 files changed, 35 insertions(+), 33 deletions(-)
diff --git a/examples/multi-tenant/README.md b/examples/multi-tenant/README.md
index 7e497db37dd..f1719d0f959 100644
--- a/examples/multi-tenant/README.md
+++ b/examples/multi-tenant/README.md
@@ -10,11 +10,17 @@ To spin up this example locally, follow these steps:
- `npx create-payload-app --example multi-tenant`
-2. `pnpm dev`, `yarn dev` or `npm run dev` to start the server
+2. `cp .env.example .env` to copy the example environment variables
+
+3. `pnpm dev`, `yarn dev` or `npm run dev` to start the server
- Press `y` when prompted to seed the database
-3. `open http://localhost:3000` to access the home page
-4. `open http://localhost:3000/admin` to access the admin panel
- - Login with email `demo@payloadcms.com` and password `demo`
+4. `open http://localhost:3000` to access the home page
+5. `open http://localhost:3000/admin` to access the admin panel
+
+### Default users
+
+The seed script seeds 3 tenants.
+Login with email `demo@payloadcms.com` and password `demo`
## How it works
@@ -40,13 +46,13 @@ See the [Collections](https://payloadcms.com/docs/configuration/collections) doc
**Domain-based Tenant Setting**:
- This example also supports domain-based tenant selection, where tenants can be associated with a specific domain. If a tenant is associated with a domain (e.g., `gold.localhost.com:3000`), when a user logs in from that domain, they will be automatically scoped to the matching tenant. This is accomplished through an optional `afterLogin` hook that sets a `payload-tenant` cookie based on the domain.
+ This example also supports domain-based tenant selection, where tenants can be associated with a specific domain. If a tenant is associated with a domain (e.g., `gold.test:3000`), when a user logs in from that domain, they will be automatically scoped to the matching tenant. This is accomplished through an optional `afterLogin` hook that sets a `payload-tenant` cookie based on the domain.
- The seed script seeds 3 tenants, for the domain portion of the example to function properly you will need to add the following entries to your systems `/etc/hosts` file:
+For the domain portion of the example to function properly, you will need to add the following entries to your system's `/etc/hosts` file:
- - gold.localhost.com:3000
- - silver.localhost.com:3000
- - bronze.localhost.com:3000
+- gold.test:3000
+- silver.test:3000
+- bronze.test:3000
- #### Pages
diff --git a/examples/multi-tenant/src/app/(app)/page.tsx b/examples/multi-tenant/src/app/(app)/page.tsx
index c772fd5a157..2011e90eead 100644
--- a/examples/multi-tenant/src/app/(app)/page.tsx
+++ b/examples/multi-tenant/src/app/(app)/page.tsx
@@ -10,10 +10,10 @@ export default async ({ params: paramsPromise }: { params: Promise<{ slug: strin
When you visit a tenant by domain, the domain is used to determine the tenant.
For example, visiting{' '}
-
- http://gold.localhost.com:3000/tenant-domains/login
+
+ http://gold.test:3000/tenant-domains/login
{' '}
- will show the tenant with the domain "gold.localhost.com".
+ will show the tenant with the domain "gold.test".
Slugs
diff --git a/examples/multi-tenant/src/migrations/seed.ts b/examples/multi-tenant/src/migrations/seed.ts
index 52e0db3a5f3..21d4bb73c27 100644
--- a/examples/multi-tenant/src/migrations/seed.ts
+++ b/examples/multi-tenant/src/migrations/seed.ts
@@ -1,21 +1,12 @@
import type { MigrateUpArgs } from '@payloadcms/db-mongodb'
export async function up({ payload }: MigrateUpArgs): Promise {
- await payload.create({
- collection: 'users',
- data: {
- email: 'demo@payloadcms.com',
- password: 'demo',
- roles: ['super-admin'],
- },
- })
-
const tenant1 = await payload.create({
collection: 'tenants',
data: {
name: 'Tenant 1',
slug: 'gold',
- domain: 'gold.localhost.com',
+ domain: 'gold.test',
},
})
@@ -24,7 +15,7 @@ export async function up({ payload }: MigrateUpArgs): Promise {
data: {
name: 'Tenant 2',
slug: 'silver',
- domain: 'silver.localhost.com',
+ domain: 'silver.test',
},
})
@@ -33,7 +24,16 @@ export async function up({ payload }: MigrateUpArgs): Promise {
data: {
name: 'Tenant 3',
slug: 'bronze',
- domain: 'bronze.localhost.com',
+ domain: 'bronze.test',
+ },
+ })
+
+ await payload.create({
+ collection: 'users',
+ data: {
+ email: 'demo@payloadcms.com',
+ password: 'demo',
+ roles: ['super-admin'],
},
})
@@ -41,16 +41,12 @@ export async function up({ payload }: MigrateUpArgs): Promise {
collection: 'users',
data: {
email: 'tenant1@payloadcms.com',
- password: 'test',
+ password: 'demo',
tenants: [
{
roles: ['tenant-admin'],
tenant: tenant1.id,
},
- // {
- // roles: ['tenant-admin'],
- // tenant: tenant2.id,
- // },
],
username: 'tenant1',
},
@@ -60,7 +56,7 @@ export async function up({ payload }: MigrateUpArgs): Promise {
collection: 'users',
data: {
email: 'tenant2@payloadcms.com',
- password: 'test',
+ password: 'demo',
tenants: [
{
roles: ['tenant-admin'],
@@ -75,7 +71,7 @@ export async function up({ payload }: MigrateUpArgs): Promise {
collection: 'users',
data: {
email: 'tenant3@payloadcms.com',
- password: 'test',
+ password: 'demo',
tenants: [
{
roles: ['tenant-admin'],
@@ -90,7 +86,7 @@ export async function up({ payload }: MigrateUpArgs): Promise {
collection: 'users',
data: {
email: 'multi-admin@payloadcms.com',
- password: 'test',
+ password: 'demo',
tenants: [
{
roles: ['tenant-admin'],
@@ -105,7 +101,7 @@ export async function up({ payload }: MigrateUpArgs): Promise {
tenant: tenant3.id,
},
],
- username: 'tenant3',
+ username: 'multi-admin',
},
})
From faec24d0e775ddd38ac5f7babe93055155da1c67 Mon Sep 17 00:00:00 2001
From: Boyan Bratvanov <6027160+bratvanov@users.noreply.github.com>
Date: Tue, 21 Jan 2025 16:53:16 +0200
Subject: [PATCH 2/5] Grammar fixes
---
examples/multi-tenant/README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/examples/multi-tenant/README.md b/examples/multi-tenant/README.md
index f1719d0f959..00b8b16d9fe 100644
--- a/examples/multi-tenant/README.md
+++ b/examples/multi-tenant/README.md
@@ -34,7 +34,7 @@ See the [Collections](https://payloadcms.com/docs/configuration/collections) doc
- #### Users
- The `users` collection is auth-enabled and encompass both app-wide and tenant-scoped users based on the value of their `roles` and `tenants` fields. Users with the role `super-admin` can manage your entire application, while users with the _tenant role_ of `admin` have limited access to the platform and can manage only the tenant(s) they are assigned to, see [Tenants](#tenants) for more details.
+ The `users` collection is auth-enabled and encompasses both app-wide and tenant-scoped users based on the value of their `roles` and `tenants` fields. Users with the role `super-admin` can manage your entire application, while users with the _tenant role_ of `admin` have limited access to the platform and can manage only the tenant(s) they are assigned to, see [Tenants](#tenants) for more details.
For additional help with authentication, see the official [Auth Example](https://github.com/payloadcms/payload/tree/main/examples/cms#readme) or the [Authentication](https://payloadcms.com/docs/authentication/overview#authentication-overview) docs.
@@ -60,7 +60,7 @@ For the domain portion of the example to function properly, you will need to add
## Access control
-Basic role-based access control is setup to determine what users can and cannot do based on their roles, which are:
+Basic role-based access control is set up to determine what users can and cannot do based on their roles, which are:
- `super-admin`: They can access the Payload admin panel to manage your multi-tenant application. They can see all tenants and make all operations.
- `user`: They can only access the Payload admin panel if they are a tenant-admin, in which case they have a limited access to operations based on their tenant (see below).
From afc642e8606a883e42e347fa95ee0d997f8a6cda Mon Sep 17 00:00:00 2001
From: Boyan Bratvanov <6027160+bratvanov@users.noreply.github.com>
Date: Tue, 21 Jan 2025 16:57:06 +0200
Subject: [PATCH 3/5] Remove local .tgz dependency in package.json
---
examples/multi-tenant/package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/examples/multi-tenant/package.json b/examples/multi-tenant/package.json
index 4c9a5ae70ae..0f4a8a21d85 100644
--- a/examples/multi-tenant/package.json
+++ b/examples/multi-tenant/package.json
@@ -18,7 +18,7 @@
"dependencies": {
"@payloadcms/db-mongodb": "latest",
"@payloadcms/next": "latest",
- "@payloadcms/plugin-multi-tenant": "file:payloadcms-plugin-multi-tenant-3.15.1.tgz",
+ "@payloadcms/plugin-multi-tenant": "latest",
"@payloadcms/richtext-lexical": "latest",
"@payloadcms/ui": "latest",
"cross-env": "^7.0.3",
From e436ea0a636ddecb0c9ec1d5e5c35c8849a1836f Mon Sep 17 00:00:00 2001
From: Boyan Bratvanov <6027160+bratvanov@users.noreply.github.com>
Date: Tue, 21 Jan 2025 17:01:55 +0200
Subject: [PATCH 4/5] Fix hosts file entry
---
examples/multi-tenant/README.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/examples/multi-tenant/README.md b/examples/multi-tenant/README.md
index 00b8b16d9fe..5626f3600ef 100644
--- a/examples/multi-tenant/README.md
+++ b/examples/multi-tenant/README.md
@@ -50,9 +50,9 @@ See the [Collections](https://payloadcms.com/docs/configuration/collections) doc
For the domain portion of the example to function properly, you will need to add the following entries to your system's `/etc/hosts` file:
-- gold.test:3000
-- silver.test:3000
-- bronze.test:3000
+```
+127.0.0.1 gold.test silver.test bronze.test
+```
- #### Pages
From 908cc86913f062fca776cb99b1251b7838a69fe7 Mon Sep 17 00:00:00 2001
From: Boyan Bratvanov <6027160+bratvanov@users.noreply.github.com>
Date: Wed, 22 Jan 2025 13:52:03 +0200
Subject: [PATCH 5/5] Fix typo in exported const
---
.../collections/Pages/access/superAdminOrTenantAdmin.ts | 2 +-
examples/multi-tenant/src/collections/Pages/index.ts | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/examples/multi-tenant/src/collections/Pages/access/superAdminOrTenantAdmin.ts b/examples/multi-tenant/src/collections/Pages/access/superAdminOrTenantAdmin.ts
index f60af75c877..28cde64c75e 100644
--- a/examples/multi-tenant/src/collections/Pages/access/superAdminOrTenantAdmin.ts
+++ b/examples/multi-tenant/src/collections/Pages/access/superAdminOrTenantAdmin.ts
@@ -5,7 +5,7 @@ import { Access } from 'payload'
/**
* Tenant admins and super admins can will be allowed access
*/
-export const superAdminOrTeanantAdminAccess: Access = ({ req }) => {
+export const superAdminOrTenantAdminAccess: Access = ({ req }) => {
if (!req.user) {
return false
}
diff --git a/examples/multi-tenant/src/collections/Pages/index.ts b/examples/multi-tenant/src/collections/Pages/index.ts
index 0ff7d895634..3d3cc0d7b4d 100644
--- a/examples/multi-tenant/src/collections/Pages/index.ts
+++ b/examples/multi-tenant/src/collections/Pages/index.ts
@@ -1,15 +1,15 @@
import type { CollectionConfig } from 'payload'
import { ensureUniqueSlug } from './hooks/ensureUniqueSlug'
-import { superAdminOrTeanantAdminAccess } from '@/collections/Pages/access/superAdminOrTenantAdmin'
+import { superAdminOrTenantAdminAccess } from '@/collections/Pages/access/superAdminOrTenantAdmin'
export const Pages: CollectionConfig = {
slug: 'pages',
access: {
- create: superAdminOrTeanantAdminAccess,
- delete: superAdminOrTeanantAdminAccess,
+ create: superAdminOrTenantAdminAccess,
+ delete: superAdminOrTenantAdminAccess,
read: () => true,
- update: superAdminOrTeanantAdminAccess,
+ update: superAdminOrTenantAdminAccess,
},
admin: {
useAsTitle: 'title',