diff --git a/composer.json b/composer.json
index 6a007d5..947b0b9 100644
--- a/composer.json
+++ b/composer.json
@@ -21,11 +21,11 @@
"symfony/framework-bundle": "^5.1"
},
"require-dev": {
- "drupol/php-conventions": "^1.8.16",
+ "drupol/php-conventions": "^1.8.18",
"friends-of-phpspec/phpspec-code-coverage": "^4.3.2",
"infection/infection": "^0.15.3",
"phpspec/phpspec": "^6.2.1",
- "vimeo/psalm": "^3.13"
+ "vimeo/psalm": "^3.14"
},
"autoload": {
"psr-4": {
diff --git a/spec/EcPhp/EuLoginBundle/Security/Core/User/EuLoginUserProviderSpec.php b/spec/EcPhp/EuLoginBundle/Security/Core/User/EuLoginUserProviderSpec.php
index 9b7ac89..e1bb829 100644
--- a/spec/EcPhp/EuLoginBundle/Security/Core/User/EuLoginUserProviderSpec.php
+++ b/spec/EcPhp/EuLoginBundle/Security/Core/User/EuLoginUserProviderSpec.php
@@ -10,8 +10,8 @@
use EcPhp\EuLoginBundle\Security\Core\User\EuLoginUser;
use EcPhp\EuLoginBundle\Security\Core\User\EuLoginUserInterface;
use EcPhp\EuLoginBundle\Security\Core\User\EuLoginUserProvider;
+use Nyholm\Psr7\Response;
use PhpSpec\ObjectBehavior;
-use Psr\Http\Message\ResponseInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\User;
@@ -28,93 +28,200 @@ public function it_can_check_if_the_user_class_is_supported()
->shouldReturn(false);
}
- public function it_can_load_a_user_from_a_response(ResponseInterface $response)
+ public function it_can_load_a_user_from_a_response(): void
{
- $response
- ->getStatusCode()
- ->willReturn(200);
-
- $response
- ->hasHeader('Content-Type')
- ->willReturn(true);
-
- $response
- ->getHeaderLine('Content-Type')
- ->willReturn('application/xml');
-
- $body = <<<'EOF'
-
-
- username
- bar
-
- foo
-
-
- group1
- group2
-
-
-
- rex
- snoopy
-
-
-
-
-EOF;
+ // TestBody1
+ $response = new Response(200, ['content-type' => 'application/xml'], $this->getTestBody1());
- $response
- ->getBody()
- ->willReturn($body);
-
- $this
- ->loadUserByResponse($response)
- ->shouldReturnAnInstanceOf(EuLoginUser::class);
+ $user = $this->loadUserByResponse($response);
- $this
- ->loadUserByResponse($response)
+ $user
->getAttributes()
- ->shouldEqual([
- 'foo' => 'bar',
- 'groups' => [
- 'group' => [
- 'group1',
- 'group2',
+ ->shouldReturn(
+ [
+ 'departmentNumber' => 'departmentNumber',
+ 'email' => 'email',
+ 'employeeNumber' => 'employeeNumber',
+ 'employeeType' => 'employeeType',
+ 'firstName' => 'firstName',
+ 'lastName' => 'lastName',
+ 'domain' => 'domain',
+ 'domainUsername' => 'domainUsername',
+ 'telephoneNumber' => 'telephoneNumber',
+ 'userManager' => 'userManager',
+ 'timeZone' => 'timeZone',
+ 'locale' => 'locale',
+ 'assuranceLevel' => 'assuranceLevel',
+ 'uid' => 'uid',
+ 'orgId' => 'orgId',
+ 'teleworkingPriority' => 'teleworkingPriority',
+ 'extendedAttributes' => [
+ 'extendedAttribute' => [
+ [
+ 'attributeValue' => [
+ 'value1',
+ 'value2',
+ ],
+ '@attributes' => [
+ 'name' => 'extendedAttribute1',
+ ],
+ ],
+ [
+ 'attributeValue' => [
+ 'value3',
+ 'value4',
+ ],
+ '@attributes' => [
+ 'name' => 'extendedAttribute2',
+ ],
+ ],
+ ],
],
- ],
- 'extendedAttributes' => [
- 'http://stork.eu/motherInLawDogName' => [
- 'rex',
- 'snoopy',
+ 'groups' => [
+ 'group' => [
+ 'group1',
+ 'group2',
+ ],
+ '@attributes' => [
+ 'number' => '2',
+ ],
+ ],
+ 'strengths' => [
+ 'strength' => [
+ 'strength1',
+ 'strength2',
+ ],
+ '@attributes' => [
+ 'number' => '2',
+ ],
+ ],
+ 'authenticationFactors' => [
+ 'moniker' => 'moniker1',
+ '@attributes' => [
+ 'number' => '1',
+ ],
],
+ 'loginDate' => '',
+ 'sso' => 'sso',
+ 'ticketType' => 'ticketType',
+ 'proxyGrantingProtocol' => 'proxyGrantingProtocol',
+ ]
+ );
+
+ $user
+ ->getExtendedAttributes()
+ ->shouldReturn([
+ 'extendedAttribute1' => [
+ 'value1',
+ 'value2',
+ ],
+ 'extendedAttribute2' => [
+ 'value3',
+ 'value4',
],
]);
- $this
- ->loadUserByResponse($response)
- ->getUsername()
- ->shouldReturn('username');
-
- $this
- ->loadUserByResponse($response)
- ->getRoles()
+ $user
+ ->getGroups()
->shouldReturn([
'group1',
'group2',
- 'ROLE_CAS_AUTHENTICATED',
]);
- $this->loadUserByResponse($response)
- ->getExtendedAttributes()
+ $user
+ ->getStrengths()
+ ->shouldReturn([
+ 'strength1',
+ 'strength2',
+ ]);
+
+ // TestBody2
+ $response = new Response(200, ['content-type' => 'application/xml'], $this->getTestBody2());
+
+ $user = $this->loadUserByResponse($response);
+
+ $user
+ ->getAttributes()
->shouldReturn(
[
- 'http://stork.eu/motherInLawDogName' => [
- 'rex',
- 'snoopy',
+ 'departmentNumber' => 'departmentNumber',
+ 'email' => 'email',
+ 'employeeNumber' => 'employeeNumber',
+ 'employeeType' => 'employeeType',
+ 'firstName' => 'firstName',
+ 'lastName' => 'lastName',
+ 'domain' => 'domain',
+ 'domainUsername' => 'domainUsername',
+ 'telephoneNumber' => 'telephoneNumber',
+ 'userManager' => 'userManager',
+ 'timeZone' => 'timeZone',
+ 'locale' => 'locale',
+ 'assuranceLevel' => 'assuranceLevel',
+ 'uid' => 'uid',
+ 'orgId' => 'orgId',
+ 'teleworkingPriority' => 'teleworkingPriority',
+ 'extendedAttributes' => [
+ 'extendedAttribute' => [
+ [
+ 'attributeValue' => [
+ 'value1',
+ 'value2',
+ ],
+ '@attributes' => [
+ 'name' => 'extendedAttribute1',
+ ],
+ ],
+ ],
],
+ 'groups' => [
+ 'group' => [
+ 'group1',
+ ],
+ '@attributes' => [
+ 'number' => '1',
+ ],
+ ],
+ 'strengths' => [
+ 'strength' => [
+ 'strength1',
+ ],
+ '@attributes' => [
+ 'number' => '1',
+ ],
+ ],
+ 'authenticationFactors' => [
+ 'moniker' => 'moniker1',
+ '@attributes' => [
+ 'number' => '1',
+ ],
+ ],
+ 'loginDate' => '',
+ 'sso' => 'sso',
+ 'ticketType' => 'ticketType',
+ 'proxyGrantingProtocol' => 'proxyGrantingProtocol',
]
);
+
+ $user
+ ->getExtendedAttributes()
+ ->shouldReturn([
+ 'extendedAttribute1' => [
+ 'value1',
+ 'value2',
+ ],
+ ]);
+
+ $user
+ ->getGroups()
+ ->shouldReturn([
+ 'group1',
+ ]);
+
+ $user
+ ->getStrengths()
+ ->shouldReturn([
+ 'strength1',
+ ]);
}
public function it_can_refresh_a_user(EuLoginUserInterface $user)
@@ -145,4 +252,110 @@ public function let()
$this
->beConstructedWith(new CasUserProvider(new EcasIntrospector(new Introspector())));
}
+
+ private function getTestBody1()
+ {
+ return <<< 'EOF'
+
+
+
+ username
+ departmentNumber
+ email
+ employeeNumber
+ employeeType
+ firstName
+ lastName
+ domain
+ domainUsername
+ telephoneNumber
+ userManager
+ timeZone
+ locale
+ assuranceLevel
+ uid
+ orgId
+ teleworkingPriority
+
+
+ value1
+ value2
+
+
+ value3
+ value4
+
+
+
+ group1
+ group2
+
+
+ strength1
+ strength2
+
+
+ moniker1
+
+
+ sso
+ ticketType
+ proxyGrantingProtocol
+
+ proxy1
+
+
+
+EOF;
+ }
+
+ private function getTestBody2()
+ {
+ return <<< 'EOF'
+
+
+
+ username
+ departmentNumber
+ email
+ employeeNumber
+ employeeType
+ firstName
+ lastName
+ domain
+ domainUsername
+ telephoneNumber
+ userManager
+ timeZone
+ locale
+ assuranceLevel
+ uid
+ orgId
+ teleworkingPriority
+
+
+ value1
+ value2
+
+
+
+ group1
+
+
+ strength1
+
+
+ moniker1
+
+
+ sso
+ ticketType
+ proxyGrantingProtocol
+
+ proxy1
+
+
+
+EOF;
+ }
}
diff --git a/spec/EcPhp/EuLoginBundle/Security/Core/User/EuLoginUserSpec.php b/spec/EcPhp/EuLoginBundle/Security/Core/User/EuLoginUserSpec.php
index de55069..63e32be 100644
--- a/spec/EcPhp/EuLoginBundle/Security/Core/User/EuLoginUserSpec.php
+++ b/spec/EcPhp/EuLoginBundle/Security/Core/User/EuLoginUserSpec.php
@@ -24,10 +24,7 @@ public function it_can_get_groups_when_no_groups_are_available()
foo
-
- group1
- group2
-
+
rex
@@ -41,7 +38,6 @@ public function it_can_get_groups_when_no_groups_are_available()
$response = new Response(200, ['Content-Type' => 'application/xml'], $body);
$data = (new Introspector())->parse($response)['serviceResponse']['authenticationSuccess'];
- unset($data['attributes']['groups']);
$casUser = new CasUser($data);
@@ -203,7 +199,7 @@ public function let(CasUserInterface $user)
40
-
+
group1
group2
@@ -218,7 +214,7 @@ public function let(CasUserInterface $user)
EOF;
- $response = new Response(200, ['Content-Type' => 'application/json'], $body);
+ $response = new Response(200, ['Content-Type' => 'application/xml'], $body);
$data = (new Introspector())->parse($response)['serviceResponse']['authenticationSuccess'];
$user
@@ -362,9 +358,13 @@ private function getAttributesData(): array
'employeeNumber' => 'employeeNumber',
'employeeType' => 'employeeType',
'extendedAttributes' => [
- 'attr1' => [
- 'value1',
- 'value2',
+ 'extendedAttribute' => [
+ [
+ 'attr1' => [
+ 'value1',
+ 'value2',
+ ],
+ ],
],
],
'firstName' => 'firstName',
@@ -378,11 +378,15 @@ private function getAttributesData(): array
'orgId' => 'orgId',
'teleworkingPriority' => 'teleworkingPriority',
'groups' => [
- 'group1',
- 'group2',
+ 'group' => [
+ 'group1',
+ 'group2',
+ ],
],
'strengths' => [
- 'bar',
+ 'strength' => [
+ 'bar',
+ ],
],
'authenticationFactors' => [
'ecphp@ec.europa.eu',
diff --git a/src/Security/Core/User/EuLoginUser.php b/src/Security/Core/User/EuLoginUser.php
index 47fcca1..3864a4f 100644
--- a/src/Security/Core/User/EuLoginUser.php
+++ b/src/Security/Core/User/EuLoginUser.php
@@ -6,6 +6,8 @@
use EcPhp\CasBundle\Security\Core\User\CasUserInterface;
+use function array_key_exists;
+
final class EuLoginUser implements EuLoginUserInterface
{
/**
@@ -56,7 +58,32 @@ public function getAttribute(string $key, $default = null)
public function getAttributes(): array
{
$attributes = $this->user->getAttributes();
- $attributes['extendedAttributes'] = $this->getExtendedAttributes();
+
+ /** @Todo Ugly. Refactor this when JSON format will be available. */
+ $propertyToMangle = [
+ ['extendedAttributes', 'extendedAttribute'],
+ ['groups', 'group'],
+ ['strengths', 'strength'],
+ ['authenticationFactors', 'authenticationFactor'],
+ ];
+
+ foreach ($propertyToMangle as [$parent, $child]) {
+ if (!array_key_exists($parent, $attributes)) {
+ continue;
+ }
+
+ if (!array_key_exists($child, $attributes[$parent])) {
+ continue;
+ }
+
+ $attributes[$parent][$child] = (array) $attributes[$parent][$child];
+
+ if (array_key_exists(0, $attributes[$parent][$child])) {
+ continue;
+ }
+
+ $attributes[$parent][$child] = [$attributes[$parent][$child]];
+ }
return $attributes;
}
@@ -119,8 +146,22 @@ public function getEmployeeType(): ?string
public function getExtendedAttributes(): array
{
+ $attributes = $this->getAttributes();
+
+ if (!array_key_exists('extendedAttributes', $attributes)) {
+ return [];
+ }
+
+ $extendedAttributes = $attributes['extendedAttributes'];
+
+ if (!array_key_exists('extendedAttribute', $extendedAttributes)) {
+ return [];
+ }
+
+ $extendedAttributes = $attributes['extendedAttributes']['extendedAttribute'];
+
return array_reduce(
- $this->user->getAttribute('extendedAttributes', []),
+ $extendedAttributes,
static function (array $carry, array $item): array {
$carry[$item['@attributes']['name']] = $item['attributeValue'];
@@ -143,7 +184,19 @@ public function getFirstName(): ?string
*/
public function getGroups(): array
{
- return $this->user->getAttribute('groups', ['group' => []])['group'];
+ $attributes = $this->getAttributes();
+
+ if (!array_key_exists('groups', $attributes)) {
+ return [];
+ }
+
+ $groups = $attributes['groups'];
+
+ if (!array_key_exists('group', $groups)) {
+ return [];
+ }
+
+ return $groups['group'];
}
/**
@@ -225,7 +278,19 @@ public function getSso(): ?string
*/
public function getStrengths(): array
{
- return $this->user->getAttribute('strengths', []);
+ $attributes = $this->getAttributes();
+
+ if (!array_key_exists('strengths', $attributes)) {
+ return [];
+ }
+
+ $strengths = $attributes['strengths'];
+
+ if (!array_key_exists('strength', $strengths)) {
+ return [];
+ }
+
+ return (array) $strengths['strength'];
}
/**