mirror of
https://github.com/archtechx/tenancy.git
synced 2025-12-12 10:54:04 +00:00
Fix #998, centralize config used by BelongsToTenant and HasDomains
This commit is contained in:
parent
942d79cbd7
commit
dd0f03f742
14 changed files with 41 additions and 32 deletions
|
|
@ -6,10 +6,29 @@ use Stancl\Tenancy\Middleware;
|
||||||
use Stancl\Tenancy\Resolvers;
|
use Stancl\Tenancy\Resolvers;
|
||||||
|
|
||||||
return [
|
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.
|
* The list of domains hosting your central app.
|
||||||
|
|
@ -293,12 +312,4 @@ return [
|
||||||
'--class' => 'Database\Seeders\DatabaseSeeder', // root seeder class
|
'--class' => 'Database\Seeders\DatabaseSeeder', // root seeder class
|
||||||
// '--force' => true,
|
// '--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',
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,12 @@ trait BelongsToTenant
|
||||||
{
|
{
|
||||||
public function tenant()
|
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
|
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
|
public static function bootBelongsToTenant(): void
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
// todo not sure if this should be in Database\
|
|
||||||
|
|
||||||
namespace Stancl\Tenancy\Database\Concerns;
|
namespace Stancl\Tenancy\Database\Concerns;
|
||||||
|
|
||||||
use Stancl\Tenancy\Contracts\Domain;
|
use Stancl\Tenancy\Contracts\Domain;
|
||||||
|
|
@ -17,12 +15,12 @@ trait HasDomains
|
||||||
{
|
{
|
||||||
public function domains()
|
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
|
public function createDomain($data): Domain
|
||||||
{
|
{
|
||||||
$class = config('tenancy.domain_model');
|
$class = config('tenancy.models.domain');
|
||||||
|
|
||||||
if (! is_array($data)) {
|
if (! is_array($data)) {
|
||||||
$data = ['domain' => $data];
|
$data = ['domain' => $data];
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class Domain extends Model implements Contracts\Domain
|
||||||
|
|
||||||
public function tenant(): BelongsTo
|
public function tenant(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(config('tenancy.tenant_model'));
|
return $this->belongsTo(config('tenancy.models.tenant'));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected $dispatchesEvents = [
|
protected $dispatchesEvents = [
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ class DomainTenantResolver extends Contracts\CachedTenantResolver
|
||||||
{
|
{
|
||||||
$domain = $args[0];
|
$domain = $args[0];
|
||||||
|
|
||||||
$tenant = config('tenancy.tenant_model')::query()
|
$tenant = config('tenancy.models.tenant')::query()
|
||||||
->whereHas('domains', fn (Builder $query) => $query->where('domain', $domain))
|
->whereHas('domains', fn (Builder $query) => $query->where('domain', $domain))
|
||||||
->with('domains')
|
->with('domains')
|
||||||
->first();
|
->first();
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ class Tenancy
|
||||||
|
|
||||||
public static function model(): Tenant&Model
|
public static function model(): Tenant&Model
|
||||||
{
|
{
|
||||||
$class = config('tenancy.tenant_model');
|
$class = config('tenancy.models.tenant');
|
||||||
|
|
||||||
/** @var Tenant&Model $model */
|
/** @var Tenant&Model $model */
|
||||||
$model = new $class;
|
$model = new $class;
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,9 @@ class TenancyServiceProvider extends ServiceProvider
|
||||||
$this->app->singleton($bootstrapper);
|
$this->app->singleton($bootstrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind the class in the tenancy.id_generator config to the UniqueIdentifierGenerator abstract.
|
// Bind the class in the tenancy.models.id_generator config to the UniqueIdentifierGenerator abstract.
|
||||||
if (! is_null($this->app['config']['tenancy.id_generator'])) {
|
if (! is_null($this->app['config']['tenancy.models.id_generator'])) {
|
||||||
$this->app->bind(Contracts\UniqueIdentifierGenerator::class, $this->app['config']['tenancy.id_generator']);
|
$this->app->bind(Contracts\UniqueIdentifierGenerator::class, $this->app['config']['tenancy.models.id_generator']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->app->singleton(Commands\Migrate::class, function ($app) {
|
$this->app->singleton(Commands\Migrate::class, function ($app) {
|
||||||
|
|
|
||||||
|
|
@ -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 () {
|
test('tenant can be identified by subdomain', function () {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use Stancl\Tenancy\Database\Concerns\HasDomains;
|
||||||
use Stancl\Tenancy\Jobs\DeleteDomains;
|
use Stancl\Tenancy\Jobs\DeleteDomains;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
config(['tenancy.tenant_model' => DatabaseAndDomainTenant::class]);
|
config(['tenancy.models.tenant' => DatabaseAndDomainTenant::class]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('job delete domains successfully', function (){
|
test('job delete domains successfully', function (){
|
||||||
|
|
@ -29,4 +29,4 @@ test('job delete domains successfully', function (){
|
||||||
class DatabaseAndDomainTenant extends \Stancl\Tenancy\Tests\Etc\Tenant
|
class DatabaseAndDomainTenant extends \Stancl\Tenancy\Tests\Etc\Tenant
|
||||||
{
|
{
|
||||||
use HasDomains;
|
use HasDomains;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 () {
|
test('tenant can be identified using hostname', function () {
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ beforeEach(function () {
|
||||||
$table->foreign('post_id')->references('id')->on('posts')->onUpdate('cascade')->onDelete('cascade');
|
$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 () {
|
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 () {
|
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('comments');
|
||||||
Schema::drop('posts');
|
Schema::drop('posts');
|
||||||
|
|
|
||||||
|
|
@ -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 () {
|
test('tenant can be identified by subdomain', function () {
|
||||||
|
|
|
||||||
|
|
@ -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 () {
|
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) {
|
$this->mock(UUIDGenerator::class, function ($mock) {
|
||||||
return $mock->shouldReceive('generate')->once();
|
return $mock->shouldReceive('generate')->once();
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ abstract class TestCase extends \Orchestra\Testbench\TestCase
|
||||||
'central' => true,
|
'central' => true,
|
||||||
],
|
],
|
||||||
'tenancy.seeder_parameters' => [],
|
'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
|
$app->singleton(RedisTenancyBootstrapper::class); // todo (Samuel) use proper approach eg config for singleton registration
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue