device_id.'/'.$name; Storage::disk('local')->put($path, $png); return Photo::query()->create([ 'device_id' => $device->id, 'sha256' => hash('sha256', $png), 'path' => $path, 'size' => strlen($png), ]); } #[Test] public function viewing_photo_marks_read_for_that_admin_only(): void { $a = Admin::query()->create(['username' => 'root', 'password' => 'secret12', 'is_super' => 1]); $b = Admin::query()->create(['username' => 'staff', 'password' => 'secret12', 'is_super' => 0]); $device = Device::query()->create(['device_id' => 'dev-read-1']); $photo = $this->storePng($device); $this->actingAs($a, 'admin') ->get(route('admin.devices.photo', [$device, $photo->id])) ->assertOk(); $this->assertSame(0, PhotoRead::query()->count()); $this->actingAs($a, 'admin') ->get(route('admin.devices.photo', [$device, $photo->id, 'seen' => 1])) ->assertOk(); $this->assertSame(1, PhotoRead::query()->count()); $row = PhotoRead::query()->first(); $this->assertSame('admin', $row->actor_guard); $this->assertSame($a->id, $row->actor_id); $this->assertSame($photo->id, $row->photo_id); $this->actingAs($a, 'admin') ->getJson(route('admin.photos.data')) ->assertOk() ->assertJsonPath('data.0.read', 1); $this->actingAs($b, 'admin') ->getJson(route('admin.photos.data')) ->assertOk() ->assertJsonPath('data.0.read', 0); $this->actingAs($a, 'admin') ->get(route('admin.devices.photo', [$device, $photo->id, 'seen' => 1])) ->assertOk(); $this->assertSame(1, PhotoRead::query()->count()); } #[Test] public function photos_data_filters_unread(): void { $admin = Admin::query()->create(['username' => 'root', 'password' => 'secret12', 'is_super' => 1]); $device = Device::query()->create(['device_id' => 'dev-read-2']); $seen = $this->storePng($device, 'a.png'); $this->storePng($device, 'b.png'); PhotoRead::mark($seen, 'admin', (int) $admin->id); $this->actingAs($admin, 'admin') ->getJson(route('admin.photos.data', ['read' => '0'])) ->assertOk() ->assertJsonPath('count', 1) ->assertJsonPath('data.0.read', 0); $this->actingAs($admin, 'admin') ->getJson(route('admin.photos.data', ['read' => '1'])) ->assertOk() ->assertJsonPath('count', 1) ->assertJsonPath('data.0.id', $seen->id) ->assertJsonPath('data.0.read', 1); } #[Test] public function device_tab_filters_unread(): void { $admin = Admin::query()->create(['username' => 'root', 'password' => 'secret12', 'is_super' => 1]); $device = Device::query()->create(['device_id' => 'dev-read-3']); $seen = $this->storePng($device, 'a.png'); $this->storePng($device, 'b.png'); PhotoRead::mark($seen, 'admin', (int) $admin->id); $tab = $this->actingAs($admin, 'admin') ->getJson(route('admin.devices.tabData', [$device, 'tab' => 'photos', 'read' => '0'])) ->assertOk() ->assertJsonPath('count', 1) ->assertJsonPath('data.0.read', 0); $this->assertStringContainsString('seen=1', (string) $tab->json('data.0.url')); } #[Test] public function agent_read_is_separate_from_admin(): void { $admin = Admin::query()->create(['username' => 'root', 'password' => 'secret12', 'is_super' => 1]); $agent = User::query()->create([ 'username' => 'photo_agent', 'password' => 'secret12', 'status' => 1, ]); Channel::query()->create([ 'channel_id' => 'cccccccccccccccccccccccccccccccc', 'user_id' => $agent->id, 'status' => 1, ]); $device = Device::query()->create([ 'device_id' => 'dev-read-agent', 'channel_id' => 'cccccccccccccccccccccccccccccccc', ]); $photo = $this->storePng($device); $this->actingAs($admin, 'admin') ->get(route('admin.devices.photo', [$device, $photo->id, 'seen' => 1])) ->assertOk(); $list = $this->actingAs($agent, 'agent') ->getJson(route('user.photos.data')) ->assertOk() ->assertJsonPath('data.0.read', 0); $this->assertStringNotContainsString('seen=1', (string) $list->json('data.0.url')); $this->actingAs($agent, 'agent') ->get(route('user.devices.photo', [$device, $photo->id, 'seen' => 1])) ->assertOk(); $this->assertSame(2, PhotoRead::query()->count()); $this->assertTrue(PhotoRead::query()->where('actor_guard', 'agent')->where('actor_id', $agent->id)->exists()); } #[Test] public function missing_file_does_not_mark_read(): void { Storage::fake('local'); $admin = Admin::query()->create(['username' => 'root', 'password' => 'secret12', 'is_super' => 1]); $device = Device::query()->create(['device_id' => 'dev-read-missing']); $photo = Photo::query()->create([ 'device_id' => $device->id, 'sha256' => str_repeat('a', 64), 'path' => 'c2/photos/dev-read-missing/gone.png', 'size' => 1, ]); $this->actingAs($admin, 'admin') ->get(route('admin.devices.photo', [$device, $photo->id])) ->assertNotFound(); $this->assertSame(0, PhotoRead::query()->count()); } }