Fix groups members and filtering

Fixes issue #1
This commit is contained in:
Julien Schneider 2023-01-02 15:33:24 +01:00
parent f4a10277b0
commit 3a277bae44
8 changed files with 86 additions and 21 deletions

View file

@ -31,7 +31,9 @@ class MockGroupAdapter extends AbstractAdapter
$coreGroupMembers = [];
foreach ($mockGroup->getMembers() as $mockGroupMember) {
$coreGroupMember = new MultiValuedAttribute();
$coreGroupMember->setValue($mockGroupMember);
$coreGroupMember->setValue($mockGroupMember->getValue());
$coreGroupMember->setDisplay($mockGroupMember->getDisplay());
$coreGroupMember->setRef($mockGroupMember->getRef());
$coreGroupMembers[] = $coreGroupMember;
}
@ -60,12 +62,15 @@ class MockGroupAdapter extends AbstractAdapter
if ($coreGroup->getMembers() !== null && !empty($coreGroup->getMembers())) {
$mockGroupMembers = [];
foreach ($coreGroup->getMembers() as $coreGroupMember) {
$mockGroupMembers[] = $coreGroupMember->getValue();
$mockGroupMember = new MultiValuedAttribute();
$mockGroupMember->setValue($coreGroupMember->getValue());
$mockGroupMember->setDisplay($coreGroupMember->getDisplay());
$mockGroupMember->setRef($coreGroupMember->getRef());
$mockGroupMembers[] = $mockGroupMember;
}
$mockGroup->setMembers($mockGroupMembers);
}
return $mockGroup;
}
}

View file

@ -109,8 +109,10 @@ class MockGroupDataAccess
$insertRes = $insertStatement->execute([
$groupToCreate->getId(),
$groupToCreate->getDisplayName(),
// we serialize the whole members array and store it as is in the database
// this is relatively dirty, but fine enough for a mock group implementation
$groupToCreate->getMembers() !== null && !empty($groupToCreate->getMembers())
? $groupToCreate->getMembers() : "",
? serialize($groupToCreate->getMembers()) : "",
$dateNow,
$dateNow
]);
@ -149,7 +151,7 @@ class MockGroupDataAccess
$query = $query . "members = ?, ";
// We need to transform the string array of user IDs to a single string
$values[] = implode(",", $groupToUpdate->getMembers());
$values[] = serialize($groupToUpdate->getMembers());
}
if (empty($query)) {

View file

@ -7,7 +7,7 @@ class MockGroup extends MockCommonEntity
/** @var string|null $displayName */
private $displayName;
/** @var array<string>|null $members */
/** @var \Opf\Models\SCIM\MultiValuedAttribute|null $members */
private $members;
public function mapFromArray($properties = null): bool
@ -36,7 +36,8 @@ class MockGroup extends MockCommonEntity
}
if (strcasecmp($key, 'members') === 0) {
$this->members = $value;
// the members array is stored as a serialized array in the DB
$this->members = unserialize($value);
continue;
}
$result = false;

View file

@ -62,7 +62,9 @@ class CoreGroup extends CommonEntity
$members = [];
foreach ($data['members'] as $member) {
$scimMember = new MultiValuedAttribute();
$scimMember->setValue($member);
$scimMember->setValue($member['value']);
$scimMember->setDisplay($member['display']);
$scimMember->setRef($member['$ref']);
$members[] = $scimMember;
}
$this->setMembers($members);

View file

