Code development platform for open source projects from the European Union institutions

Skip to content
Snippets Groups Projects
Unverified Commit 65f32577 authored by Pol Dellaiera's avatar Pol Dellaiera Committed by GitHub
Browse files

Merge pull request #8 from ecphp/parse-extendedAttributes

Parse EU Access attributes.
parents e0d253ce 88b8f5b2
No related branches found
Tags 2.3.2
No related merge requests found
......@@ -21,11 +21,11 @@
"symfony/framework-bundle": "^5.1"
},
"require-dev": {
"drupol/php-conventions": "^1.8.6",
"drupol/php-conventions": "^1.8.16",
"friends-of-phpspec/phpspec-code-coverage": "^4.3.2",
"infection/infection": "^0.15.3",
"phpspec/phpspec": "^6.2.1",
"vimeo/psalm": "^3.12"
"vimeo/psalm": "^3.13"
},
"autoload": {
"psr-4": {
......
......@@ -8,4 +8,4 @@ extensions:
output:
html: build/coverage
clover: build/logs/clover.xml
php: build/coverage.php
\ No newline at end of file
php: build/coverage.php
......@@ -54,6 +54,12 @@ class EuLoginUserProviderSpec extends ObjectBehavior
<cas:group>group1</cas:group>
<cas:group>group2</cas:group>
</cas:groups>
<cas:extendedAttributes>
<cas:extendedAttribute name="http://stork.eu/motherInLawDogName">
<cas:attributeValue>rex</cas:attributeValue>
<cas:attributeValue>snoopy</cas:attributeValue>
</cas:extendedAttribute>
</cas:extendedAttributes>
</cas:authenticationSuccess>
</cas:serviceResponse>
EOF;
......@@ -77,11 +83,17 @@ EOF;
'group2',
],
],
'extendedAttributes' => [
'http://stork.eu/motherInLawDogName' => [
'rex',
'snoopy',
],
],
]);
$this
->loadUserByResponse($response)
->getUser()
->getUsername()
->shouldReturn('username');
$this
......@@ -92,6 +104,17 @@ EOF;
'group2',
'ROLE_CAS_AUTHENTICATED',
]);
$this->loadUserByResponse($response)
->getExtendedAttributes()
->shouldReturn(
[
'http://stork.eu/motherInLawDogName' => [
'rex',
'snoopy',
],
]
);
}
public function it_can_refresh_a_user(EuLoginUserInterface $user)
......
......@@ -6,27 +6,47 @@ namespace spec\EcPhp\EuLoginBundle\Security\Core\User;
use EcPhp\CasBundle\Security\Core\User\CasUser;
use EcPhp\CasBundle\Security\Core\User\CasUserInterface;
use EcPhp\CasLib\Introspection\Introspector;
use EcPhp\EuLoginBundle\Security\Core\User\EuLoginUser;
use Nyholm\Psr7\Response;
use PhpSpec\ObjectBehavior;
class EuLoginUserSpec extends ObjectBehavior
{
public function it_can_get_groups_when_no_groups_are_available()
{
$attributes = $this->getAttributesData();
unset($attributes['groups']);
$data = [
'user' => 'user',
'proxyGrantingTicket' => 'proxyGrantingTicket',
'proxies' => [
'proxy1',
],
'attributes' => $attributes,
];
$body = <<<'EOF'
<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
<cas:authenticationSuccess>
<cas:user>username</cas:user>
<cas:foo>bar</cas:foo>
<cas:proxies>
<cas:proxy>foo</cas:proxy>
</cas:proxies>
<cas:attributes>
<cas:groups number="10">
<cas:group>group1</cas:group>
<cas:group>group2</cas:group>
</cas:groups>
<cas:extendedAttributes>
<cas:extendedAttribute name="http://stork.eu/motherInLawDogName">
<cas:attributeValue>rex</cas:attributeValue>
<cas:attributeValue>snoopy</cas:attributeValue>
</cas:extendedAttribute>
</cas:extendedAttributes>
</cas:attributes>
</cas:authenticationSuccess>
</cas:serviceResponse>
EOF;
$response = new Response(200, ['Content-Type' => 'application/xml'], $body);
$data = (new Introspector())->parse($response)['serviceResponse']['authenticationSuccess'];
unset($data['attributes']['groups']);
$casUser = new CasUser($data);
$this
->beConstructedWith(new CasUser($data));
->beConstructedWith($casUser);
$this
->getGroups()
......@@ -37,11 +57,11 @@ class EuLoginUserSpec extends ObjectBehavior
{
$this
->getAssuranceLevel()
->shouldReturn('assuranceLevel');
->shouldReturn('40');
$this
->getAuthenticationFactors()
->shouldReturn(['foobar']);
->shouldReturn(['ecphp@ec.europa.eu']);
$this
->getDepartmentNumber()
......@@ -73,7 +93,10 @@ class EuLoginUserSpec extends ObjectBehavior
$this
->getGroups()
->shouldReturn(['foo']);
->shouldReturn([
'group1',
'group2',
]);
$this
->getLastName()
......@@ -114,28 +137,14 @@ class EuLoginUserSpec extends ObjectBehavior
$this
->getUid()
->shouldReturn('uid');
$this
->getAttributes()
->shouldReturn($this->getAttributesData());
}
public function it_can_get_the_attributes_only(CasUserInterface $user)
{
$data = [
'user' => 'user',
'proxyGrantingTicket' => 'proxyGrantingTicket',
'proxies' => [
'proxy1',
],
'attributes' => $this->getAttributesData(),
];
$user
->getAttributes()
->willReturn($this->getAttributesData());
$user
->beConstructedWith($data);
$this
->beConstructedWith($user);
$this
->getAttributes()
->shouldReturn($this->getAttributesData());
......@@ -144,30 +153,115 @@ class EuLoginUserSpec extends ObjectBehavior
public function it_is_initializable()
{
$this->shouldHaveType(EuLoginUser::class);
$this
->getPassword()
->shouldBeNull();
$this
->getPgt()
->shouldReturn('proxyGrantingTicket');
$this
->getSalt()
->shouldBeNull();
$this
->getAttribute('user')
->shouldReturn('username');
$this
->getUser()
->shouldReturn('username');
$this
->get('foo', 'bar')
->shouldReturn('bar');
$this
->eraseCredentials()
->shouldBeNull();
}
public function let(CasUserInterface $user)
{
$data = [
'user' => 'user',
'proxyGrantingTicket' => 'proxyGrantingTicket',
'proxies' => [
'proxy1',
],
'attributes' => $this->getAttributesData(),
];
$body = <<<'EOF'
<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
<cas:authenticationSuccess>
<cas:user>username</cas:user>
<cas:foo>bar</cas:foo>
<cas:proxies>
<cas:proxy>foo</cas:proxy>
</cas:proxies>
<cas:proxyGrantingTicket>
proxyGrantingTicket
</cas:proxyGrantingTicket>
<cas:attributes>
<cas:authenticationFactors>
<cas:moniker number="1">
ecphp@ec.europa.eu
</cas:moniker>
</cas:authenticationFactors>
<cas:assuranceLevel>40</cas:assuranceLevel>
<cas:groups number="10">
<cas:group>group1</cas:group>
<cas:group>group2</cas:group>
</cas:groups>
<cas:extendedAttributes>
<cas:extendedAttribute name="http://stork.eu/motherInLawDogName">
<cas:attributeValue>rex</cas:attributeValue>
<cas:attributeValue>snoopy</cas:attributeValue>
</cas:extendedAttribute>
</cas:extendedAttributes>
</cas:attributes>
</cas:authenticationSuccess>
</cas:serviceResponse>
EOF;
$response = new Response(200, ['Content-Type' => 'application/json'], $body);
$data = (new Introspector())->parse($response)['serviceResponse']['authenticationSuccess'];
$user
->beConstructedWith($data);
$user
->getAttribute('extendedAttributes', [])
->willReturn([
'extendedAttribute' => [
'attributeValue' => [
'value1',
'value2',
],
'@attributes' => [
'name' => 'attr1',
],
],
]);
$user
->get('foo', 'bar')
->willReturn('bar');
$user
->getUsername()
->willReturn('username');
$user
->getAttribute('user', null)
->willReturn('username');
$user
->getPgt()
->willReturn('proxyGrantingTicket');
$user
->getAttribute('assuranceLevel')
->willReturn('assuranceLevel');
->willReturn($data['attributes']['assuranceLevel']);
$user
->getAttribute('authenticationFactors', [])
->willReturn([
'foobar',
'ecphp@ec.europa.eu',
]);
$user
......@@ -199,9 +293,15 @@ class EuLoginUserSpec extends ObjectBehavior
->willReturn('firstName');
$user
->getAttribute('groups', [])
->getAttribute('groups', ['group' => []])
->willReturn([
'foo',
'group' => [
'group1',
'group2',
],
'@attributes' => [
'number' => 2,
],
]);
$user
......@@ -246,6 +346,10 @@ class EuLoginUserSpec extends ObjectBehavior
->getAttribute('uid')
->willReturn('uid');
$user
->getAttributes()
->willReturn($this->getAttributesData());
$this
->beConstructedWith($user);
}
......@@ -257,24 +361,31 @@ class EuLoginUserSpec extends ObjectBehavior
'email' => 'email',
'employeeNumber' => 'employeeNumber',
'employeeType' => 'employeeType',
'extendedAttributes' => [
'attr1' => [
'value1',
'value2',
],
],
'firstName' => 'firstName',
'lastName' => 'lastName',
'domain' => 'domain',
'domainUsername' => 'domainUsername',
'telephoneNumber' => 'telephoneNumber',
'locale' => 'locale',
'assuranceLevel' => 'assuranceLevel',
'assuranceLevel' => '40',
'uid' => 'uid',
'orgId' => 'orgId',
'teleworkingPriority' => 'teleworkingPriority',
'groups' => [
'foo',
'group1',
'group2',
],
'strengths' => [
'bar',
],
'authenticationFactors' => [
'foobar',
'ecphp@ec.europa.eu',
],
'loginDate' => 'loginDate',
'sso' => 'sso',
......
......@@ -6,9 +6,6 @@ namespace EcPhp\EuLoginBundle\Security\Core\User;
use EcPhp\CasBundle\Security\Core\User\CasUserInterface;
use function array_key_exists;
use function is_array;
final class EuLoginUser implements EuLoginUserInterface
{
/**
......@@ -16,9 +13,6 @@ final class EuLoginUser implements EuLoginUserInterface
*/
private $user;
/**
* EuLoginUser constructor.
*/
public function __construct(CasUserInterface $user)
{
$this->user = $user;
......@@ -61,7 +55,10 @@ final class EuLoginUser implements EuLoginUserInterface
*/
public function getAttributes(): array
{
return $this->user->getAttributes();
$attributes = $this->user->getAttributes();
$attributes['extendedAttributes'] = $this->getExtendedAttributes();
return $attributes;
}
/**
......@@ -120,6 +117,19 @@ final class EuLoginUser implements EuLoginUserInterface
return $this->user->getAttribute('employeeType');
}
public function getExtendedAttributes(): array
{
return array_reduce(
$this->user->getAttribute('extendedAttributes', []),
static function (array $carry, array $item): array {
$carry[$item['@attributes']['name']] = $item['attributeValue'];
return $carry;
},
[]
);
}
/**
* {@inheritdoc}
*/
......@@ -133,7 +143,7 @@ final class EuLoginUser implements EuLoginUserInterface
*/
public function getGroups(): array
{
return $this->user->getAttribute('groups', []);
return $this->user->getAttribute('groups', ['group' => []])['group'];
}
/**
......@@ -191,11 +201,7 @@ final class EuLoginUser implements EuLoginUserInterface
{
$default = ['ROLE_CAS_AUTHENTICATED'];
if (([] !== $roles = $this->getGroups()) && (array_key_exists('group', $roles) && is_array($roles['group']))) {
return array_merge($roles['group'], $default);
}
return $default;
return array_merge($this->getGroups(), $default);
}
/**
......
......@@ -27,6 +27,8 @@ interface EuLoginUserInterface extends CasUserInterface
public function getEmployeeType(): ?string;
public function getExtendedAttributes(): array;
public function getFirstName(): ?string;
/**
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment