angelitosystems/filament-tenancy

Tenancy package for Filament - multi-database tenants + central support

Installs: 2

Dependents: 0

Suggesters: 0

Security: 0

Stars: 1

Watchers: 0

Forks: 0

Open Issues: 1

pkg:composer/angelitosystems/filament-tenancy

v1.0.4 2025-11-07 00:10 UTC

This package is auto-updated.

Last update: 2025-11-07 00:33:17 UTC


README

A comprehensive multi-tenancy package for Filament with support for multiple databases, central management, advanced logging, and performance monitoring.

Features

  • ๐Ÿš€ Easy Installation - Interactive installer with automatic setup
  • ๐Ÿ‘ฅ User Management - Create and manage tenant users with roles and permissions
  • ๐Ÿ” Roles & Permissions - Complete Spatie-like RBAC system for tenant access control
  • ๐Ÿ“ฆ Asset Sharing - Share Livewire, Filament, and custom assets from central to tenants
  • ๐Ÿ‘ฅ Admin User Creation - Interactive admin user creation during installation
  • ๐Ÿ—„๏ธ Multi-database tenancy - Complete isolation between tenants
  • ๐ŸŽ›๏ธ Central tenant management - Unified control panel for all tenants
  • โšก Automatic database creation and migration - Seamless tenant provisioning
  • ๐Ÿ”„ Tenant-aware middleware - Automatic context switching
  • ๐ŸŽจ Filament integration - Native Filament admin panel support
  • ๐Ÿ” Secure credential management - Encrypted credential storage with rotation
  • ๐Ÿ“Š Enhanced Debug Logging - Environment-aware logging with production-safe output
  • ๐Ÿ“ˆ Performance monitoring - Real-time metrics and connection monitoring
  • ๐Ÿ”Œ Connection pooling - Optimized database connection management
  • ๐Ÿ’ณ Plans & Subscriptions - Built-in plan and subscription management
  • ๐Ÿ’ณ PayPal Integration - Complete PayPal payment integration with webhooks support
  • ๐Ÿ›ก๏ธ Database compatibility check - Automatic validation of database requirements
  • ๐Ÿงน Smart error handling - Automatic retry and cleanup on connection errors
  • ๐ŸŒ APP_DOMAIN Auto-Detection - Automatic domain detection from APP_URL for subdomain tenancy
  • ๐Ÿ”ง Enhanced Tenant Creation - Interactive wizard with automatic domain configuration
  • ๐ŸŽจ Custom 404 Page - Beautiful personalized 404 page for tenant not found errors with Livewire component support
  • โš–๏ธ License-Based - Future licensing model for commercial use (currently public access)

Installation

Quick Install

The easiest way to install Filament Tenancy is using the interactive installer:

composer require angelitosystems/filament-tenancy
php artisan filament-tenancy:install

The installer will:

  • โœ… Check if Filament is installed and install it if needed
  • โœ… Verify database compatibility (MySQL/PostgreSQL required)
  • โœ… Configure database connection interactively if needed
  • โœ… Publish configuration files
  • โœ… Run migrations automatically
  • โœ… Create default plans automatically (Basic, Premium, Enterprise)
  • โœ… Register the ServiceProvider automatically
  • โœ… Register middlewares automatically in bootstrap/app.php (Laravel 11) or via ServiceProvider (Laravel 10)
  • โœ… Configure custom 404 page - Ask if you want to publish components and views for tenant not found errors

Manual Installation

If you prefer manual installation:

# Install the package
composer require angelitosystems/filament-tenancy

# Publish the configuration file
php artisan vendor:publish --tag="filament-tenancy-config"

# Publish seeders (now includes central and tenant seeders)
php artisan vendor:publish --tag="filament-tenancy-seeders"
php artisan vendor:publish --tag="filament-tenancy-tenant-seeders"

# Publish custom 404 page components and views (optional)
php artisan vendor:publish --tag="filament-tenancy-views"
php artisan vendor:publish --tag="filament-tenancy-components"

# Run the migrations
php artisan migrate

