From 5e7c758fcd26280d7662a9b0e2d12f9b4ca58b68 Mon Sep 17 00:00:00 2001 From: sindoring Date: Sun, 4 Oct 2026 20:43:36 +0400 Subject: [PATCH] fix --- ...000002_create_vmangos_site_credentials.php | 14 +++- ...eb_user_id_to_vmangos_site_credentials.php | 18 +++-- .../VMangosSiteCredentialsMigrationTest.php | 73 +++++++++++++++++++ 3 files changed, 95 insertions(+), 10 deletions(-) create mode 100644 tests/Feature/VMangosSiteCredentialsMigrationTest.php diff --git a/database/migrations/2026_10_03_000002_create_vmangos_site_credentials.php b/database/migrations/2026_10_03_000002_create_vmangos_site_credentials.php index f58ef3e..6a9f891 100644 --- a/database/migrations/2026_10_03_000002_create_vmangos_site_credentials.php +++ b/database/migrations/2026_10_03_000002_create_vmangos_site_credentials.php @@ -8,12 +8,20 @@ return new class extends Migration { public function getConnection(): ?string { - return app()->environment('testing') ? config('database.default') : 'vmangos_auth'; + return app()->environment('testing') ? config('database.default') : config('moonwell.auth_connection'); } public function up(): void { - Schema::connection($this->getConnection())->create('site_credentials', function (Blueprint $table): void { + $schema = Schema::connection($this->getConnection()); + + // Restoring the web database can lose migration history while realmd + // still contains credentials from an earlier deployment. + if ($schema->hasTable('site_credentials')) { + return; + } + + $schema->create('site_credentials', function (Blueprint $table): void { $table->unsignedInteger('account_id')->primary(); $table->unsignedInteger('legacy_account_id')->nullable()->unique(); $table->char('salt_hex', 64); @@ -27,6 +35,6 @@ return new class extends Migration public function down(): void { - Schema::connection($this->getConnection())->dropIfExists('site_credentials'); + // The table can predate this migration. Preserve shared credentials. } }; diff --git a/database/migrations/2026_10_04_000001_add_web_user_id_to_vmangos_site_credentials.php b/database/migrations/2026_10_04_000001_add_web_user_id_to_vmangos_site_credentials.php index b884fc6..1a5d727 100644 --- a/database/migrations/2026_10_04_000001_add_web_user_id_to_vmangos_site_credentials.php +++ b/database/migrations/2026_10_04_000001_add_web_user_id_to_vmangos_site_credentials.php @@ -13,9 +13,16 @@ return new class extends Migration public function up(): void { - Schema::connection($this->getConnection())->table('site_credentials', function (Blueprint $table): void { - // web.users lives in another database, so no cross-database foreign key. - $table->unsignedBigInteger('web_user_id')->nullable()->unique(); + $schema = Schema::connection($this->getConnection()); + + if (! $schema->hasColumn('site_credentials', 'web_user_id')) { + $schema->table('site_credentials', function (Blueprint $table): void { + // web.users lives in another database, so no cross-database foreign key. + $table->unsignedBigInteger('web_user_id')->nullable()->unique(); + }); + } + + $schema->table('site_credentials', function (Blueprint $table): void { $table->char('salt_hex', 64)->nullable()->change(); $table->char('verifier_hex', 64)->nullable()->change(); }); @@ -23,9 +30,6 @@ return new class extends Migration public function down(): void { - Schema::connection($this->getConnection())->table('site_credentials', function (Blueprint $table): void { - $table->dropUnique(['web_user_id']); - $table->dropColumn('web_user_id'); - }); + // The column can predate this migration. Preserve existing web mappings. } }; diff --git a/tests/Feature/VMangosSiteCredentialsMigrationTest.php b/tests/Feature/VMangosSiteCredentialsMigrationTest.php new file mode 100644 index 0000000..cbafa12 --- /dev/null +++ b/tests/Feature/VMangosSiteCredentialsMigrationTest.php @@ -0,0 +1,73 @@ + 'migration_test', + 'database.connections.migration_test' => ['driver' => 'sqlite', 'database' => ':memory:', 'prefix' => ''], + ]); + DB::purge('migration_test'); + } + + protected function tearDown(): void + { + DB::purge('migration_test'); + parent::tearDown(); + } + + public function test_fresh_install_and_repeated_migrations_preserve_web_mappings(): void + { + $create = require database_path('migrations/2026_10_03_000002_create_vmangos_site_credentials.php'); + $link = require database_path('migrations/2026_10_04_000001_add_web_user_id_to_vmangos_site_credentials.php'); + $create->up(); + $link->up(); + DB::table('site_credentials')->insert(['account_id' => 1, 'web_user_id' => 42]); + + $create->up(); + $link->up(); + $this->assertDatabaseHas('site_credentials', [ + 'account_id' => 1, 'web_user_id' => 42, 'salt_hex' => null, 'verifier_hex' => null, + ]); + $this->assertSame(1, DB::table('site_credentials')->count()); + + $link->down(); + $create->down(); + $this->assertDatabaseHas('site_credentials', ['account_id' => 1, 'web_user_id' => 42]); + } + + public function test_existing_legacy_table_is_upgraded_without_losing_credentials(): void + { + Schema::create('site_credentials', function (Blueprint $table): void { + $table->unsignedInteger('account_id')->primary(); + $table->unsignedInteger('legacy_account_id')->nullable()->unique(); + $table->char('salt_hex', 64); + $table->char('verifier_hex', 64); + $table->timestamps(); + }); + DB::table('site_credentials')->insert([ + 'account_id' => 7, 'legacy_account_id' => 17, + 'salt_hex' => str_repeat('A', 64), 'verifier_hex' => str_repeat('B', 64), + ]); + + $create = require database_path('migrations/2026_10_03_000002_create_vmangos_site_credentials.php'); + $link = require database_path('migrations/2026_10_04_000001_add_web_user_id_to_vmangos_site_credentials.php'); + $create->up(); + $link->up(); + $this->assertDatabaseHas('site_credentials', [ + 'account_id' => 7, 'legacy_account_id' => 17, 'web_user_id' => null, + 'salt_hex' => str_repeat('A', 64), 'verifier_hex' => str_repeat('B', 64), + ]); + DB::table('site_credentials')->insert(['account_id' => 8, 'web_user_id' => 28]); + $this->assertDatabaseHas('site_credentials', ['account_id' => 8, 'salt_hex' => null, 'verifier_hex' => null]); + } +}