Skip to content

Commit

Permalink
Merge pull request #714 from SUNET/lundberg_scim_search_attrib_fix
Browse files Browse the repository at this point in the history
SCIM search attrib fix
  • Loading branch information
helylle authored Nov 18, 2024
2 parents 7f7123b + 76f3197 commit 6852018
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 5 deletions.
18 changes: 15 additions & 3 deletions src/eduid/scimapi/routers/utils/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,21 @@ def acceptable_linked_accounts(value: list[LinkedAccount], environment: EduidEnv


def users_to_resources_dicts(query: SearchRequest, users: Sequence[ScimApiUser]) -> list[dict[str, Any]]:
_attributes = query.attributes
# TODO: include the requested attributes, not just id
return [{"id": str(user.scim_id)} for user in users]
resources = []
for user in users:
resource: dict[str, Any] = {"id": str(user.scim_id)}
if query.attributes:
# TODO: this is a hack to get some attributes we need
if "givenName" in query.attributes:
resource["givenName"] = user.name.given_name
if "familyName" in query.attributes:
resource["familyName"] = user.name.family_name
if "formatted" in query.attributes:
resource["formatted"] = user.name.formatted
if "externalId" in query.attributes:
resource["externalId"] = user.external_id
resources.append(resource)
return resources


def filter_externalid(req: ContextRequest, search_filter: SearchFilter) -> list[ScimApiUser]:
Expand Down
9 changes: 8 additions & 1 deletion src/eduid/scimapi/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,15 @@ def add_user(
external_id: str | None = None,
profiles: dict[str, ScimApiProfile] | None = None,
linked_accounts: list[ScimApiLinkedAccount] | None = None,
name: ScimApiName | None = None,
) -> ScimApiUser:
user = ScimApiUser(user_id=ObjectId(), scim_id=uuid.UUID(identifier), external_id=external_id)
user = ScimApiUser(
user_id=ObjectId(),
scim_id=uuid.UUID(identifier),
external_id=external_id,
)
if name is not None:
user.name = name
if profiles:
for key, value in profiles.items():
user.profiles[key] = value
Expand Down
41 changes: 40 additions & 1 deletion src/eduid/scimapi/tests/test_scimuser.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from eduid.common.utils import make_etag
from eduid.scimapi.testing import ScimApiTestCase
from eduid.scimapi.utils import filter_none
from eduid.userdb.scimapi import EventStatus, ScimApiGroup, ScimApiLinkedAccount
from eduid.userdb.scimapi import EventStatus, ScimApiGroup, ScimApiLinkedAccount, ScimApiName
from eduid.userdb.scimapi.userdb import ScimApiProfile, ScimApiUser

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -606,6 +606,42 @@ def test_search_user_external_id(self) -> None:
self.add_user(identifier=str(uuid4()), external_id="test-id-2", profiles={"test": self.test_profile})
self._perform_search(search_filter=f'externalId eq "{db_user.external_id}"', expected_user=db_user)

def test_search_user_external_id_with_attributes(self) -> None:
attributes = ["givenName", "familyName", "formatted", "externalId"]
db_user = self.add_user(
identifier=str(uuid4()),
external_id="test-id-1",
profiles={"test": self.test_profile},
name=ScimApiName(family_name="Test", given_name="User", formatted="Test User"),
)
self.add_user(identifier=str(uuid4()), external_id="test-id-2", profiles={"test": self.test_profile})
resources = self._perform_search(
search_filter=f'externalId eq "{db_user.external_id}"',
expected_user=db_user,
attributes=attributes,
)
for resource in resources:
for attrib in attributes:
assert attrib in resource
assert resource[attrib] is not None

def test_search_user_external_id_with_none_attributes(self) -> None:
attributes = ["givenName", "familyName", "formatted", "externalId"]
db_user = self.add_user(
identifier=str(uuid4()),
external_id="test-id-1",
profiles={"test": self.test_profile},
name=ScimApiName(family_name="Test", given_name="User"),
)
self.add_user(identifier=str(uuid4()), external_id="test-id-2", profiles={"test": self.test_profile})
resources = self._perform_search(
search_filter=f'externalId eq "{db_user.external_id}"',
expected_user=db_user,
attributes=attributes,
)
for resource in resources:
assert resource["formatted"] is None

def test_search_user_last_modified(self) -> None:
db_user1 = self.add_user(identifier=str(uuid4()), external_id="test-id-1", profiles={"test": self.test_profile})
db_user2 = self.add_user(identifier=str(uuid4()), external_id="test-id-2", profiles={"test": self.test_profile})
Expand Down Expand Up @@ -772,6 +808,7 @@ def _perform_search(
search_filter: str,
start: int = 1,
count: int = 10,
attributes: list[str] | None = None,
return_json: bool = False,
expected_user: ScimApiUser | None = None,
expected_num_resources: int | None = None,
Expand All @@ -784,6 +821,8 @@ def _perform_search(
"startIndex": start,
"count": count,
}
if attributes is not None:
req["attributes"] = attributes
response = self.client.post(url="/Users/.search", json=req, headers=self.headers)
logger.info(f"Search parsed_response:\n{response.json()}")
if return_json:
Expand Down

0 comments on commit 6852018

Please sign in to comment.