# Seed default plans (or they will be seeded automatically during installation)
php artisan db:seed --class=Database\Seeders\PlanSeeder

# Setup central database (required for landlord administration)
php artisan filament-tenancy:setup-central --create-admin

Central Database Setup

After installation, you need to set up the central database with roles and permissions for the landlord/central administration:

# Complete central database setup (recommended)
php artisan filament-tenancy:setup-central --create-admin

# Or step by step:
php artisan migrate --path="packages/filament-tenancy/database/migrations"
php artisan filament-tenancy:seed-central
php artisan filament-tenancy:create-central-admin

The central database setup includes:

  • ๐Ÿ›๏ธ Central Roles & Permissions: Separate permission system for central administration
  • ๐Ÿ‘‘ Super Admin Role: Complete access to all central features
  • ๐Ÿ›ก๏ธ Landlord Admin Role: Manage tenants, plans, and subscriptions
  • ๐ŸŽง Support Role: Read-only access for support staff
  • ๐Ÿ‘ค Central Admin User: Automatically created with Super Admin role

Central Permissions Available:

  • manage tenants - Create, edit, delete tenants
  • manage plans - Manage subscription plans
  • manage subscriptions - Handle tenant subscriptions
  • manage central users - Manage central admin users
  • manage central roles - Manage central roles and permissions
  • view central dashboard - Access central dashboard
  • manage system settings - Configure system-wide settings
  • access landlord panel - Access landlord administration panel
  • manage tenant databases - Manage tenant database operations

Requirements

  • PHP: 8.1 or higher
  • Laravel: 10.x or 11.x
  • Filament: ^4.0
  • Database: MySQL 5.7+ or PostgreSQL 10+ (SQLite is not supported for multi-database tenancy)

Configuration

The package configuration is located at config/filament-tenancy.php. Key configuration options include:

Tenant Resolution

// How tenants are resolved from requests
'resolver' => env('TENANCY_RESOLVER', 'domain'), // 'domain', 'subdomain', 'path'

// Central domains that won't be resolved as tenants
'central_domains' => [
    'app.dental.test',
    'localhost',
    env('APP_DOMAIN', 'localhost'),
],

Note: The package now supports APP_DOMAIN environment variable for subdomain-based tenancy. When creating tenants with subdomains, the package will automatically detect and suggest configuring APP_DOMAIN from your APP_URL if it's not already set.

Database Configuration

'database' => [
    'default_connection' => env('DB_CONNECTION', 'mysql'),
    'tenants_connection_template' => [
        'driver' => env('TENANT_DB_DRIVER', 'mysql'),
        'host' => env('TENANT_DB_HOST', '127.0.0.1'),
        'port' => env('TENANT_DB_PORT', '3306'),
        'username' => env('TENANT_DB_USERNAME', 'root'),
        'password' => env('TENANT_DB_PASSWORD', ''),
        // ... other database options
    ],
    'auto_create_tenant_database' => env('TENANCY_AUTO_CREATE_DB', true),
    'auto_delete_tenant_database' => env('TENANCY_AUTO_DELETE_DB', false),
],

Environment Variables

The package uses the following environment variables:

# Base domain for subdomain-based tenancy (auto-detected from APP_URL)
APP_DOMAIN=hola.test

# Tenant resolution strategy
TENANCY_RESOLVER=domain

# Database configuration (optional, uses DB_* by default)
TENANT_DB_DRIVER=mysql
TENANT_DB_HOST=127.0.0.1
TENANT_DB_PORT=3306
TENANT_DB_USERNAME=root
TENANT_DB_PASSWORD=

# Tenancy settings
TENANCY_AUTO_CREATE_DB=true
TENANCY_AUTO_DELETE_DB=false

