From d346b1c3392e449de598509c5cb06bed9a09a9d0 Mon Sep 17 00:00:00 2001 From: Anton Krytskyi Date: Thu, 26 Jun 2025 18:14:06 +0300 Subject: [PATCH 1/3] add scope for POST collection search --- api/search/views.py | 1 + api_tests/search/views/test_views.py | 23 +++++++++++++++++++++++ framework/auth/oauth_scopes.py | 5 ++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/api/search/views.py b/api/search/views.py index 2af2afd79a3..e024cb38550 100644 --- a/api/search/views.py +++ b/api/search/views.py @@ -656,6 +656,7 @@ class SearchCollections(BaseSearchView): doc_type = 'collectionSubmission' view_category = 'search' view_name = 'search-collected-metadata' + required_write_scopes = [CoreScopes.SEARCH_COLLECTIONS_WRITE] @property def search_fields(self): diff --git a/api_tests/search/views/test_views.py b/api_tests/search/views/test_views.py index 675381668dc..5259e76d6ed 100644 --- a/api_tests/search/views/test_views.py +++ b/api_tests/search/views/test_views.py @@ -1,8 +1,10 @@ import pytest import uuid +from unittest import mock from api.base.settings.defaults import API_BASE from api_tests import utils +from framework.auth.cas import CasResponse from framework.auth.core import Auth from osf.models import RegistrationSchema from osf_tests.factories import ( @@ -1025,3 +1027,24 @@ def test_POST_search_collections_disease_data_type( assert res.status_code == 200 assert res.json['links']['meta']['total'] == 2 assert len(res.json['data']) == 2 + + def test_POST_search_collections_scope(self, app, url_collection_search, user): + payload = self.post_payload(q='Collection') + + token_invalid = CasResponse( + authenticated=True, + user=user._id, + attributes={'accessTokenScope': ['osf.full_read']} + ) + with mock.patch('framework.auth.cas.CasClient.profile', return_value=token_invalid): + res = app.post_json_api(url_collection_search, payload, auth='some-invalid-token', expect_errors=True, auth_type='jwt') + assert res.status_code == 403 + + token_valid = CasResponse( + authenticated=True, + user=user._id, + attributes={'accessTokenScope': ['osf.full_read', 'osf.full_write']} + ) + with mock.patch('framework.auth.cas.CasClient.profile', return_value=token_valid): + res = app.post_json_api(url_collection_search, payload, auth='some-valid-token', auth_type='jwt') + assert res.status_code == 200 diff --git a/framework/auth/oauth_scopes.py b/framework/auth/oauth_scopes.py index 65811b9a981..8f859319717 100644 --- a/framework/auth/oauth_scopes.py +++ b/framework/auth/oauth_scopes.py @@ -210,6 +210,8 @@ class CoreScopes: READ_COLLECTION_SUBMISSION = 'read_collection_submission' WRITE_COLLECTION_SUBMISSION = 'write_collection_submission' + SEARCH_COLLECTIONS_WRITE = 'search_collections_write' + class ComposedScopes: """ @@ -370,7 +372,8 @@ class ComposedScopes: CoreScopes.CEDAR_METADATA_RECORD_WRITE, CoreScopes.WRITE_COLLECTION_SUBMISSION_ACTION, CoreScopes.WRITE_COLLECTION_SUBMISSION, - CoreScopes.USERS_MESSAGE_WRITE_EMAIL + CoreScopes.USERS_MESSAGE_WRITE_EMAIL, + CoreScopes.SEARCH_COLLECTIONS_WRITE ) # Admin permissions- includes functionality not intended for third-party use From 657de787824a0558e2350264a4f131add634567b Mon Sep 17 00:00:00 2001 From: Anton Krytskyi Date: Fri, 27 Jun 2025 11:23:28 +0300 Subject: [PATCH 2/3] rename scope --- api/search/views.py | 2 +- framework/auth/oauth_scopes.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/search/views.py b/api/search/views.py index e024cb38550..958c5907f3b 100644 --- a/api/search/views.py +++ b/api/search/views.py @@ -656,7 +656,7 @@ class SearchCollections(BaseSearchView): doc_type = 'collectionSubmission' view_category = 'search' view_name = 'search-collected-metadata' - required_write_scopes = [CoreScopes.SEARCH_COLLECTIONS_WRITE] + required_write_scopes = [CoreScopes.ADVANCED_SEARCH] @property def search_fields(self): diff --git a/framework/auth/oauth_scopes.py b/framework/auth/oauth_scopes.py index 8f859319717..6bf6d386266 100644 --- a/framework/auth/oauth_scopes.py +++ b/framework/auth/oauth_scopes.py @@ -210,7 +210,7 @@ class CoreScopes: READ_COLLECTION_SUBMISSION = 'read_collection_submission' WRITE_COLLECTION_SUBMISSION = 'write_collection_submission' - SEARCH_COLLECTIONS_WRITE = 'search_collections_write' + ADVANCED_SEARCH = 'advanced_search' class ComposedScopes: From bff28c456d37abd6b7d6bbe399a92f1635844083 Mon Sep 17 00:00:00 2001 From: Anton Krytskyi Date: Fri, 27 Jun 2025 11:26:33 +0300 Subject: [PATCH 3/3] fix composed scope --- framework/auth/oauth_scopes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/auth/oauth_scopes.py b/framework/auth/oauth_scopes.py index 6bf6d386266..65a852f058b 100644 --- a/framework/auth/oauth_scopes.py +++ b/framework/auth/oauth_scopes.py @@ -373,7 +373,7 @@ class ComposedScopes: CoreScopes.WRITE_COLLECTION_SUBMISSION_ACTION, CoreScopes.WRITE_COLLECTION_SUBMISSION, CoreScopes.USERS_MESSAGE_WRITE_EMAIL, - CoreScopes.SEARCH_COLLECTIONS_WRITE + CoreScopes.ADVANCED_SEARCH ) # Admin permissions- includes functionality not intended for third-party use