From dd0f03f74274a96b0723fd5c1c65a78e66a8cf6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20=C5=A0tancl?= Date: Thu, 10 Nov 2022 16:03:13 +0100 Subject: [PATCH] Fix #998, centralize config used by BelongsToTenant and HasDomains --- assets/config.php | 33 ++++++++++++------- src/Database/Concerns/BelongsToTenant.php | 4 +-- src/Database/Concerns/HasDomains.php | 6 ++-- src/Database/Models/Domain.php | 2 +- src/Resolvers/DomainTenantResolver.php | 2 +- src/Tenancy.php | 2 +- src/TenancyServiceProvider.php | 6 ++-- ...edDomainAndSubdomainIdentificationTest.php | 2 +- tests/DeleteDomainsJobTest.php | 4 +-- tests/DomainTest.php | 2 +- tests/SingleDatabaseTenancyTest.php | 4 +-- tests/SubdomainTest.php | 2 +- tests/TenantModelTest.php | 2 +- tests/TestCase.php | 2 +- 14 files changed, 41 insertions(+), 32 deletions(-) diff --git a/assets/config.php b/assets/config.php index cfde54ac..ce276f3d 100644 --- a/assets/config.php +++ b/assets/config.php @@ -6,10 +6,29 @@ use Stancl\Tenancy\Middleware; use Stancl\Tenancy\Resolvers; return [ - 'tenant_model' => Stancl\Tenancy\Database\Models\Tenant::class, - 'domain_model' => Stancl\Tenancy\Database\Models\Domain::class, + /** + * Configuration for the models used by Tenancy. + */ + 'models' => [ + 'tenant' => Stancl\Tenancy\Database\Models\Tenant::class, + 'domain' => Stancl\Tenancy\Database\Models\Domain::class, - 'id_generator' => Stancl\Tenancy\UUIDGenerator::class, + /** + * Name of the column used to for ->tenant() relationships. + * + * This is used by the HasDomains trait, and models that use the BelongsToTenant trait (used in single-database tenancy). + */ + 'tenant_key_column' => 'tenant_id', + + /** + * Used for generating tenant IDs. + * + * - Feel free to override this with a custom class that implements the UniqueIdentifierGenerator interface. + * - To use autoincrement IDs, set this to null and update the `tenants` table migration to use an autoincrement column. + * SECURITY NOTE: Keep in mind that autoincrement IDs come with *potential* enumeration issues (such as tenant storage URLs). + */ + 'id_generator' => Stancl\Tenancy\UUIDGenerator::class, + ], /** * The list of domains hosting your central app. @@ -293,12 +312,4 @@ return [ '--class' => 'Database\Seeders\DatabaseSeeder', // root seeder class // '--force' => true, ], - - /** - * Single-database tenancy config. - */ - 'single_db' => [ - /** The name of the column used by models with the BelongsToTenant trait. */ - 'tenant_id_column' => 'tenant_id', - ], ]; diff --git a/src/Database/Concerns/BelongsToTenant.php b/src/Database/Concerns/BelongsToTenant.php index 07048a1f..1be3c4cf 100644 --- a/src/Database/Concerns/BelongsToTenant.php +++ b/src/Database/Concerns/BelongsToTenant.php @@ -14,12 +14,12 @@ trait BelongsToTenant { public function tenant() { - return $this->belongsTo(config('tenancy.tenant_model'), static::tenantIdColumn()); + return $this->belongsTo(config('tenancy.models.tenant'), static::tenantIdColumn()); } public static function tenantIdColumn(): string { - return config('tenancy.single_db.tenant_id_column'); + return config('tenancy.models.tenant_key_column'); } public static function bootBelongsToTenant(): void diff --git a/src/Database/Concerns/HasDomains.php b/src/Database/Concerns/HasDomains.php index bd512e23..aa1e49d0 100644 --- a/src/Database/Concerns/HasDomains.php +++ b/src/Database/Concerns/HasDomains.php @@ -2,8 +2,6 @@ declare(strict_types=1); -// todo not sure if this should be in Database\ - namespace Stancl\Tenancy\Database\Concerns; use Stancl\Tenancy\Contracts\Domain; @@ -17,12 +15,12 @@ trait HasDomains { public function domains() { - return $this->hasMany(config('tenancy.domain_model'), 'tenant_id'); + return $this->hasMany(config('tenancy.models.domain'), 'tenant_id'); } public function createDomain($data): Domain { - $class = config('tenancy.domain_model'); + $class = config('tenancy.models.domain'); if (! is_array($data)) { $data = ['domain' => $data]; diff --git a/src/Database/Models/Domain.php b/src/Database/Models/Domain.php index 16695711..e5c49bcf 100644 --- a/src/Database/Models/Domain.php +++ b/src/Database/Models/Domain.php @@ -28,7 +28,7 @@ class Domain extends Model implements Contracts\Domain public function tenant(): BelongsTo { - return $this->belongsTo(config('tenancy.tenant_model')); + return $this->belongsTo(config('tenancy.models.tenant')); } protected $dispatchesEvents = [ diff --git a/src/Resolvers/DomainTenantResolver.php b/src/Resolvers/DomainTenantResolver.php index cf88f579..2163febe 100644 --- a/src/Resolvers/DomainTenantResolver.php +++ b/src/Resolvers/DomainTenantResolver.php @@ -18,7 +18,7 @@ class DomainTenantResolver extends Contracts\CachedTenantResolver { $domain = $args[0]; - $tenant = config('tenancy.tenant_model')::query() + $tenant = config('tenancy.models.tenant')::query() ->whereHas('domains', fn (Builder $query) => $query->where('domain', $domain)) ->with('domains') ->first(); diff --git a/src/Tenancy.php b/src/Tenancy.php index 5b30e3e0..8788ec4c 100644 --- a/src/Tenancy.php +++ b/src/Tenancy.php @@ -97,7 +97,7 @@ class Tenancy public static function model(): Tenant&Model { - $class = config('tenancy.tenant_model'); + $class = config('tenancy.models.tenant'); /** @var Tenant&Model $model */ $model = new $class; diff --git a/src/TenancyServiceProvider.php b/src/TenancyServiceProvider.php index 01770cda..ded96f35 100644 --- a/src/TenancyServiceProvider.php +++ b/src/TenancyServiceProvider.php @@ -54,9 +54,9 @@ class TenancyServiceProvider extends ServiceProvider $this->app->singleton($bootstrapper); } - // Bind the class in the tenancy.id_generator config to the UniqueIdentifierGenerator abstract. - if (! is_null($this->app['config']['tenancy.id_generator'])) { - $this->app->bind(Contracts\UniqueIdentifierGenerator::class, $this->app['config']['tenancy.id_generator']); + // Bind the class in the tenancy.models.id_generator config to the UniqueIdentifierGenerator abstract. + if (! is_null($this->app['config']['tenancy.models.id_generator'])) { + $this->app->bind(Contracts\UniqueIdentifierGenerator::class, $this->app['config']['tenancy.models.id_generator']); } $this->app->singleton(Commands\Migrate::class, function ($app) { diff --git a/tests/CombinedDomainAndSubdomainIdentificationTest.php b/tests/CombinedDomainAndSubdomainIdentificationTest.php index 4e3c190b..8d613875 100644 --- a/tests/CombinedDomainAndSubdomainIdentificationTest.php +++ b/tests/CombinedDomainAndSubdomainIdentificationTest.php @@ -16,7 +16,7 @@ beforeEach(function () { }); }); - config(['tenancy.tenant_model' => CombinedTenant::class]); + config(['tenancy.models.tenant' => CombinedTenant::class]); }); test('tenant can be identified by subdomain', function () { diff --git a/tests/DeleteDomainsJobTest.php b/tests/DeleteDomainsJobTest.php index bdee14dd..bd825b71 100644 --- a/tests/DeleteDomainsJobTest.php +++ b/tests/DeleteDomainsJobTest.php @@ -6,7 +6,7 @@ use Stancl\Tenancy\Database\Concerns\HasDomains; use Stancl\Tenancy\Jobs\DeleteDomains; beforeEach(function () { - config(['tenancy.tenant_model' => DatabaseAndDomainTenant::class]); + config(['tenancy.models.tenant' => DatabaseAndDomainTenant::class]); }); test('job delete domains successfully', function (){ @@ -29,4 +29,4 @@ test('job delete domains successfully', function (){ class DatabaseAndDomainTenant extends \Stancl\Tenancy\Tests\Etc\Tenant { use HasDomains; -} \ No newline at end of file +} diff --git a/tests/DomainTest.php b/tests/DomainTest.php index 6995da24..2fc04b76 100644 --- a/tests/DomainTest.php +++ b/tests/DomainTest.php @@ -21,7 +21,7 @@ beforeEach(function () { }); }); - config(['tenancy.tenant_model' => DomainTenant::class]); + config(['tenancy.models.tenant' => DomainTenant::class]); }); test('tenant can be identified using hostname', function () { diff --git a/tests/SingleDatabaseTenancyTest.php b/tests/SingleDatabaseTenancyTest.php index ec0a0edf..d9f10fc0 100644 --- a/tests/SingleDatabaseTenancyTest.php +++ b/tests/SingleDatabaseTenancyTest.php @@ -31,7 +31,7 @@ beforeEach(function () { $table->foreign('post_id')->references('id')->on('posts')->onUpdate('cascade')->onDelete('cascade'); }); - config(['tenancy.tenant_model' => Tenant::class]); + config(['tenancy.models.tenant' => Tenant::class]); }); test('primary models are scoped to the current tenant', function () { @@ -142,7 +142,7 @@ test('tenant id is not auto added when creating primary resources in central con }); test('tenant id column name can be customized', function () { - config(['tenancy.single_db.tenant_id_column' => 'team_id']); + config(['tenancy.models.tenant_key_column' => 'team_id']); Schema::drop('comments'); Schema::drop('posts'); diff --git a/tests/SubdomainTest.php b/tests/SubdomainTest.php index 0ff52bc0..365ecc47 100644 --- a/tests/SubdomainTest.php +++ b/tests/SubdomainTest.php @@ -20,7 +20,7 @@ beforeEach(function () { }); }); - config(['tenancy.tenant_model' => SubdomainTenant::class]); + config(['tenancy.models.tenant' => SubdomainTenant::class]); }); test('tenant can be identified by subdomain', function () { diff --git a/tests/TenantModelTest.php b/tests/TenantModelTest.php index fb62260c..1c5a7700 100644 --- a/tests/TenantModelTest.php +++ b/tests/TenantModelTest.php @@ -43,7 +43,7 @@ test('current tenant can be resolved from service container using typehint', fun }); test('id is generated when no id is supplied', function () { - config(['tenancy.id_generator' => UUIDGenerator::class]); + config(['tenancy.models.id_generator' => UUIDGenerator::class]); $this->mock(UUIDGenerator::class, function ($mock) { return $mock->shouldReceive('generate')->once(); diff --git a/tests/TestCase.php b/tests/TestCase.php index 1c0ceb83..7b9deea0 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -109,7 +109,7 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase 'central' => true, ], 'tenancy.seeder_parameters' => [], - 'tenancy.tenant_model' => Tenant::class, // Use test tenant w/ DBs & domains + 'tenancy.models.tenant' => Tenant::class, // Use test tenant w/ DBs & domains ]); $app->singleton(RedisTenancyBootstrapper::class); // todo (Samuel) use proper approach eg config for singleton registration