APP_DOMAIN: This variable is automatically detected and configured when creating tenants. If your APP_URL contains a valid domain (e.g., http://hola.test), the package will ask if you want to use it as APP_DOMAIN. This is essential for subdomain-based tenancy.

Central Domains: APP_DOMAIN is automatically considered a central domain and will not resolve tenants. Additional domains can be configured in central_domains config array. Central domains typically host the admin panel for managing tenants. The middleware automatically allows access to these domains without tenant resolution.

Security: The middleware automatically:

  • Returns 404 for domains/subdomains that don't match any tenant
  • Only resolves active tenants (is_active = true and not expired)
  • Protects central domains from tenant resolution
  • Validates tenant status before allowing access

Filament Integration

'filament' => [
    'auto_register_plugins' => true,
    'landlord_panel_id' => 'admin',
    'tenant_panel_id' => 'tenant',
    'tenant_panel_path' => '/admin',
],

Usage

Creating Tenants

Using Artisan Commands (Interactive)

The easiest way to create tenants is using the interactive command:

# Interactive tenant creation
php artisan tenancy:create

The command will guide you through:

  • APP_DOMAIN Detection: Automatically detects and configures APP_DOMAIN from APP_URL if needed
  • Tenant name and slug
  • Domain or subdomain configuration (subdomains use APP_DOMAIN automatically)
  • Database name (auto-generated if not provided)
  • Plan selection: Shows plans from database with prices and billing cycles (Basic, Premium, Enterprise)
  • Active status and expiration date
  • Automatic subscription creation: Creates an active subscription when a plan is selected

APP_DOMAIN Auto-Configuration:

  • Valid Domain Detection: If APP_URL contains a valid domain (e.g., http://hola.test), the command will detect it and ask if you want to use it as APP_DOMAIN
  • Localhost/Port Detection: If APP_URL is localhost or has a port (e.g., http://localhost:8000), you'll be prompted to configure APP_DOMAIN manually
  • Automatic .env Updates: The APP_DOMAIN variable is automatically added or updated in your .env file
  • Subdomain Support: When using subdomains, the full domain is automatically constructed using APP_DOMAIN (e.g., tenant.APP_DOMAIN)

Creating Tenant Users

Create users for specific tenants with roles and permissions:

# Interactive mode
php artisan tenant:user-create

# Non-interactive mode
php artisan tenant:user-create \
    --tenant="my-tenant" \
    --name="John Doe" \
    --email="john@example.com" \
    --role="admin" \
    --permissions="manage users,view dashboard"

# List available options
php artisan tenant:user-create --list-tenants
php artisan tenant:user-create --tenant="my-tenant" --list-roles
php artisan tenant:user-create --tenant="my-tenant" --list-permissions

Features:

  • Interactive tenant selection with numbered options
  • Automatic password generation
  • Role and permission assignment
  • Email validation
  • Comprehensive user information display

Using Artisan Commands (Non-Interactive)

# Create a new tenant with all options (plan slug must exist in database)
php artisan tenancy:create "Acme Corp" \
    --subdomain="acme" \
    --database="acme_db" \
    --plan="premium" \
    --active \
    --expires="2025-12-31"

# Create with domain
php artisan tenancy:create "Acme Corp" --domain="acme.com"

# Create with subdomain
php artisan tenancy:create "Acme Corp" --subdomain="acme"

Note: When using --plan, the plan slug must exist in the tenancy_plans table. If a plan is provided, a subscription will be automatically created for the tenant.

Programmatically

use AngelitoSystems\FilamentTenancy\Facades\Tenancy;

// Create a new tenant
$tenant = Tenancy::createTenant([
    'name' => 'Acme Corporation',
    'slug' => 'acme-corp',
    'domain' => 'acme.com',
    'is_active' => true,
]);

// Switch to tenant context
Tenancy::switchToTenant($tenant);

// Run code in tenant context
Tenancy::runForTenant($tenant, function () {
    // This code runs in the tenant's database context
    User::create(['name' => 'John Doe', 'email' => 'john@acme.com']);
});

// Switch back to central context
Tenancy::switchToCentral();

Working with Models

User Model with Roles & Permissions

Add the HasRoles trait to your User model to enable role-based access control:

<?php

namespace App\Models;

use AngelitoSystems\FilamentTenancy\Concerns\HasRoles;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use HasRoles;
    
    // Your model code...
}

Using Roles and Permissions

// Assign roles
$user->assignRole('admin');
$user->syncRoles(['admin', 'editor']);

// Check roles
$user->hasRole('admin');
$user->hasAnyRole(['admin', 'editor']);

// Assign permissions
$user->givePermissionTo('manage users');
$user->syncPermissions(['manage users', 'view dashboard']);

// Check permissions
$user->hasPermissionTo('manage users');
$user->hasAnyPermission(['manage users', 'edit posts']);

Asset Sharing

Use the tenant_asset() helper to access shared assets:

<!-- In Blade templates -->
<link href="{{ tenant_asset('css/app.css') }}" rel="stylesheet">
<script src="{{ tenant_asset('livewire/livewire.js') }}" defer></script>
<link href="{{ tenant_asset('filament/assets/app.css') }}" rel="stylesheet">

The helper automatically:

  1. Checks for the asset in the tenant's storage disk
  2. Falls back to the central storage disk if not found
  3. Uses Laravel's asset() helper as final fallback

Tenant Models

For models that belong to tenants, use the BelongsToTenant trait:

use AngelitoSystems\FilamentTenancy\Concerns\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    use BelongsToTenant;
    
    // Your model code...
}

Central/Landlord Models

For models that should always use the central database, use the UsesLandlordConnection trait:

use AngelitoSystems\FilamentTenancy\Concerns\UsesLandlordConnection;
use Illuminate\Database\Eloquent\Model;

class Plan extends Model
{
    use UsesLandlordConnection;
    
    // Your model code...
}

Filament Panel Configuration

Landlord Panel

Create a landlord panel for managing tenants:

// app/Providers/Filament/AdminPanelProvider.php
use AngelitoSystems\FilamentTenancy\FilamentPlugins\TenancyLandlordPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->id('admin')
        ->path('/admin')
        ->plugin(TenancyLandlordPlugin::make())
        // ... other panel configuration
}

