romegadigital/multitenancy

Adds domain based multitenancy to Laravel applications.

4.0.0 2023-05-31 23:34 UTC

This package is auto-updated.

Last update: 2024-03-30 00:17:10 UTC


README

Total Downloads

This package provides a convenient way to add multitenancy to your Laravel application. It manages models and relationships for Tenants, identifies incoming traffic by subdomain, and associates it with a corresponding tenant. Users not linked with a specific subdomain or without a matching tenant in the Tenant table are presented with a 403 error.

Note: Any resources saved while accessing a scoped subdomain will automatically be saved against the current tenant, based on subdomain.

Note: The admin subdomain is reserved for the package to remove all scopes from users with a Super Administrator role.

Table of Contents

Installation

1. Use composer to install the package:

composer require romegadigital/multitenancy

In Laravel 5.5 and newer, the service provider gets registered automatically. For older versions, add the service provider in the config/app.php file:

'providers' => [
    // ...
    RomegaDigital\Multitenancy\MultitenancyServiceProvider::class,
];

2. Publish the config file

php artisan vendor:publish --provider="RomegaDigital\Multitenancy\MultitenancyServiceProvider" --tag="config"

3. Run the setup

php artisan multitenancy:install

This command will:

  • Publish and migrate required migrations
  • Add a Super Administrator role and access admin permission
  • Create an admin Tenant model

4. Update your .env file

The package needs to know your base URL so it can determine what constitutes a tenant by the subdomain.

Add this to your .env file: MULTITENANCY_BASE_URL=

5. Update your User model

Apply the RomegaDigital\Multitenancy\Traits\HasTenants and Spatie\Permission\Traits\HasRoles traits to your User model(s):

use Spatie\Permission\Traits\HasRoles;
use RomegaDigital\Multitenancy\Traits\HasTenants;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use HasTenants, HasRoles;
    // ...
}

Usage

Tenants require a name to identify the tenant and a subdomain that is associated with that user. Example:

tenant1.example.com

tenant2.example.com

Note: You define the base url example.com in the config/multitenancy.php file.

These Tenants could be added to the database like so:

Tenant::create([
    'name'    => 'An Identifying Name',
    'domain'  => 'tenant1'
]);
Tenant::create([
    'name'    => 'A Second Customer',
    'domain'  => 'tenant2'
]);

You can then attach user models to the Tenant:

$user = User::first();
Tenant::first()->users()->save($user);

Create Tenants, associate them with Users, and define access rules using provided Middleware. Check the detailed usage guide for examples.

Detailed Usage Guide

1. Models and relationships:

Use Eloquent to access User's tenants (User::tenants()->get()) and Tenant's users (Tenant::users()->get()). Add new tenants and their associated users to the database.

2. Middleware:

Add TenantMiddleware and GuestTenantMiddleware to your app/Http/Kernel.php file and apply them to routes.

Tenant Middleware

protected $middlewareAliases = [
    // ...
    'tenant.auth' => \RomegaDigital\Multitenancy\Middleware\TenantMiddleware::class,
];

Then you can bring multitenancy to your routes using middleware rules:

Route::group(['middleware' => ['tenant.auth']], function () {
    // ...
});

Guest Tenant Middleware

This package comes with GuestTenantMiddleware middleware which applies the tenant scope to all models and can be used for allowing guest users to access Tenant related pages. You can add it inside your app/Http/Kernel.php file.

protected $middlewareAliases = [
    // ...
    'tenant.guest' => \RomegaDigital\Multitenancy\Middleware\GuestTenantMiddleware::class,
];

Then you can bring multitenancy to your routes using middleware rules:

Route::group(['middleware' => ['tenant.guest']], function () {
    // ...
});

3. Tenant Assignment for Models:

Make models tenant-aware by adding a trait and migration. Then apply tenant scoping automatically. This allows users to access tenant1.example.com and return the data from tenant1 only.

For example, say you wanted Tenants to manage their own Product. In your Product model, add the BelongsToTenant trait. Then run the provided console command to add the necessary relationship column to your existing products table.

use Illuminate\Database\Eloquent\Model;
use RomegaDigital\Multitenancy\Traits\BelongsToTenant;

class Product extends Model
{
    use BelongsToTenant;

    // ...
}

Add tenancy to a model's table: php artisan multitenancy:migration products

4. Access to Current Tenant:

Use app('multitenancy')->currentTenant() to get the current tenant model.

5. Admin Domain Access:

Assign the Super Administrator role to a user to enable access to the admin subdomain. Manually create an admin portal if necessary.

6. Auto-assign Users to Tenants:

Enable ignore_tenant_on_user_creation setting to automatically assign users to the Tenant subdomain on which they are created.

7. Give a user Super Administration rights:

In order to access the admin.example.com subdomain, a user will need the access admin permission. This package relies on Spatie's Laravel Permission package and is automatically included as a dependency when installing this package. We also provide a Super Administrator role on migration that has the relevant permission already associated with it. Assign the Super Administrator role to an admin user to provide the access they need. See the Laravel Permission documentation for more on adding users to the appropriate role and permission.

The Super Administrator is a special user role with privileged access. Users with this role can access all model resources, navigate across different tenants' domains, and gain entry to the admin subdomain where all tenant scopes are disabled.

When a user is granted the Super Administrator role, they can freely access the admin subdomain. In this context, tenant scopes aren't applied. This privilege allows Super Administrators to manage data across all instances without requiring specific access to each individual tenant's account.

Give a user Super Administration rights: php artisan multitenancy:super-admin admin@example.com

Managing with Nova

You can manage the resources of this package in Nova with the MultitenancyNovaTool.

Testing Package

Run tests with the command:

php vendor/bin/testbench package:test