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