for($this->tenant)->create([ 'slug' => 'secure-photo-upload', ]); MediaStorageTarget::query()->create([ 'key' => 'local', 'name' => 'Local Storage', 'driver' => 'local', 'is_hot' => true, 'is_default' => true, 'is_active' => true, 'priority' => 1, ]); $package = Package::factory()->endcustomer()->create([ 'max_photos' => 500, 'max_guests' => 100, 'gallery_days' => 30, ]); EventPackage::query()->create([ 'event_id' => $event->id, 'package_id' => $package->id, 'purchased_price' => 0, 'used_photos' => 0, 'used_guests' => 0, ]); $file = UploadedFile::fake()->image('photo.jpeg', 800, 600); $response = $this->withHeaders([ 'Authorization' => 'Bearer '.$this->token, 'Accept' => 'application/json', ])->post("/api/v1/tenant/events/{$event->slug}/photos", [ 'photo' => $file, ]); $response->assertCreated(); $photo = Photo::query()->first(); $this->assertNotNull($photo); $this->assertSame('jpg', strtolower(pathinfo((string) $photo->file_path, PATHINFO_EXTENSION))); if (Photo::supportsFilenameColumn()) { $this->assertStringEndsWith('.jpg', (string) $photo->filename); } } public function test_member_without_moderation_permission_cannot_access_moderation_queue(): void { $event = Event::factory()->for($this->tenant)->create([ 'slug' => 'no-moderation-permission', ]); $memberUser = User::factory()->create([ 'email' => 'limited.member@example.com', 'tenant_id' => $this->tenant->id, 'role' => 'member', 'password' => Hash::make('secret123'), ]); EventMember::factory()->create([ 'tenant_id' => $this->tenant->id, 'event_id' => $event->id, 'user_id' => $memberUser->id, 'email' => $memberUser->email, 'role' => 'member', 'status' => 'active', 'permissions' => [], ]); $login = $this->postJson('/api/v1/tenant-auth/login', [ 'login' => $memberUser->email, 'password' => 'secret123', ]); $login->assertOk(); $token = $login->json('token'); $response = $this->withHeaders([ 'Authorization' => 'Bearer '.$token, 'Accept' => 'application/json', ])->getJson("/api/v1/tenant/events/{$event->slug}/photos/moderation"); $response->assertForbidden(); $response->assertJsonPath('error.code', 'insufficient_permission'); } }