Skip to content

Commit ae0736b

Browse files
authored
examples: multi-tenant seed script, readme and other improvements (#10702)
1 parent 1a68fa1 commit ae0736b

File tree

5 files changed

+42
-40
lines changed

5 files changed

+42
-40
lines changed

examples/multi-tenant/README.md

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,17 @@ To spin up this example locally, follow these steps:
1010

1111
- `npx create-payload-app --example multi-tenant`
1212

13-
2. `pnpm dev`, `yarn dev` or `npm run dev` to start the server
13+
2. `cp .env.example .env` to copy the example environment variables
14+
15+
3. `pnpm dev`, `yarn dev` or `npm run dev` to start the server
1416
- Press `y` when prompted to seed the database
15-
3. `open http://localhost:3000` to access the home page
16-
4. `open http://localhost:3000/admin` to access the admin panel
17-
- Login with email `demo@payloadcms.com` and password `demo`
17+
4. `open http://localhost:3000` to access the home page
18+
5. `open http://localhost:3000/admin` to access the admin panel
19+
20+
### Default users
21+
22+
The seed script seeds 3 tenants.
23+
Login with email `demo@payloadcms.com` and password `demo`
1824

1925
## How it works
2026

@@ -28,7 +34,7 @@ See the [Collections](https://payloadcms.com/docs/configuration/collections) doc
2834

2935
- #### Users
3036

31-
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.
37+
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.
3238

3339
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.
3440

@@ -40,21 +46,21 @@ See the [Collections](https://payloadcms.com/docs/configuration/collections) doc
4046

4147
**Domain-based Tenant Setting**:
4248

43-
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.
49+
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.
4450

45-
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:
51+
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:
4652

47-
- gold.localhost.com:3000
48-
- silver.localhost.com:3000
49-
- bronze.localhost.com:3000
53+
```
54+
127.0.0.1 gold.test silver.test bronze.test
55+
```
5056

5157
- #### Pages
5258

5359
Each page is assigned a `tenant`, which is used to control access and scope API requests. Only users with the `super-admin` role can create pages, and pages are assigned to specific tenants. Other users can view only the pages assigned to the tenant they are associated with.
5460

5561
## Access control
5662

57-
Basic role-based access control is setup to determine what users can and cannot do based on their roles, which are:
63+
Basic role-based access control is set up to determine what users can and cannot do based on their roles, which are:
5864

5965
- `super-admin`: They can access the Payload admin panel to manage your multi-tenant application. They can see all tenants and make all operations.
6066
- `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).

examples/multi-tenant/src/app/(app)/page.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ export default async ({ params: paramsPromise }: { params: Promise<{ slug: strin
1010
<p>When you visit a tenant by domain, the domain is used to determine the tenant.</p>
1111
<p>
1212
For example, visiting{' '}
13-
<a href="http://gold.localhost.com:3000/tenant-domains/login">
14-
http://gold.localhost.com:3000/tenant-domains/login
13+
<a href="http://gold.test:3000/tenant-domains/login">
14+
http://gold.test:3000/tenant-domains/login
1515
</a>{' '}
16-
will show the tenant with the domain "gold.localhost.com".
16+
will show the tenant with the domain "gold.test".
1717
</p>
1818

1919
<h2>Slugs</h2>

examples/multi-tenant/src/collections/Pages/access/superAdminOrTenantAdmin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Access } from 'payload'
55
/**
66
* Tenant admins and super admins can will be allowed access
77
*/
8-
export const superAdminOrTeanantAdminAccess: Access = ({ req }) => {
8+
export const superAdminOrTenantAdminAccess: Access = ({ req }) => {
99
if (!req.user) {
1010
return false
1111
}

examples/multi-tenant/src/collections/Pages/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import type { CollectionConfig } from 'payload'
22

33
import { ensureUniqueSlug } from './hooks/ensureUniqueSlug'
4-
import { superAdminOrTeanantAdminAccess } from '@/collections/Pages/access/superAdminOrTenantAdmin'
4+
import { superAdminOrTenantAdminAccess } from '@/collections/Pages/access/superAdminOrTenantAdmin'
55

66
export const Pages: CollectionConfig = {
77
slug: 'pages',
88
access: {
9-
create: superAdminOrTeanantAdminAccess,
10-
delete: superAdminOrTeanantAdminAccess,
9+
create: superAdminOrTenantAdminAccess,
10+
delete: superAdminOrTenantAdminAccess,
1111
read: () => true,
12-
update: superAdminOrTeanantAdminAccess,
12+
update: superAdminOrTenantAdminAccess,
1313
},
1414
admin: {
1515
useAsTitle: 'title',

examples/multi-tenant/src/migrations/seed.ts

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,12 @@
11
import type { MigrateUpArgs } from '@payloadcms/db-mongodb'
22

33
export async function up({ payload }: MigrateUpArgs): Promise<void> {
4-
await payload.create({
5-
collection: 'users',
6-
data: {
7-
email: 'demo@payloadcms.com',
8-
password: 'demo',
9-
roles: ['super-admin'],
10-
},
11-
})
12-
134
const tenant1 = await payload.create({
145
collection: 'tenants',
156
data: {
167
name: 'Tenant 1',
178
slug: 'gold',
18-
domain: 'gold.localhost.com',
9+
domain: 'gold.test',
1910
},
2011
})
2112

@@ -24,7 +15,7 @@ export async function up({ payload }: MigrateUpArgs): Promise<void> {
2415
data: {
2516
name: 'Tenant 2',
2617
slug: 'silver',
27-
domain: 'silver.localhost.com',
18+
domain: 'silver.test',
2819
},
2920
})
3021

@@ -33,24 +24,29 @@ export async function up({ payload }: MigrateUpArgs): Promise<void> {
3324
data: {
3425
name: 'Tenant 3',
3526
slug: 'bronze',
36-
domain: 'bronze.localhost.com',
27+
domain: 'bronze.test',
28+
},
29+
})
30+
31+
await payload.create({
32+
collection: 'users',
33+
data: {
34+
email: 'demo@payloadcms.com',
35+
password: 'demo',
36+
roles: ['super-admin'],
3737
},
3838
})
3939

4040
await payload.create({
4141
collection: 'users',
4242
data: {
4343
email: 'tenant1@payloadcms.com',
44-
password: 'test',
44+
password: 'demo',
4545
tenants: [
4646
{
4747
roles: ['tenant-admin'],
4848
tenant: tenant1.id,
4949
},
50-
// {
51-
// roles: ['tenant-admin'],
52-
// tenant: tenant2.id,
53-
// },
5450
],
5551
username: 'tenant1',
5652
},
@@ -60,7 +56,7 @@ export async function up({ payload }: MigrateUpArgs): Promise<void> {
6056
collection: 'users',
6157
data: {
6258
email: 'tenant2@payloadcms.com',
63-
password: 'test',
59+
password: 'demo',
6460
tenants: [
6561
{
6662
roles: ['tenant-admin'],
@@ -75,7 +71,7 @@ export async function up({ payload }: MigrateUpArgs): Promise<void> {
7571
collection: 'users',
7672
data: {
7773
email: 'tenant3@payloadcms.com',
78-
password: 'test',
74+
password: 'demo',
7975
tenants: [
8076
{
8177
roles: ['tenant-admin'],
@@ -90,7 +86,7 @@ export async function up({ payload }: MigrateUpArgs): Promise<void> {
9086
collection: 'users',
9187
data: {
9288
email: 'multi-admin@payloadcms.com',
93-
password: 'test',
89+
password: 'demo',
9490
tenants: [
9591
{
9692
roles: ['tenant-admin'],
@@ -105,7 +101,7 @@ export async function up({ payload }: MigrateUpArgs): Promise<void> {
105101
tenant: tenant3.id,
106102
},
107103
],
108-
username: 'tenant3',
104+
username: 'multi-admin',
109105
},
110106
})
111107

0 commit comments

Comments
 (0)