Tenant Panel

Create a tenant panel:

// app/Providers/Filament/TenantPanelProvider.php
use AngelitoSystems\FilamentTenancy\FilamentPlugins\TenancyTenantPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->id('tenant')
        ->path('/admin')
        ->plugin(TenancyTenantPlugin::make())
        // ... other panel configuration
}

Middleware

The package provides several middleware for tenant management:

  • InitializeTenancy:

    • Automatically resolves tenant from domain/subdomain
    • Returns custom 404 page if tenant is not found (if published, otherwise standard 404)
    • Verifies tenant is active before allowing access
    • Allows access to landlord/admin routes even with inactive tenants (configurable)
    • Registered globally by default (can be disabled in config)
  • EnsureTenantAccess:

    • Ensures a tenant is present and active
    • Returns 404 if no tenant is found
    • Returns 403 if tenant is inactive or expired
  • PreventAccessFromCentralDomains: Prevents tenant access from central domains

Custom 404 Page

The package includes a beautiful, personalized 404 page for tenant not found errors. During installation, you'll be asked if you want to publish the components and views for customization.

Publishing Components

# Publish views (Blade templates)
php artisan vendor:publish --tag="filament-tenancy-views"

# Publish Livewire component (optional, requires Livewire)
php artisan vendor:publish --tag="filament-tenancy-components"

Published Files

If you choose to publish during installation:

  • Views: resources/views/vendor/filament-tenancy/errors/tenant-not-found.blade.php
  • Livewire Component: app/Livewire/TenantNotFound.php (if Livewire is available)

Customization

Once published, you can fully customize:

  • Blade View: Edit resources/views/vendor/filament-tenancy/errors/tenant-not-found.blade.php to change the design, colors, layout, or content
  • Livewire Component: Edit app/Livewire/TenantNotFound.php to add dynamic functionality or interactivity

Automatic Registration

The installer automatically registers the custom 404 page in bootstrap/app.php (Laravel 11) for handling tenant not found errors. The page will:

  • Display a beautiful error message
  • Show request details (domain, resolver, APP_DOMAIN)
  • Provide a link back to the homepage
  • Work without Livewire if not published

