Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions api/guids/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from furl import furl
from django import http
from osf.models.base import VersionedGuidMixin
from rest_framework.exceptions import NotFound
from rest_framework import permissions as drf_permissions
from rest_framework import generics
Expand Down Expand Up @@ -70,11 +71,17 @@ def get(self, request, **kwargs):
raise NotFound

def get_redirect_url(self, **kwargs):
guid = Guid.load(kwargs['guids'])
if guid:
referent = guid.referent
guid_str, version_number = Guid.split_guid(kwargs['guids'])
guid = Guid.load(guid_str)
if not guid:
return None
referent = guid.referent
if version_number and isinstance(referent, VersionedGuidMixin):
# if the guid string contains a version number and referent is versionable
return referent.get_versioned_absolute_api_v2_url(version_number)
else:
# if the guid string doesn't have a version number or the referent is not versionable
if getattr(referent, 'absolute_api_v2_url', None):
return referent.absolute_api_v2_url
else:
raise EndpointNotImplementedError()
return None
45 changes: 45 additions & 0 deletions api_tests/guids/views/test_guid_detail.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from api.base.settings.defaults import API_BASE
from osf_tests.factories import (
AuthUserFactory,
PreprintFactory,
ProjectFactory,
RegistrationFactory,
CommentFactory,
Expand All @@ -27,6 +28,18 @@ def project(self):
@pytest.fixture()
def registration(self):
return RegistrationFactory()

@pytest.fixture()
def versioned_preprint(self, user):
preprint = PreprintFactory(reviews_workflow='pre-moderation')
PreprintFactory.create_version(
create_from=preprint,
creator=user,
final_machine_state='accepted',
is_published=True,
set_doi=False
)
return preprint

def test_redirects(self, app, project, registration, user):
# test_redirect_to_node_view
Expand Down Expand Up @@ -125,6 +138,38 @@ def test_redirects_through_view_only_link(self, app, project, user):
assert res.status_code == 302
assert res.location == redirect_url

def test_redirects_with_version_for_versionable_objects(self, app, versioned_preprint, user):
# if you go to the guids endpoint with just the guid without version number
url = f'/{API_BASE}guids/{versioned_preprint.versioned_guids.first().guid._id}/'
res = app.get(url, auth=user.auth)
redirect_url = f'{API_DOMAIN}{API_BASE}preprints/{versioned_preprint.versioned_guids.first().guid._id}_v2/'
assert res.status_code == 302
assert res.location == redirect_url

# if you go to the guids endpoint with just the guid with a version number
url = f'/{API_BASE}guids/{versioned_preprint.versioned_guids.first().guid._id}_v2/'
res = app.get(url, auth=user.auth)
redirect_url = f'{API_DOMAIN}{API_BASE}preprints/{versioned_preprint.versioned_guids.first().guid._id}_v2/'
assert res.status_code == 302
assert res.location == redirect_url

url = f'/{API_BASE}guids/{versioned_preprint.versioned_guids.first().guid._id}_v1/'
res = app.get(url, auth=user.auth)
redirect_url = f'{API_DOMAIN}{API_BASE}preprints/{versioned_preprint.versioned_guids.first().guid._id}_v1/'
assert res.status_code == 302
assert res.location == redirect_url

url = f'/{API_BASE}guids/{versioned_preprint.versioned_guids.first().guid._id}_v3/'
res = app.get(url, auth=user.auth, expect_errors=True)
assert res.status_code == 404

def test_redirects_with_version_for_unversionable_objects(self, app, project, user):
url = f'/{API_BASE}guids/{project._id}_v12/'
res = app.get(url, auth=user.auth, expect_errors=True)
redirect_url = f'{API_DOMAIN}{API_BASE}nodes/{project._id}/'
assert res.status_code == 302
assert res.location == redirect_url

def test_resolves(self, app, project, user):
# test_resolve_query_param
url = '{}{}guids/{}/?resolve=false'.format(
Expand Down
3 changes: 3 additions & 0 deletions osf/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,9 @@ def get_guid(self):
"""
return self.versioned_guids.first().guid

def get_versioned_absolute_api_v2_url(self, version):
raise NotImplementedError

def get_semantic_iri(self):
"""Override `get_semantic_iri()` in `GuidMixin` so that all versions of the same object have the same semantic
iri using only the base guid str.
Expand Down
6 changes: 6 additions & 0 deletions osf/models/preprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,12 @@ def api_url_for(self, view_name, _absolute=False, *args, **kwargs):
def get_absolute_url(self):
return self.absolute_api_v2_url

def get_versioned_absolute_api_v2_url(self, version):
if self.guids.first().versions.filter(version=version).exists():
path = f'/preprints/{self.guids.first()._id}{VersionedGuidMixin.GUID_VERSION_DELIMITER}{version}/'
return api_v2_url(path)
return None

def add_log(self, action, params, auth, foreign_user=None, log_date=None, save=True, request=None, should_hide=False):
user = None
if auth:
Expand Down
Loading