@ -2,6 +2,7 @@
namespace Opf\Util\Filters;
use Attribute;
use Opf\Models\SCIM\Standard\Filters\AttributeExpression;
use Opf\Models\SCIM\Standard\Filters\FilterException;
use Opf\Models\SCIM\Standard\Filters\FilterExpression;
@ -24,16 +25,35 @@ class FilterParser
);
}
$splitFilterExpression = explode(" ", $filterExpression);
if (count($splitFilterExpression) < 2 || count($splitFilterExpression) > 3) {
$splitAttributePathFromFilterExpression = explode(" ", $filterExpression, 2);
if (!isset($splitAttributePathFromFilterExpression[1]) || empty($splitAttributePathFromFilterExpression[1])) {
throw new FilterException("Incorrectly formatted AttributeExpression");
} else if (strcmp($splitAttributePathFromFilterExpression[1], "pr") === 0) {
$attributeExpression = new AttributeExpression(
$splitAttributePathFromFilterExpression[0], // The attribute path
"pr", // The comparison operator (which must be "pr" in this case)
null // The comparison value (must be null due to "pr")
);
} else {
$splitFilterExpressionWithoutAttributePath = explode(" ", $splitAttributePathFromFilterExpression[1], 2);
$attributeExpression = new AttributeExpression(
$splitAttributePathFromFilterExpression[0], // The attribute path
$splitFilterExpressionWithoutAttributePath[0], // The comparison operator (which is different from "pr")
$splitFilterExpressionWithoutAttributePath[1] // The comparison value (can contain spaces)
);
}
$attributeExpression = new AttributeExpression(
$splitFilterExpression[0],
$splitFilterExpression[1],
$splitFilterExpression[2]
);
// if (count($splitFilterExpression) < 2 || count($splitFilterExpression) > 3) {
// throw new FilterException("Incorrectly formatted AttributeExpression");
// }
// $attributeExpression = new AttributeExpression(
// $splitFilterExpression[0],
// $splitFilterExpression[1],
// $splitFilterExpression[2]
// );
return $attributeExpression;
}

View file

@ -15,5 +15,10 @@
"userName": "testuser3",
"externalId": "testuser3external",
"profileUrl": "http://example.com/testuser3"
},
{
"userName": "some user",
"externalId": "testsome_userexternal",
"profileUrl": "http://example.com/some_user"
}
]

View file

@ -46,12 +46,25 @@ final class FilterParserTest extends TestCase
$parsedFilterExpression = FilterParser::parseFilterExpression($filterString);
}
public function testParseTooLongFilterExpression()
public function testFilterExpressionWithSpacesInValue()
{
$filterString = "userName eq \"some value\"";
$parsedFilterExpression = FilterParser::parseFilterExpression($filterString);
$this->assertInstanceOf(FilterExpression::class, $parsedFilterExpression);
$this->assertInstanceOf(AttributeExpression::class, $parsedFilterExpression);
$this->assertEquals("userName", $parsedFilterExpression->getAttributePath());
$this->assertEquals(AttributeOperator::OP_EQ, $parsedFilterExpression->getCompareOperator());
$this->assertEquals("\"some value\"", $parsedFilterExpression->getComparisonValue());
}
public function testParseIncorrectExpression()
{
$this->expectException(FilterException::class);
$this->expectExceptionMessage("Incorrectly formatted AttributeExpression");
$this->expectExceptionMessage("Invalid AttributeOperation passed to AttributeExpression");
$filterString = "userName eq some value";
$filterString = "userName blabla \"some moreblabla\"";
$parsedFilterExpression = FilterParser::parseFilterExpression($filterString);
}
}

View file

@ -42,15 +42,32 @@ final class FilterUtilTest extends TestCase
$filterString = "userName sw testuser";
$filteredScimUsers = FilterUtil::performFiltering($filterString, $this->scimUsers);
$this->assertEquals($this->scimUsers, $filteredScimUsers);
$this->assertEquals(array_splice($this->scimUsers, 0, 3), $filteredScimUsers);
}
public function testInvalidFiltering()
{
$this->expectException(FilterException::class);
$this->expectExceptionMessage("Incorrectly formatted AttributeExpression");
$this->expectExceptionMessage("Invalid AttributeOperation passed to AttributeExpression");
$filterString = "externalId eq some value";
$filterString = "externalId bla some value";
$filteredScimUsers = FilterUtil::performFiltering($filterString, $this->scimUsers);
}
public function testFilteringWithSpaces()
{
$filterString = "userName eq some user";
$filteredScimUsers = FilterUtil::performFiltering($filterString, $this->scimUsers);
$this->assertEquals(array($this->scimUsers[3]), $filteredScimUsers);
}
public function testIncorrectPRFilterExpression()
{
$this->expectException(FilterException::class);
$this->expectExceptionMessage("\"pr\" filter operator must be used without a comparison value");
$filterString = "userName pr \"some blabla\"";
$parsedFilterExpression = FilterUtil::performFiltering($filterString, $this->scimUsers);
}
}