diff --git a/app/ModelSerializers/Summit/Speakers/PresentationSpeakerSerializer.php b/app/ModelSerializers/Summit/Speakers/PresentationSpeakerSerializer.php index 2e7476088..fdc018f3a 100644 --- a/app/ModelSerializers/Summit/Speakers/PresentationSpeakerSerializer.php +++ b/app/ModelSerializers/Summit/Speakers/PresentationSpeakerSerializer.php @@ -394,10 +394,9 @@ protected function checkDataPermissions(PresentationSpeaker $speaker, array $val } */ - if(!$speaker->isPublicProfileShowTelephoneNumber()) - { - if(isset($values['phone_number'])) $values['phone_number'] = ''; - } + // phone_number is never public regardless of the target speaker's own account + // visibility toggle - see policy/profile-data-handling.md Rule 4. + if(isset($values['phone_number'])) $values['phone_number'] = ''; return $values; } diff --git a/tests/PresentationSpeakerSerializerTest.php b/tests/PresentationSpeakerSerializerTest.php new file mode 100644 index 000000000..192a02184 --- /dev/null +++ b/tests/PresentationSpeakerSerializerTest.php @@ -0,0 +1,52 @@ +makePartial(); + $speaker->shouldReceive('hasMember')->andReturn(false); + $speaker->shouldReceive('getPhoneNumber')->andReturn('+1-555-0100'); + // target speaker's own account-level toggle is ON - the exact case that used to leak + // the raw phone_number regardless of the requesting caller's identity. + $speaker->shouldReceive('isPublicProfileShowTelephoneNumber')->andReturn(true); + $speaker->shouldReceive('isPublicProfileShowBio')->andReturn(true); + $speaker->shouldReceive('isPublicProfileShowEmail')->andReturn(true); + $speaker->shouldReceive('isPublicProfileShowSocialMediaInfo')->andReturn(true); + $speaker->shouldReceive('isPublicProfileShowPhoto')->andReturn(true); + + $resource_server_context = Mockery::mock(IResourceServerContext::class); + $serializer = new PresentationSpeakerSerializer($speaker, $resource_server_context); + + $values = $serializer->serialize(null, ['phone_number'], ['none']); + + $this->assertSame('', $values['phone_number']); + } +}