[], 'coruna.panel.agent_hosts' => [], ]); } private function superAdmin(): Admin { return Admin::query()->create([ 'username' => 'root', 'password' => 'secret12', 'is_super' => 1, ]); } private function staffAdmin(): Admin { return Admin::query()->create([ 'username' => 'staff', 'password' => 'secret12', 'is_super' => 0, ]); } #[Test] public function super_admin_can_add_mnemonic_with_device_and_source(): void { $admin = $this->superAdmin(); $device = Device::query()->create(['device_id' => '001938811A46201E']); $this->actingAs($admin, 'admin') ->postJson(route('admin.mnemonics.store'), [ 'device_id' => '001938811A46201E', 'source' => 'TronLink', 'mnemonic' => " abandon abandon abandon abandon abandon abandon\nabandon abandon abandon abandon abandon about ", ]) ->assertOk() ->assertJsonPath('code', 0) ->assertJsonPath('data.device_id', '001938811A46201E') ->assertJsonPath('data.source', 'TronLink'); $row = WalletMnemonic::query()->first(); $this->assertNotNull($row); $this->assertSame($device->id, (int) $row->device_id); $this->assertSame('TronLink', $row->source); $this->assertSame(self::PHRASE, $row->mnemonic); $log = SystemLog::query()->where('action', SystemLog::ACTION_MNEMONIC_CREATE)->first(); $this->assertNotNull($log); $this->assertSame('root', $log->actor_username); $this->assertStringContainsString('设备 001938811A46201E', (string) $log->content); $this->assertStringContainsString('来源 TronLink', (string) $log->content); $this->assertStringNotContainsString('abandon', (string) $log->content); } #[Test] public function super_admin_can_lookup_device_by_numeric_id(): void { $admin = $this->superAdmin(); $device = Device::query()->create(['device_id' => 'dev-numeric-1']); $this->actingAs($admin, 'admin') ->postJson(route('admin.mnemonics.store'), [ 'device_id' => (string) $device->id, 'source' => '手动添加', 'mnemonic' => self::PHRASE, ]) ->assertOk() ->assertJsonPath('code', 0) ->assertJsonPath('data.source', '手动添加'); $this->assertSame(1, WalletMnemonic::query()->count()); $this->assertSame($device->id, (int) WalletMnemonic::query()->value('device_id')); } #[Test] public function staff_admin_cannot_add_mnemonic(): void { $staff = $this->staffAdmin(); Device::query()->create(['device_id' => 'dev-staff-blocked']); $this->actingAs($staff, 'admin') ->postJson(route('admin.mnemonics.store'), [ 'device_id' => 'dev-staff-blocked', 'source' => 'imToken', 'mnemonic' => self::PHRASE, ]) ->assertForbidden() ->assertJsonPath('msg', '需要超级管理员权限'); $this->assertSame(0, WalletMnemonic::query()->count()); } #[Test] public function staff_list_page_hides_create_button_super_sees_it(): void { $this->actingAs($this->staffAdmin(), 'admin') ->get(route('admin.mnemonics.index')) ->assertOk() ->assertDontSee('手动添加'); $this->actingAs($this->superAdmin(), 'admin') ->get(route('admin.mnemonics.index')) ->assertOk() ->assertSee('手动添加') ->assertSee('TronLink'); } #[Test] public function agent_portal_has_no_store_route_and_hides_create(): void { $this->assertFalse(Route::has('user.mnemonics.store')); $agent = User::query()->create([ 'username' => 'agent1', 'password' => 'secret12', 'status' => 1, ]); $this->actingAs($agent, 'agent') ->get(route('user.mnemonics.index')) ->assertOk() ->assertDontSee('手动添加'); } #[Test] public function rejects_missing_device_invalid_phrase_and_duplicate(): void { $admin = $this->superAdmin(); Device::query()->create(['device_id' => 'dev-dup']); $this->actingAs($admin, 'admin') ->postJson(route('admin.mnemonics.store'), [ 'device_id' => 'no-such-device', 'source' => 'imToken', 'mnemonic' => self::PHRASE, ]) ->assertStatus(422) ->assertJsonPath('msg', '找不到该设备'); $this->actingAs($admin, 'admin') ->postJson(route('admin.mnemonics.store'), [ 'device_id' => 'dev-dup', 'source' => 'imToken', 'mnemonic' => 'not a mnemonic', ]) ->assertStatus(422) ->assertJsonPath('code', 1); $this->actingAs($admin, 'admin') ->postJson(route('admin.mnemonics.store'), [ 'device_id' => 'dev-dup', 'source' => 'imToken', 'mnemonic' => self::PHRASE, ]) ->assertOk(); $this->actingAs($admin, 'admin') ->postJson(route('admin.mnemonics.store'), [ 'device_id' => 'dev-dup', 'source' => 'TronLink', 'mnemonic' => self::PHRASE, ]) ->assertStatus(422) ->assertJsonPath('msg', '该设备已存在相同助记词'); $this->assertSame(1, WalletMnemonic::query()->count()); } }