74 lines
2.8 KiB
PHP
74 lines
2.8 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Artisan;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Tests\TestCase;
|
|
|
|
/**
|
|
* clusev:install (install.sh phase 8) — first-admin bootstrap. The password is a RANDOM one-time
|
|
* secret printed once (CLUSEV_ADMIN_PASSWORD=…), not a guessable literal; must_change_password
|
|
* nudges a rotation on first login (optional).
|
|
*/
|
|
class InstallCommandTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
/** Run the command and return the password it printed on the CLUSEV_ADMIN_PASSWORD line. */
|
|
private function install(array $args = []): string
|
|
{
|
|
$this->assertSame(0, Artisan::call('clusev:install', $args));
|
|
$out = Artisan::output(); // capture once — the buffer is cleared after the first read
|
|
$this->assertMatchesRegularExpression('/CLUSEV_ADMIN_PASSWORD=(\S+)/', $out, 'must print the generated password once');
|
|
preg_match('/CLUSEV_ADMIN_PASSWORD=(\S+)/', $out, $m);
|
|
|
|
return $m[1] ?? '';
|
|
}
|
|
|
|
public function test_creates_admin_with_a_generated_password_and_forced_change(): void
|
|
{
|
|
$pw = $this->install(['--email' => 'admin@example.test']);
|
|
|
|
// Not the old guessable literal, and strong enough to resist guessing even if kept.
|
|
$this->assertNotSame('clusev', $pw);
|
|
$this->assertGreaterThanOrEqual(12, strlen($pw));
|
|
|
|
$user = User::where('email', 'admin@example.test')->first();
|
|
$this->assertNotNull($user);
|
|
$this->assertTrue(Hash::check($pw, $user->password), 'the printed password must authenticate');
|
|
$this->assertTrue((bool) $user->must_change_password, 'first login should still nudge a change');
|
|
}
|
|
|
|
public function test_uses_the_fixed_default_email_when_none_is_given(): void
|
|
{
|
|
$pw = $this->install();
|
|
|
|
$user = User::sole();
|
|
$this->assertSame('admin@clusev.local', $user->email, 'a fresh install must default to the predictable admin@clusev.local');
|
|
$this->assertTrue(Hash::check($pw, $user->password));
|
|
$this->assertTrue((bool) $user->must_change_password);
|
|
}
|
|
|
|
public function test_generates_a_distinct_password_each_install(): void
|
|
{
|
|
$first = $this->install(['--email' => 'a@example.test']);
|
|
User::query()->delete();
|
|
$second = $this->install(['--email' => 'b@example.test']);
|
|
|
|
$this->assertNotSame($first, $second, 'the generated password must not be a fixed value');
|
|
}
|
|
|
|
public function test_is_a_noop_when_an_admin_already_exists(): void
|
|
{
|
|
User::factory()->create();
|
|
|
|
$this->artisan('clusev:install', ['--email' => 'second@example.test'])->assertSuccessful();
|
|
|
|
$this->assertSame(1, User::count());
|
|
$this->assertNull(User::where('email', 'second@example.test')->first());
|
|
}
|
|
}
|