Skip to content

Commit

Permalink
Allow both ROLE_USER&SURFCONEXT_REPRESENTATIVE
Browse files Browse the repository at this point in the history
At the same time. This entails rearanging the SamlProvider slightly.

Tests where made to reflect the combinations between the roles
  • Loading branch information
MKodde committed Aug 5, 2024
1 parent 6b4b1d9 commit de66016
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -126,22 +126,31 @@ private function assignRoles(
$authorizations = null;
}
// Default to the ROLE_USER role for services.
$role = 'ROLE_USER';
if ($authorizations && $authorizations->isSurfConextRepresentative()) {
$role = 'ROLE_SURFCONEXT_REPRESENTATIVE';
$contact->setInstitutionId($authorizations->getOrganizationCode());
$contact->assignRole($role);
$contact->assignRole('ROLE_SURFCONEXT_REPRESENTATIVE');
}

if (array_intersect($this->administratorTeams, $teamNames) !== []) {
$role = 'ROLE_ADMINISTRATOR';
$contact->assignRole($role);
$contact->assignRole('ROLE_ADMINISTRATOR');
return;
}

if ($role === 'ROLE_USER') {
$this->assignServicesToContact($contact, $teamNames);
if ($teamNames !== []) {
try {
$this->assignServicesToContact($contact, $teamNames);
} catch (UnknownServiceException $e) {
// If the isMemberOf attribute did not have any teams that grant the user access to SPD,
// but the user is a surfconext representative. Only grant ROLE_SURFCONEXT_REPRESENTATIVE
if ($contact->isSurfConextRepresentative()) {
return;
}
// Otherwise, the user is neither USER or ROLE_SURFCONEXT_REPRESENTATIVE, throw the original exception
// SPD will display a user friendly 405 error message.
throw $e;
}
$this->contacts->save($contact);
$contact->assignRole($role);
$contact->assignRole('ROLE_USER');
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use SAML2\Assertion;
use Surfnet\SamlBundle\Exception\RuntimeException;
use Surfnet\SamlBundle\SAML2\Attribute\AttributeDictionary;
use Surfnet\SamlBundle\SAML2\Response\AssertionAdapter;
use Surfnet\ServiceProviderDashboard\Domain\Entity\Service;
use Surfnet\ServiceProviderDashboard\Domain\Repository\ContactRepository;
use Surfnet\ServiceProviderDashboard\Domain\Repository\ServiceRepository;
use Surfnet\ServiceProviderDashboard\Infrastructure\DashboardSamlBundle\Security\Authentication\Provider\SamlProvider;
Expand Down Expand Up @@ -85,14 +89,85 @@ public function test_administrator_teams_validation_rejects_invalid_teams()
$this->buildProvider(",345345,true,false,foo,bar");
}

public function test_authorization_user()
{
$provider = $this->buildProvider("'urn:collab:foo:team.foobar.com'", 'eduPersonEntitlement');

$assertion = m::mock(Assertion::class);
$adapter = m::mock(AssertionAdapter::class);
$this->attributeDictionary->shouldReceive('translate')->andReturn($adapter);
$adapter->shouldReceive('getNameID')->andReturn('does-not-exist-yet');
$adapter->shouldReceive('getAttributeValue')->with('mail')->andReturn(['john@example.com']);
$adapter->shouldReceive('getAttributeValue')->with('commonName')->andReturn(['John Doe']);
$adapter->shouldReceive('getAttributeValue')->with('isMemberOf')->andReturn(['team-1', 'team-2']);
$this->contactRepo->shouldReceive('findByNameId')->with('does-not-exist-yet')->andReturnNull();
$service1 = m::mock(Service::class);
$service2 = m::mock(Service::class);
$this->serviceRepo->shouldReceive('findByTeamNames')->with(['team-1', 'team-2'])->andReturn([$service1, $service2]);
$this->contactRepo->shouldReceive('save');
$user = $provider->getUser($assertion);
self::assertEquals($user->getRoles(), ['ROLE_USER']);
}

public function test_authorization_surfconext_representative()
{
$provider = $this->buildProvider("'urn:collab:foo:team.foobar.com'", 'urn:mace:surfnet.nl:surfnet.nl:sab:role:SURFconext-verantwoordelijk');

$assertion = m::mock(Assertion::class);
$adapter = m::mock(AssertionAdapter::class);
$this->attributeDictionary->shouldReceive('translate')->andReturn($adapter);
$adapter->shouldReceive('getNameID')->andReturn('does-not-exist-yet');
$adapter->shouldReceive('getAttributeValue')->with('mail')->andReturn(['john@example.com']);
$adapter->shouldReceive('getAttributeValue')->with('commonName')->andReturn(['John Doe']);
$adapter->shouldReceive('getAttributeValue')->with('isMemberOf')->andReturn([]);
$adapter->shouldReceive('getAttributeValue')->with('urn:mace:surfnet.nl:surfnet.nl:sab:role:SURFconext-verantwoordelijke', [])->andReturn(
[
'urn:mace:surfnet.nl:surfnet.nl:sab:organizationCode:ibuildings',
'urn:mace:surfnet.nl:surfnet.nl:sab:role:SURFconext-verantwoordelijk',
]
);
$this->contactRepo->shouldReceive('findByNameId')->with('does-not-exist-yet')->andReturnNull();
$this->serviceRepo->shouldReceive('findByTeamNames')->andReturnNull();
$this->contactRepo->shouldReceive('save');
$user = $provider->getUser($assertion);
self::assertEquals($user->getRoles(), ['ROLE_SURFCONEXT_REPRESENTATIVE']);
}

public function test_authorization_surfconext_representative_and_user()
{
$provider = $this->buildProvider("'urn:collab:foo:team.foobar.com'", 'urn:mace:surfnet.nl:surfnet.nl:sab:role:SURFconext-verantwoordelijk');

$assertion = m::mock(Assertion::class);
$adapter = m::mock(AssertionAdapter::class);
$this->attributeDictionary->shouldReceive('translate')->andReturn($adapter);
$adapter->shouldReceive('getNameID')->andReturn('does-not-exist-yet');
$adapter->shouldReceive('getAttributeValue')->with('mail')->andReturn(['john@example.com']);
$adapter->shouldReceive('getAttributeValue')->with('commonName')->andReturn(['John Doe']);
$adapter->shouldReceive('getAttributeValue')->with('isMemberOf')->andReturn(['team-1', 'team-2']);
$adapter->shouldReceive('getAttributeValue')->with('urn:mace:surfnet.nl:surfnet.nl:sab:role:SURFconext-verantwoordelijke', [])->andReturn(
[
'urn:mace:surfnet.nl:surfnet.nl:sab:organizationCode:ibuildings',
'urn:mace:surfnet.nl:surfnet.nl:sab:role:SURFconext-verantwoordelijk',
]
);
$service1 = m::mock(Service::class);
$service2 = m::mock(Service::class);
$this->serviceRepo->shouldReceive('findByTeamNames')->with(['team-1', 'team-2'])->andReturn([$service1, $service2]);
$this->contactRepo->shouldReceive('findByNameId')->with('does-not-exist-yet')->andReturnNull();
$this->serviceRepo->shouldReceive('findByTeamNames')->andReturnNull();
$this->contactRepo->shouldReceive('save');
$user = $provider->getUser($assertion);
self::assertEquals($user->getRoles(), ['ROLE_SURFCONEXT_REPRESENTATIVE', 'ROLE_USER']);
}

private function buildProvider(string $administratorTeams, $surfConextResponsible = "defualt")
{
return new SamlProvider(
$this->contactRepo,
$this->serviceRepo,
$this->attributeDictionary,
$this->logger,
'surf-autorisaties',
'urn:mace:surfnet.nl:surfnet.nl:sab:role:SURFconext-verantwoordelijke',
$surfConextResponsible,
$administratorTeams,
);
Expand Down

0 comments on commit de66016

Please sign in to comment.