Without Publishing

If you choose not to publish, the package will use its internal views and components. The 404 page will still work, but you won't be able to customize it.

Database Migrations

Running Tenant Migrations

# Run migrations for all tenants
php artisan tenant:migrate

# Run migrations for a specific tenant
php artisan tenant:migrate --tenant=1

# Run fresh migrations with seeding
php artisan tenant:migrate --fresh --seed

Creating Tenant-Specific Migrations

Place tenant-specific migrations in database/migrations/tenant/:

php artisan make:migration create_tenant_users_table --path=database/migrations/tenant

Events

The package dispatches several events:

  • TenantCreated: When a new tenant is created
  • TenantDeleted: When a tenant is deleted
  • TenantSwitched: When switching between tenants
use AngelitoSystems\FilamentTenancy\Events\TenantCreated;

Event::listen(TenantCreated::class, function (TenantCreated $event) {
    // Handle tenant creation
    $tenant = $event->tenant;
});

Advanced Usage

Custom Tenant Resolution

You can extend the tenant resolver for custom logic:

use AngelitoSystems\FilamentTenancy\Support\TenantResolver;

class CustomTenantResolver extends TenantResolver
{
    public function resolve(Request $request): ?Tenant
    {
        // Your custom resolution logic
        return parent::resolve($request);
    }
}

// Register in a service provider
$this->app->bind(TenantResolver::class, CustomTenantResolver::class);

Custom Database Configuration

Override database configuration per tenant:

$tenant = Tenant::find(1);
$tenant->update([
    'database_host' => 'custom-host.com',
    'database_name' => 'custom_database',
    'database_username' => 'custom_user',
    'database_password' => 'custom_password',
]);

Tenant Data Storage

Store additional tenant data using the JSON data column:

$tenant->data = [
    'settings' => [
        'theme' => 'dark',
        'timezone' => 'UTC',
    ],
    'features' => ['feature1', 'feature2'],
];
$tenant->save();

// Access data
$theme = $tenant->data['settings']['theme'] ?? 'light';

APP_DOMAIN Configuration

The APP_DOMAIN environment variable is used for subdomain-based tenancy. It's automatically detected and configured during tenant creation:

Automatic Detection:

  • When running php artisan tenancy:create, the package checks your APP_URL
  • If APP_URL contains a valid domain (e.g., http://hola.test), it suggests using it as APP_DOMAIN
  • If APP_URL is localhost or has a port, you'll be prompted to configure APP_DOMAIN manually

Manual Configuration:

APP_DOMAIN=hola.test

Usage:

  • When creating tenants with subdomains, the full domain is automatically constructed: {subdomain}.{APP_DOMAIN}
  • For example, if APP_DOMAIN=hola.test and subdomain is acme, the full domain becomes acme.hola.test
  • The Tenant::getFullDomain() method uses APP_DOMAIN when available, falling back to central_domains configuration

Example:

// With APP_DOMAIN=hola.test configured
$tenant = Tenant::create([
    'name' => 'Acme Corp',
    'subdomain' => 'acme',
]);

echo $tenant->getFullDomain(); // Output: acme.hola.test
echo $tenant->getUrl(); // Output: http://acme.hola.test

Testing

Run the package tests:

composer test

Debug Logging

The package includes enhanced debug logging that is environment-aware:

DebugHelper Class

The DebugHelper class provides environment-aware logging:

use AngelitoSystems\FilamentTenancy\Support\DebugHelper;

// Only logs when APP_ENV=local AND APP_DEBUG=true
DebugHelper::info('Tenant created', ['tenant_id' => $tenant->id]);
DebugHelper::debug('Connection details', $connectionData);
DebugHelper::warning('Potential issue detected', $context);

// Always logs regardless of environment
DebugHelper::error('Critical error occurred', $errorData);
DebugHelper::critical('System failure', $criticalData);

Environment Configuration

# Enable debug logging
APP_ENV=local
APP_DEBUG=true

# Production settings (logs only errors/criticals)
APP_ENV=production
APP_DEBUG=false

Log Behavior

  • Development (APP_ENV=local, APP_DEBUG=true): All logs are visible
  • Production (APP_ENV=production OR APP_DEBUG=false): Only errors and criticals are logged
  • Debug/Info/Warning: Only shown in development environment
  • Error/Critical: Always logged regardless of environment

Security

This package includes several security features:

  • Cross-tenant isolation: Prevents data leakage between tenants
  • Domain validation: Ensures tenants can only be accessed from their domains
  • Database separation: Each tenant has its own database
  • Middleware protection: Automatic tenant context validation
  • Automatic 404 for invalid domains: Domains/subdomains that don't match any tenant automatically return a beautiful custom 404 page
  • Customizable 404 page: Personalized error page with request details and optional Livewire component support
  • Active tenant verification: Only active tenants can be accessed (checks is_active and expires_at)
  • Central domain protection: Central domains are protected from tenant resolution

Contributing

Please see CONTRIBUTING.md for details.

License

This package is currently available for public use, but will transition to a license-based distribution model in the future.

โš–๏ธ License Terms & Usage Rights

Current Status: Public Access (Temporary)

  • โœ… You CAN: Use this software in your projects (personal, commercial, educational)
  • โœ… You CAN: Install and use the package via Composer
  • โœ… You CAN: Customize configurations and extend functionality
  • โŒ You CANNOT: Create replicas, forks, or copies of this package
  • โŒ You CANNOT: Redistribute this package as your own
  • โŒ You CANNOT: Remove or modify license headers
  • โŒ You CANNOT: Use this package to create competing multi-tenancy solutions

๐Ÿ”ฎ Future Licensing Model

Important: This package will transition to a paid license model in the future. Users who adopt the package now will receive preferential treatment when licensing becomes available.

  • License-based distribution (coming soon)
  • Commercial use will require a valid license
  • Enterprise features will be license-gated
  • Early adopters will have migration paths to licensed versions

โš ๏ธ What Happens If You Violate the License?

Legal Consequences:

  • You may be subject to legal action for copyright infringement
  • Distribution of unauthorized copies may result in cease and desist orders
  • Commercial use without proper licensing will be pursued legally
  • Creation of replicas or competing solutions will be treated as intellectual property theft

Technical Consequences:

  • Package updates may include license validation
  • Unauthorized usage may be detected and blocked
  • Support will not be provided to unlicensed users
  • Access to future versions may be restricted

๐Ÿ“„ License Compliance

To ensure compliance:

  • โœ… Use the package via official Composer repository only
  • โœ… Do not copy, fork, or replicate the source code
  • โœ… Respect intellectual property rights
  • โœ… Contact us for licensing inquiries: angelitosystems@gmail.com

Current License: MIT License (subject to above restrictions)

For complete license terms, please read the LICENSE file.

Available Commands

Central Database Commands

# Complete central database setup with admin creation
php artisan filament-tenancy:setup-central --create-admin

# Seed central database with roles and permissions
php artisan filament-tenancy:seed-central

# Create central admin user with Super Admin role
php artisan filament-tenancy:create-central-admin

Tenant Management Commands

# Interactive tenant creation
php artisan tenancy:create

# List all tenants
php artisan tenancy:list

# Delete a tenant
php artisan tenancy:delete

# Create tenant user with roles
php artisan tenant:user-create

Migration Commands

# Run migrations for specific tenant
php artisan tenant:migrate

# Rollback tenant migrations
php artisan tenant:rollback

# Fresh tenant database
php artisan tenant:fresh

Monitoring Commands

# Monitor tenant connections
php artisan filament-tenancy:monitor-connections

Documentation

Additional Guides

  • PayPal Configuration Guide - Complete guide for setting up PayPal payment integration, including webhooks, credentials, and troubleshooting.

Credits

Support

For support, please open an issue on GitHub or contact us at angelitosystems@gmail.com.