From 9bb89a25e0df232d8606f584ea3c3050b1bfe860 Mon Sep 17 00:00:00 2001 From: Yuhuai Liu Date: Wed, 11 Sep 2024 22:15:06 -0400 Subject: [PATCH] some fixes- not final yet --- addons/base/views.py | 11 +++++++++-- api/nodes/serializers.py | 6 +++++- api/nodes/urls.py | 4 ++-- osf/external/gravy_valet/request_helpers.py | 7 ++++--- osf/external/gravy_valet/translations.py | 18 +++++++++++++++++- osf/models/node.py | 13 ++++++++----- 6 files changed, 45 insertions(+), 14 deletions(-) diff --git a/addons/base/views.py b/addons/base/views.py index e3c0a402bbb..0ffffc640cd 100644 --- a/addons/base/views.py +++ b/addons/base/views.py @@ -10,6 +10,7 @@ from furl import furl import jwe import jwt +from osf.external.gravy_valet.translations import EphemeralNodeSettings import waffle from django.db import transaction from django.contrib.contenttypes.models import ContentType @@ -837,8 +838,14 @@ def addon_view_or_download_file(auth, path, provider, **kwargs): if hasattr(target, 'get_addon'): node_addon = target.get_addon(provider) - - if not isinstance(node_addon, BaseStorageAddon): + if flag_is_active(request, features.ENABLE_GV): + if not isinstance(node_addon, EphemeralNodeSettings): + object_text = markupsafe.escape(getattr(target, 'project_or_component', 'this object')) + raise HTTPError(http_status.HTTP_400_BAD_REQUEST, data={ + 'message_short': 'Bad Request', + 'message_long': f'The {provider_safe} add-on containing {path_safe} is no longer connected to {object_text}.' + }) + elif not isinstance(node_addon, BaseStorageAddon): object_text = markupsafe.escape(getattr(target, 'project_or_component', 'this object')) raise HTTPError(http_status.HTTP_400_BAD_REQUEST, data={ 'message_short': 'Bad Request', diff --git a/api/nodes/serializers.py b/api/nodes/serializers.py index 317fcb724e8..caaf61e6b86 100644 --- a/api/nodes/serializers.py +++ b/api/nodes/serializers.py @@ -1456,7 +1456,11 @@ class Meta: @staticmethod def get_id(obj): - return f'{obj.node._id}:{obj.provider}' + from addons.base.models import BaseAddonSettings + if issubclass(type(obj.provider_settings), BaseAddonSettings): + return f'{obj.node._id}:{obj.provider}' + else: + return obj.provider_settings.gv_data.resource_id def get_absolute_url(self, obj): return absolute_reverse( diff --git a/api/nodes/urls.py b/api/nodes/urls.py index 1adb9737be0..117131b3305 100644 --- a/api/nodes/urls.py +++ b/api/nodes/urls.py @@ -27,8 +27,8 @@ re_path(r'^(?P\w+)/draft_registrations/(?P\w+)/$', views.NodeDraftRegistrationDetail.as_view(), name=views.NodeDraftRegistrationDetail.view_name), re_path(r'^(?P\w+)/files/$', views.NodeStorageProvidersList.as_view(), name=views.NodeStorageProvidersList.view_name), re_path(r'^(?P\w+)/files/providers/(?P\w+)/?$', views.NodeStorageProviderDetail.as_view(), name=views.NodeStorageProviderDetail.view_name), - re_path(r'^(?P\w+)/files/(?P\w+)(?P/(?:.*/)?)$', views.NodeFilesList.as_view(), name=views.NodeFilesList.view_name), - re_path(r'^(?P\w+)/files/(?P\w+)(?P/.+[^/])$', views.NodeFileDetail.as_view(), name=views.NodeFileDetail.view_name), + re_path(r'^(?P\w+)/files/(?P[a-zA-Z0-9\-]*)(?P/(?:.*/)?)$', views.NodeFilesList.as_view(), name=views.NodeFilesList.view_name), + re_path(r'^(?P\w+)/files/(?P[a-zA-Z0-9\-]*)(?P/.+[^/])$', views.NodeFileDetail.as_view(), name=views.NodeFileDetail.view_name), re_path(r'^(?P\w+)/forks/$', views.NodeForksList.as_view(), name=views.NodeForksList.view_name), re_path(r'^(?P\w+)/groups/$', views.NodeGroupsList.as_view(), name=views.NodeGroupsList.view_name), re_path(r'^(?P\w+)/groups/(?P\w+)/$', views.NodeGroupsDetail.as_view(), name=views.NodeGroupsDetail.view_name), diff --git a/osf/external/gravy_valet/request_helpers.py b/osf/external/gravy_valet/request_helpers.py index 22fe2a925f4..579c6cc6ae5 100644 --- a/osf/external/gravy_valet/request_helpers.py +++ b/osf/external/gravy_valet/request_helpers.py @@ -16,7 +16,7 @@ # {{placeholder}} format allows f-string to return a formatable string ACCOUNT_ENDPOINT = f'{API_BASE}authorized-storage-accounts/{{pk}}' ADDON_ENDPOINT = f'{API_BASE}configured-storage-addons/{{pk}}' -WB_CONFIG_ENDPOINT = f'{ADDON_ENDPOINT}/waterbutler-config' +WB_CONFIG_ENDPOINT = f'{ADDON_ENDPOINT}/waterbutler-credentials' USER_LIST_ENDPOINT = f'{API_BASE}user-references' USER_DETAIL_ENDPOINT = f'{API_BASE}user-references/{{pk}}' @@ -145,7 +145,7 @@ def _make_gv_request( params: dict = None, ): '''Generates HMAC-Signed auth headers and makes a request to GravyValet, returning the result.''' - full_url = urlunparse(urlparse(endpoint_url)._replace(query=urlencode(params))) + full_url = urlunparse(urlparse(endpoint_url)._replace(query=urlencode(params or {}))) auth_headers = auth_helpers.make_gravy_valet_hmac_headers( request_url=full_url, request_method=request_method, @@ -189,7 +189,8 @@ def __init__(self, result_entry: dict, included_entities_lookup: dict = None): self.resource_type = result_entry['type'] self.resource_id = result_entry['id'] self._attributes = dict(result_entry['attributes']) - self._relationships = _extract_relationships(result_entry['relationships']) + if 'relationships' in result_entry: + self._relationships = _extract_relationships(result_entry['relationships']) self._includes = {} if included_entities_lookup: self.extract_included_relationships(included_entities_lookup) diff --git a/osf/external/gravy_valet/translations.py b/osf/external/gravy_valet/translations.py index b81661876a5..d6430c3582a 100644 --- a/osf/external/gravy_valet/translations.py +++ b/osf/external/gravy_valet/translations.py @@ -92,12 +92,28 @@ def configured(self): attribute_name='credentials_available' ) + @property + def deleted(self): + return False + + @property + def id(self): + return self.gv_id + + @property + def has_auth(self): + return True + + @property + def complete(self): + return True + def before_page_load(self, *args, **kwargs): pass @property def folder_id(self): - return self.gv_data.get_attribute('root_folder') + return self.gv_data.get_attribute('root_folder').split(':')[1] def serialize_waterbutler_credentials(self): # sufficient for most OAuth services, including Box diff --git a/osf/models/node.py b/osf/models/node.py index 33bdae3039c..0b31e2d5d0e 100644 --- a/osf/models/node.py +++ b/osf/models/node.py @@ -2432,13 +2432,16 @@ def _remove_from_associated_collections(self, auth=None, force=False): def _get_addon_from_gv(self, gv_pk, requesting_user_id): requesting_user = OSFUser.load(requesting_user_id) - gv_addon_data = gv_requests.get_addon( - gv_addon_pk=gv_pk, + all_node_addon_data = [item for item in gv_requests.iterate_addons_for_resource( requested_resource=self, - requesting_user=requesting_user, - ) + requesting_user=requesting_user)] + # gv_addon_data = gv_requests.get_addon( + # gv_addon_pk=gv_pk, + # requested_resource=self, + # requesting_user=requesting_user, + # ) return gv_translations.make_ephemeral_node_settings( - gv_addon_data=gv_addon_data, + gv_addon_data=all_node_addon_data[0], requested_resource=self, requesting_user=requesting_user )