diff --git a/invenio_users_resources/services/users/config.py b/invenio_users_resources/services/users/config.py index 5542d5e..2b8d00e 100644 --- a/invenio_users_resources/services/users/config.py +++ b/invenio_users_resources/services/users/config.py @@ -2,6 +2,7 @@ # # Copyright (C) 2022 TU Wien. # Copyright (C) 2022 CERN. +# Copyright (C) 2024 KTH Royal Institute of Technology. # # Invenio-Users-Resources is free software; you can redistribute it and/or # modify it under the terms of the MIT License; see LICENSE file for more @@ -192,12 +193,14 @@ class UsersServiceConfig(RecordServiceConfig, ConfiguratorMixin): links_item = { "self": Link("{+api}/users/{id}"), "avatar": Link("{+api}/users/{id}/avatar.svg"), - "records_html": Link("{+ui}/search/records?q=user:{id}"), + "records_html": Link("{+ui}/search/records?q=parent.access.owned_by.user:{id}"), "admin_records_html": Link( - "{+ui}/administration/records?q=user:{id}&f=allversions", when=can_manage + "{+ui}/administration/records?q=parent.access.owned_by.user:{id}&f=allversions", + when=can_manage, ), "admin_drafts_html": Link( - "{+ui}/administration/drafts?q=user:{id}&f=allversions", when=can_manage + "{+ui}/administration/drafts?q=parent.access.owned_by.user:{id}&f=allversions", + when=can_manage, ), "admin_moderation_html": Link( "{+ui}/administration/moderation?q=topic.user:{id}", when=can_manage diff --git a/tests/resources/test_resources_users.py b/tests/resources/test_resources_users.py index 30c456c..78db21a 100644 --- a/tests/resources/test_resources_users.py +++ b/tests/resources/test_resources_users.py @@ -2,6 +2,7 @@ # # Copyright (C) 2022 European Union. # Copyright (C) 2022 CERN. +# Copyright (C) 2024 KTH Royal Institute of Technology. # # Invenio-Users-Resources is free software; you can redistribute it and/or # modify it under the terms of the MIT License; see LICENSE file for more @@ -56,7 +57,7 @@ def test_read_self_serialization(client, headers, users, user_pub): assert data["links"] == { "self": f"https://127.0.0.1:5000/api/users/{user_pub.id}", "avatar": f"https://127.0.0.1:5000/api/users/{user_pub.id}/avatar.svg", - "records_html": f"https://127.0.0.1:5000/search/records?q=user:{user_pub.id}", + "records_html": f"https://127.0.0.1:5000/search/records?q=parent.access.owned_by.user:{user_pub.id}", } @@ -87,7 +88,7 @@ def test_read_anon_serialization(client, headers, users, username, public_email) assert data["links"] == { "self": f"https://127.0.0.1:5000/api/users/{u.id}", "avatar": f"https://127.0.0.1:5000/api/users/{u.id}/avatar.svg", - "records_html": f"https://127.0.0.1:5000/search/records?q=user:{u.id}", + "records_html": f"https://127.0.0.1:5000/search/records?q=parent.access.owned_by.user:{u.id}", } for k in [ @@ -182,6 +183,61 @@ def test_impersonate_user(client, headers, user_pub, user_moderator, db): assert res.status_code == 403 +@pytest.mark.parametrize( + "link_name,expected_url", + [ + ( + "admin_records_html", + "/administration/records?q=parent.access.owned_by.user:{id}&f=allversions", + ), + ( + "admin_drafts_html", + "/administration/drafts?q=parent.access.owned_by.user:{id}&f=allversions", + ), + ("admin_moderation_html", "/administration/moderation?q=topic.user:{id}"), + ], +) +def test_admin_links( + client, headers, user_moderator, user_pub, link_name, expected_url +): + """Test admin links.""" + client = user_moderator.login(client) + res = client.get(f"/users/{user_pub.id}", headers=headers) + assert res.status_code == 200 + data = res.json + assert link_name in data["links"] + assert ( + data["links"][link_name] + == f"https://127.0.0.1:5000{expected_url.format(id=user_pub.id)}" + ) + + +@pytest.mark.parametrize( + "username,expected_admin_links", + [ + ("user_moderator", True), # user_moderator should have admin links + ("pub", False), # regular user should not have admin links + ("res", False), # regular user should not have admin links + ], +) +def test_admin_links_visibility(client, headers, users, username, expected_admin_links): + """Test admin links visibility based on user permissions.""" + user = users[username] + client = user.login(client) + res = client.get(f"/users/{user.id}", headers=headers) + assert res.status_code == 200 + data = res.json + + if expected_admin_links: + assert "admin_records_html" in data["links"] + assert "admin_drafts_html" in data["links"] + assert "admin_moderation_html" in data["links"] + else: + assert "admin_records_html" not in data["links"] + assert "admin_drafts_html" not in data["links"] + assert "admin_moderation_html" not in data["links"] + + # TODO: test conditional requests # TODO: test caching headers # TODO: test invalid identifiers