fix(seeding): ensure root user joins root team

Create the root team before production seeding depends on it, reuse the
existing root team when creating root users, and cover the production seeder
flow with a feature test.
This commit is contained in:
Andras Bacsai
2026-05-26 17:05:54 +02:00
parent 9c62996e40
commit 081bd6ef8c
5 changed files with 100 additions and 1 deletions
+5 -1
View File
@@ -2,6 +2,7 @@
namespace App\Actions\Fortify;
use App\Models\Team;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
@@ -44,7 +45,10 @@ class CreateNewUser implements CreatesNewUsers
'password' => Hash::make($input['password']),
]);
$user->save();
$team = $user->teams()->first();
$team = $user->teams()->first() ?? Team::find(0);
if ($team !== null && ! $user->teams()->where('team_id', $team->id)->exists()) {
$user->teams()->attach($team, ['role' => 'owner']);
}
// Disable registration after first user is created
$settings = instanceSettings();
+10
View File
@@ -98,8 +98,18 @@ class User extends Authenticatable implements SendsEmail
$team['id'] = 0;
$team['name'] = 'Root Team';
}
$new_team = $user->id === 0 ? Team::find(0) : null;
if ($new_team !== null) {
$new_team->forceFill($team);
$new_team->save();
return;
}
$new_team = (new Team)->forceFill($team);
$new_team->save();
$user->teams()->attach($new_team, ['role' => 'owner']);
});
+10
View File
@@ -32,6 +32,16 @@ class ProductionSeeder extends Seeder
echo " Running in self-hosted mode.\n";
}
if (Team::find(0) === null) {
(new Team)->forceFill([
'id' => 0,
'name' => 'Root Team',
'description' => 'The root team',
'personal_team' => true,
'show_boarding' => true,
])->save();
}
if (User::find(0) !== null && Team::find(0) !== null) {
if (DB::table('team_user')->where('user_id', 0)->first() === null) {
DB::table('team_user')->insert([
+7
View File
@@ -3,6 +3,7 @@
namespace Database\Seeders;
use App\Models\InstanceSettings;
use App\Models\Team;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
@@ -52,6 +53,12 @@ class RootUserSeeder extends Seeder
'password' => Hash::make(env('ROOT_USER_PASSWORD')),
]);
$user->save();
$team = Team::find(0);
if ($team !== null && ! $user->teams()->where('team_id', 0)->exists()) {
$user->teams()->attach($team, ['role' => 'owner']);
}
echo "\n SUCCESS Root user created successfully.\n\n";
} catch (\Exception $e) {
echo "\n ERROR Failed to create root user: {$e->getMessage()}\n\n";
+68
View File
@@ -0,0 +1,68 @@
<?php
use App\Actions\Fortify\CreateNewUser;
use App\Actions\Proxy\StartProxy;
use App\Models\Server;
use App\Models\SharedEnvironmentVariable;
use App\Models\SslCertificate;
use App\Models\Team;
use Database\Seeders\ProductionSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue;
uses(RefreshDatabase::class);
it('creates the root team before seeding the localhost server and predefined shared variables', function () {
config([
'broadcasting.default' => 'log',
'constants.coolify.is_windows_docker_desktop' => true,
]);
Queue::fake();
StartProxy::shouldRun()->andReturn('OK');
Server::creating(function (Server $server) {
if ((int) $server->getKey() === 0) {
expect(Team::find(0))->not->toBeNull();
}
});
Server::created(function (Server $server) {
SslCertificate::create([
'server_id' => $server->id,
'common_name' => 'Coolify CA Certificate',
'ssl_certificate' => 'certificate',
'ssl_private_key' => 'private-key',
'valid_until' => now()->addYear(),
'is_ca_certificate' => true,
]);
});
$this->seed(ProductionSeeder::class);
$rootTeam = Team::find(0);
$localhostServer = Server::find(0);
expect($rootTeam)->not->toBeNull()
->and($localhostServer)->not->toBeNull()
->and($localhostServer->team_id)->toBe(0);
expect(SharedEnvironmentVariable::query()
->where('type', 'server')
->where('server_id', 0)
->where('team_id', 0)
->pluck('key')
->all()
)->toContain('COOLIFY_SERVER_UUID', 'COOLIFY_SERVER_NAME');
instanceSettings()->update(['is_registration_enabled' => true]);
$rootUser = app(CreateNewUser::class)->create([
'name' => 'Root User',
'email' => 'root@example.com',
'password' => 'Password123!',
'password_confirmation' => 'Password123!',
]);
expect(Team::whereKey(0)->count())->toBe(1)
->and($rootUser->teams()->where('team_id', 0)->exists())->toBeTrue();
});