diff --git a/examples/multi-tenant/README.md b/examples/multi-tenant/README.md index 7e497db37dd..5626f3600ef 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 @@ -28,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. @@ -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 +``` +127.0.0.1 gold.test silver.test bronze.test +``` - #### Pages @@ -54,7 +60,7 @@ See the [Collections](https://payloadcms.com/docs/configuration/collections) doc ## 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). 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", 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/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', 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', }, })