diff --git a/tests/Etc/synced_resource_migrations/custom/central/2020_06_11_000001_test_create_central_users_with_extra_fields_table.php b/tests/Etc/synced_resource_migrations/custom/central/2020_06_11_000001_test_create_central_users_with_extra_fields_table.php new file mode 100644 index 00000000..5137b82c --- /dev/null +++ b/tests/Etc/synced_resource_migrations/custom/central/2020_06_11_000001_test_create_central_users_with_extra_fields_table.php @@ -0,0 +1,35 @@ +increments('id'); + $table->string('global_id')->unique(); + $table->string('name'); + $table->string('email'); + $table->string('password'); + + // extra columns + $table->string('role'); + $table->string('code'); + }); + } + + public function down() + { + Schema::dropIfExists('central_users'); + } +} diff --git a/tests/Etc/synced_resource_migrations/custom/central/2020_07_12_000011_test_create_tenant_central_users_pivot_table.php b/tests/Etc/synced_resource_migrations/custom/central/2020_07_12_000011_test_create_tenant_central_users_pivot_table.php new file mode 100644 index 00000000..cbf5255e --- /dev/null +++ b/tests/Etc/synced_resource_migrations/custom/central/2020_07_12_000011_test_create_tenant_central_users_pivot_table.php @@ -0,0 +1,34 @@ +increments('id'); + $table->string('tenant_id'); + $table->string('global_user_id'); + + $table->unique(['tenant_id', 'global_user_id']); + + $table->foreign('tenant_id')->references('id')->on('tenants')->onUpdate('cascade')->onDelete('cascade'); + $table->foreign('global_user_id')->references('global_id')->on('central_users')->onUpdate('cascade')->onDelete('cascade'); + }); + } + + public function down() + { + Schema::dropIfExists('tenant_central_users'); + } +} diff --git a/tests/Etc/synced_resource_migrations/custom/tenant/2020_05_11_000001_test_create_resource_users_with_no_extra_fields_table.php b/tests/Etc/synced_resource_migrations/custom/tenant/2020_05_11_000001_test_create_resource_users_with_no_extra_fields_table.php new file mode 100644 index 00000000..2f045d47 --- /dev/null +++ b/tests/Etc/synced_resource_migrations/custom/tenant/2020_05_11_000001_test_create_resource_users_with_no_extra_fields_table.php @@ -0,0 +1,31 @@ +increments('id'); + $table->string('global_id')->unique(); + $table->string('name'); + $table->string('email'); + $table->string('password'); + }); + } + + public function down() + { + Schema::dropIfExists('resource_users'); + } +} diff --git a/tests/ResourceSyncingTest.php b/tests/ResourceSyncingTest.php index e495f95a..683e5b42 100644 --- a/tests/ResourceSyncingTest.php +++ b/tests/ResourceSyncingTest.php @@ -4,9 +4,11 @@ declare(strict_types=1); use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Schema\Blueprint; use Illuminate\Events\CallQueuedListener; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Queue; +use Illuminate\Support\Facades\Schema; use Illuminate\Support\Str; use Stancl\JobPipeline\JobPipeline; use Stancl\Tenancy\Bootstrappers\DatabaseTenancyBootstrapper; @@ -370,6 +372,67 @@ test('creating the resource in central database creates it in tenant database wi }); }); +test('sync resources work when the central model creation method returns attribute names and the resource model creation method returns default values ', function (){ + // migrate central_users table and tenant_central_users pivot table + pest()->artisan('migrate', [ + '--path' => __DIR__ . '/Etc/synced_resource_migrations/custom/central', + '--realpath' => true, + ])->assertExitCode(0); + + $tenant1 = ResourceTenantWithCustomPivot::create(['id' => 't1']); + + // migrate resource_users tenant table + migrateTenantsResource(__DIR__ . '/Etc/synced_resource_migrations/custom/tenant'); + + $centralUser = CentralUserWithExtraAttributes::create([ + 'global_id' => 'acme', + 'name' => 'John Doe', + 'email' => 'john@localhost', + 'password' => 'password', + 'role' => 'admin', + 'code' => 'foo', + ]); + + $tenant1->run(function () { + expect(ResourceUserWithNoExtraAttributes::all())->toHaveCount(0); + }); + + $centralUser->tenants()->attach('t1'); + + $tenant1->run(function () { + $resourceUserWithNoExtraAttributes = ResourceUserWithNoExtraAttributes::first(); + expect(ResourceUserWithNoExtraAttributes::all())->toHaveCount(1); + expect($resourceUserWithNoExtraAttributes->global_id)->toBe('acme'); + + // role and code does not exist in resource_users table + expect($resourceUserWithNoExtraAttributes->role)->toBeNull(); + expect($resourceUserWithNoExtraAttributes->code)->toBeNull(); + }); + + $tenant2 = ResourceTenantWithCustomPivot::create(); + // migrate resource_users tenant table + migrateTenantsResource(__DIR__ . '/Etc/synced_resource_migrations/custom/tenant'); + tenancy()->initialize($tenant2); + + // Create the user in tenant DB + ResourceUserWithNoExtraAttributes::create([ + 'global_id' => 'acmey', + 'name' => 'John Doe', + 'email' => 'john@localhost', + 'password' => 'password', + ]); + + tenancy()->end(); + + $centralUserWithExtraAttributes = CentralUserWithExtraAttributes::latest('id')->first(); // get the last user because first one already created + expect($centralUserWithExtraAttributes->global_id)->toBe('acmey'); + + // CentralUserWithExtraAttributes are providing these default value + expect($centralUserWithExtraAttributes->password)->toBe('secret'); + expect($centralUserWithExtraAttributes->code)->toBe('foo'); + expect($centralUserWithExtraAttributes->role)->toBe('admin'); +}); + test('creating the resource in tenant database creates it in central database and creates the mapping', function () { creatingResourceInTenantDatabaseCreatesAndMapInCentralDatabase(); }); @@ -781,10 +844,10 @@ function creatingResourceInTenantDatabaseCreatesAndMapInCentralDatabase() expect(ResourceUser::first()->role)->toBe('commenter'); } -function migrateTenantsResource() +function migrateTenantsResource(?string $path = null) { pest()->artisan('tenants:migrate', [ - '--path' => __DIR__ . '/Etc/synced_resource_migrations/users', + '--path' => $path ?? __DIR__ . '/Etc/synced_resource_migrations/users', '--realpath' => true, ])->assertExitCode(0); } @@ -973,4 +1036,67 @@ class CentralUserWithAttributeNamesAndDefaultValues extends CentralUser { } } +class ResourceTenantWithCustomPivot extends Tenant +{ + public function users() + { + return $this->belongsToMany(CentralUserWithExtraAttributes::class, 'tenant_central_users', 'tenant_id', 'global_user_id', 'id', 'global_id') + ->using(TenantPivot::class); + } +} +class CentralUserWithExtraAttributes extends CentralUser { + public $table = 'central_users'; + + public function tenants(): BelongsToMany + { + return $this->belongsToMany(ResourceTenantWithCustomPivot::class, 'tenant_central_users', 'global_user_id', 'tenant_id', 'global_id') + ->using(TenantPivot::class); + } + + public function getTenantModelName(): string + { + return ResourceUserWithNoExtraAttributes::class; + } + + public function getSyncedCreationAttributes(): array + { + return [ + 'global_id', + 'name', + 'password', + 'email', + ]; + } +} + +class ResourceUserWithNoExtraAttributes extends ResourceUser { + protected $table = 'resource_users'; + + public function getCentralModelName(): string + { + return CentralUserWithExtraAttributes::class; + } + + public function getSyncedAttributeNames(): array + { + return [ + 'global_id', + 'name', + 'email', + ]; + } + + public function getSyncedCreationAttributes(): array + { + return [ + 'global_id', + 'name', + 'email', + // Provide default values + 'password' => 'secret', + 'role' => 'admin', + 'code' => 'foo', + ]; + } +}