master
parent
906fe4f138
commit
a468a4135c
@ -1,104 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ResetVenueAdminPasswordsCommandTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
config([
|
||||
'database.default' => 'sqlite',
|
||||
'database.connections.sqlite.database' => ':memory:',
|
||||
]);
|
||||
DB::purge();
|
||||
DB::reconnect();
|
||||
|
||||
Schema::create('users', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('username')->nullable()->unique();
|
||||
$table->string('name');
|
||||
$table->string('email')->nullable();
|
||||
$table->timestamp('email_verified_at')->nullable();
|
||||
$table->string('password');
|
||||
$table->string('role')->default('venue_admin');
|
||||
$table->boolean('is_active')->default(true);
|
||||
$table->rememberToken();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('personal_access_tokens', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->morphs('tokenable');
|
||||
$table->string('name');
|
||||
$table->string('token', 64)->unique();
|
||||
$table->text('abilities')->nullable();
|
||||
$table->timestamp('last_used_at')->nullable();
|
||||
$table->timestamp('expires_at')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function test_dry_run_does_not_change_password_or_tokens(): void
|
||||
{
|
||||
$user = $this->venueAdmin('old_admin');
|
||||
$user->createToken('admin-token');
|
||||
$oldHash = $user->password;
|
||||
|
||||
$this->artisan('venues:reset-admin-passwords', ['--dry-run' => true])
|
||||
->assertSuccessful();
|
||||
|
||||
$fresh = $user->fresh();
|
||||
$this->assertSame($oldHash, $fresh->password);
|
||||
$this->assertSame(1, $fresh->tokens()->count());
|
||||
}
|
||||
|
||||
public function test_reset_writes_new_hash_revokes_tokens_and_exports_xlsx(): void
|
||||
{
|
||||
$user = $this->venueAdmin('venue_one');
|
||||
$user->createToken('admin-token');
|
||||
$oldHash = $user->password;
|
||||
|
||||
$out = storage_path('app/exports/test_venue_admin_password_reset.xlsx');
|
||||
if (is_file($out)) {
|
||||
unlink($out);
|
||||
}
|
||||
|
||||
$this->artisan('venues:reset-admin-passwords', ['--output' => $out])
|
||||
->assertSuccessful();
|
||||
|
||||
$fresh = $user->fresh();
|
||||
$this->assertNotSame($oldHash, $fresh->password);
|
||||
$this->assertSame(0, $fresh->tokens()->count());
|
||||
$this->assertFileExists($out);
|
||||
|
||||
$sheet = IOFactory::load($out)->getActiveSheet()->toArray();
|
||||
$this->assertSame('venue_one', $sheet[1][2]);
|
||||
$plain = (string) $sheet[1][3];
|
||||
$this->assertGreaterThanOrEqual(12, strlen($plain));
|
||||
$this->assertTrue(Hash::check($plain, $fresh->password));
|
||||
|
||||
unlink($out);
|
||||
}
|
||||
|
||||
private function venueAdmin(string $username): User
|
||||
{
|
||||
return User::query()->create([
|
||||
'username' => $username,
|
||||
'name' => '场馆管理员',
|
||||
'email' => $username.'@example.test',
|
||||
'password' => 'OldPlace!holder1',
|
||||
'role' => 'venue_admin',
|
||||
'is_active' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\Support\VenueAdminCredentials;
|
||||
use Tests\TestCase;
|
||||
|
||||
class VenueAdminCredentialsTest extends TestCase
|
||||
{
|
||||
public function test_same_venue_name_yields_different_random_passwords(): void
|
||||
{
|
||||
$name = '苏州青少年科技馆';
|
||||
$first = VenueAdminCredentials::randomPassword();
|
||||
$second = VenueAdminCredentials::randomPassword();
|
||||
|
||||
$this->assertNotSame($first, $second);
|
||||
$this->assertSame(
|
||||
VenueAdminCredentials::acronymFromVenueName($name),
|
||||
VenueAdminCredentials::acronymFromVenueName($name)
|
||||
);
|
||||
}
|
||||
|
||||
public function test_random_password_meets_strength_rules(): void
|
||||
{
|
||||
$password = VenueAdminCredentials::randomPassword();
|
||||
|
||||
$this->assertGreaterThanOrEqual(12, strlen($password));
|
||||
$this->assertMatchesRegularExpression('/[A-Z]/', $password);
|
||||
$this->assertMatchesRegularExpression('/[a-z]/', $password);
|
||||
$this->assertMatchesRegularExpression('/[0-9]/', $password);
|
||||
$this->assertMatchesRegularExpression('/[^A-Za-z0-9]/', $password);
|
||||
}
|
||||
|
||||
public function test_legacy_acronym_password_helper_is_removed(): void
|
||||
{
|
||||
$this->assertFalse(method_exists(VenueAdminCredentials::class, 'passwordFromAcronym'));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue