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

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 @@ public function create(array $input): User
'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();

View file

@ -98,8 +98,18 @@ protected static function boot()
$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']);
});

View file

@ -32,6 +32,16 @@ public function run(): void
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([

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 @@ public function run(): void
'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";

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();
});