Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/gravy valet integration #10665

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
efa7b46
Merge branch 'hotfix/24.02.1'
mfraezz Jul 1, 2024
c47481a
Update CHANGELOG, bump version
mfraezz Jul 8, 2024
764fd47
Merge branch 'release/24.03.0'
mfraezz Jul 8, 2024
422a4ad
Merge branch 'release/24.03.0' into develop
mfraezz Jul 8, 2024
ed3fadd
[ENG-5030] Preprints Phase 2 - BE (#10617)
cslzchen Jul 8, 2024
bdbcc63
Update CHANGELOG, bump version
mfraezz Jul 8, 2024
a23d6c4
Merge branch 'release/24.04.0'
mfraezz Jul 8, 2024
3583f02
Merge branch 'release/24.04.0' into develop
mfraezz Jul 8, 2024
9cec4c2
[ENG-3685] Add permissions for withdrawn registration files (#10650)
uditijmehta Jul 9, 2024
ed34ace
Allow DOI metadata updates to be queued
mfraezz Jul 9, 2024
f174dc1
Merge branch 'hotfix/24.04.1'
mfraezz Jul 9, 2024
529c585
Merge branch 'hotfix/24.04.1' into develop
mfraezz Jul 9, 2024
799cb57
Fix signature
mfraezz Jul 9, 2024
cdb0aa2
Merge branch 'hotfix/24.04.2'
mfraezz Jul 9, 2024
905ea6b
Merge branch 'hotfix/24.04.2' into develop
mfraezz Jul 9, 2024
30604a0
Check Registration READ perms on the Registration
mfraezz Jul 11, 2024
a7f970a
Merge branch 'hotfix/24.04.3' into develop
mfraezz Jul 11, 2024
34d5641
Revert "[ENG-3685] Add permissions for withdrawn registration files (…
felliott Jul 12, 2024
6c32a94
[ENG-5727][ENG-5728] Get Addon information from GravyValet (#10652)
jwalz Jun 28, 2024
1eeb452
Resolve conflicts
Jul 12, 2024
7c24977
Fix File Detail tests
Jul 15, 2024
8ffd64a
Merge branch 'feature/gravy_valet_integration' into feature/gravy_val…
jwalz Jul 15, 2024
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: 14 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,20 @@

We follow the CalVer (https://calver.org/) versioning scheme: YY.MINOR.MICRO.

24.01.0 (2024-04-30)
24.03.0 (2024-07-08)
====================
- Preprints into Ember OSF Web, Phase 2 Backend Release

24.03.0 (2024-07-08)
====================
- Allow AbstractProviders to specify Discover page presence
- Update get_auth
- Expand Addons Service support functionality, waffled
- Set default Resource Type General for Registrations
- Bug fix: Archiver Unicode edge cases
- Bug fix: RelationshipField during project creation

24.02.0 (2024-04-30)
====================
- Initial Addons Service work, Waffled
- Improve default `description` for Google Dataset Discovery
Expand Down
10 changes: 6 additions & 4 deletions addons/base/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ def get_addon_user_config(**kwargs):

return addon.to_json(user)


def make_auth(user):
if user is not None:
return {
Expand Down Expand Up @@ -207,9 +207,10 @@ def get_auth(auth, **kwargs):
waterbutler_data = _decrypt_and_decode_jwt_payload()
resource = _get_authenticated_resource(waterbutler_data['nid'])


action = waterbutler_data['action']
_check_resource_permissions(resource, auth, action)

provider_name = waterbutler_data['provider']
file_version = file_node = None
if provider_name == 'osfstorage':
Expand All @@ -221,6 +222,7 @@ def get_auth(auth, **kwargs):
resource=resource, provider_name=provider_name, file_version=file_version,
)


_enqueue_metrics(file_version=file_version, file_node=file_node, action=action, auth=auth)

# Construct the response payload including the JWT
Expand All @@ -230,8 +232,8 @@ def get_auth(auth, **kwargs):
credentials=waterbutler_credentials,
waterbutler_settings=waterbutler_settings
)


def _decrypt_and_decode_jwt_payload():
try:
payload_encrypted = request.args.get('payload', '').encode('utf-8')
Expand Down
3 changes: 3 additions & 0 deletions api/nodes/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@
File,
Folder,
CedarMetadataRecord,
Preprint,
)
from addons.osfstorage.models import Region
from osf.utils.permissions import ADMIN, WRITE_NODE
Expand Down Expand Up @@ -1514,6 +1515,8 @@ def id(self):

@property
def root_folder(self):
if isinstance(self.resource, Preprint):
return self.target.root_folder
if self.provider_settings:
return self.provider_settings.root_node
return None
Expand Down
10 changes: 10 additions & 0 deletions api/preprints/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class PreprintSerializer(TaxonomizableSerializerMixin, MetricsSerializerMixin, J
date_modified = VersionedDateTimeField(source='modified', read_only=True)
date_published = VersionedDateTimeField(read_only=True)
original_publication_date = VersionedDateTimeField(required=False, allow_null=True)
custom_publication_citation = ser.CharField(required=False, allow_blank=True, allow_null=True)
doi = ser.CharField(source='article_doi', required=False, allow_null=True)
title = ser.CharField(required=True, max_length=512)
description = ser.CharField(required=False, allow_blank=True, allow_null=True)
Expand Down Expand Up @@ -222,6 +223,11 @@ def subjects_view_kwargs(self):
# Overrides TaxonomizableSerializerMixin
return {'preprint_id': '<_id>'}

@property
def subjects_self_view(self):
# Overrides TaxonomizableSerializerMixin
return 'preprints:preprint-relationships-subjects'

def get_preprint_url(self, obj):
return absolute_reverse('preprints:preprint-detail', kwargs={'preprint_id': obj._id, 'version': self.context['request'].parser_context['kwargs']['version']})

Expand Down Expand Up @@ -326,6 +332,10 @@ def update(self, preprint, validated_data):
preprint.original_publication_date = validated_data['original_publication_date'] or None
save_preprint = True

if 'custom_publication_citation' in validated_data:
preprint.custom_publication_citation = validated_data['custom_publication_citation'] or None
save_preprint = True

if 'has_coi' in validated_data:
try:
preprint.update_has_coi(auth, validated_data['has_coi'])
Expand Down
1 change: 1 addition & 0 deletions api/preprints/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
re_path(r'^(?P<preprint_id>\w+)/files/osfstorage/$', views.PreprintFilesList.as_view(), name=views.PreprintFilesList.view_name),
re_path(r'^(?P<preprint_id>\w+)/identifiers/$', views.PreprintIdentifierList.as_view(), name=views.PreprintIdentifierList.view_name),
re_path(r'^(?P<preprint_id>\w+)/relationships/node/$', views.PreprintNodeRelationship.as_view(), name=views.PreprintNodeRelationship.view_name),
re_path(r'^(?P<preprint_id>\w+)/relationships/subjects/$', views.PreprintSubjectsRelationship.as_view(), name=views.PreprintSubjectsRelationship.view_name),
re_path(r'^(?P<preprint_id>\w+)/review_actions/$', views.PreprintActionList.as_view(), name=views.PreprintActionList.view_name),
re_path(r'^(?P<preprint_id>\w+)/requests/$', views.PreprintRequestListCreate.as_view(), name=views.PreprintRequestListCreate.view_name),
re_path(r'^(?P<preprint_id>\w+)/subjects/$', views.PreprintSubjectsList.as_view(), name=views.PreprintSubjectsList.view_name),
Expand Down
33 changes: 32 additions & 1 deletion api/preprints/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
from api.requests.permissions import PreprintRequestPermission
from api.requests.serializers import PreprintRequestSerializer, PreprintRequestCreateSerializer
from api.requests.views import PreprintRequestMixin
from api.subjects.views import BaseResourceSubjectsList
from api.subjects.views import BaseResourceSubjectsList, SubjectRelationshipBaseView
from api.base.metrics import PreprintMetricsViewMixin
from osf.metrics import PreprintDownload, PreprintView

Expand Down Expand Up @@ -456,6 +456,37 @@ class PreprintSubjectsList(BaseResourceSubjectsList, PreprintMixin):
def get_resource(self):
return self.get_preprint()


class PreprintSubjectsRelationship(SubjectRelationshipBaseView, PreprintMixin):
"""The documentation for this endpoint can be found [here](https://developer.osf.io/#operation/preprint_subjects_list).
"""
permission_classes = (
drf_permissions.IsAuthenticatedOrReadOnly,
base_permissions.TokenHasScope,
ModeratorIfNeverPublicWithdrawn,
ContributorOrPublic,
PreprintPublishedOrWrite,
)

required_read_scopes = [CoreScopes.PREPRINTS_READ]
required_write_scopes = [CoreScopes.PREPRINTS_WRITE]

view_category = 'preprints'
view_name = 'preprint-relationships-subjects'

def get_resource(self, check_object_permissions=True):
return self.get_preprint(check_object_permissions=check_object_permissions)

def get_object(self):
resource = self.get_resource(check_object_permissions=False)
obj = {
'data': resource.subjects.all(),
'self': resource,
}
self.check_object_permissions(self.request, resource)
return obj


class PreprintActionList(JSONAPIBaseView, generics.ListCreateAPIView, ListFilterMixin, PreprintMixin):
"""Action List *Read-only*

Expand Down
45 changes: 45 additions & 0 deletions api_tests/files/views/test_file_detail.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@

SessionStore = import_module(django_conf_settings.SESSION_ENGINE).SessionStore

from addons.base.views import _get_authenticated_resource
from framework.exceptions import HTTPError

# stolen from^W^Winspired by DRF
# rest_framework.fields.DateTimeField.to_representation
def _dt_to_iso8601(value):
Expand Down Expand Up @@ -705,6 +708,48 @@ def test_load_and_property(self, app, user, file):
expect_errors=True, auth=user.auth,
).status_code == 405

def test_retracted_file_returns_410(self, app, user, file_url, file):
resource = RegistrationFactory(is_public=True)
retraction = resource.retract_registration(
user=resource.creator,
justification='Justification for retraction',
save=True,
moderator_initiated=False
)

retraction.accept()
resource.save()
resource.refresh_from_db()

file.target = resource
file.save()

res = app.get(file_url, auth=user.auth, expect_errors=True)
assert res.status_code == 410

def test_get_authenticated_resource_retracted(self):
resource = RegistrationFactory(is_public=True)

assert resource.is_retracted is False

retraction = resource.retract_registration(
user=resource.creator,
justification='Justification for retraction',
save=True,
moderator_initiated=False
)

retraction.accept()
resource.save()
resource.refresh_from_db()

assert resource.is_retracted is True

with pytest.raises(HTTPError) as excinfo:
_get_authenticated_resource(resource._id)

assert excinfo.value.code == 410


@pytest.mark.django_db
class TestFileTagging:
Expand Down
23 changes: 23 additions & 0 deletions api_tests/preprints/views/test_preprint_detail.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,19 @@ def test_update_original_publication_date_to_none(self, app, preprint, url):
preprint.reload()
assert preprint.original_publication_date is None

def test_update_custom_publication_citation_to_none(self, app, preprint, url):
write_contrib = AuthUserFactory()
preprint.add_contributor(write_contrib, WRITE, save=True)
preprint.custom_publication_citation = 'fake citation'
preprint.save()
update_payload = build_preprint_update_payload(
preprint._id, attributes={'custom_publication_citation': None}
)
res = app.patch_json_api(url, update_payload, auth=write_contrib.auth)
assert res.status_code == 200
preprint.reload()
assert preprint.custom_publication_citation is None

@responses.activate
@mock.patch('osf.models.preprint.update_or_enqueue_on_preprint_updated', mock.Mock())
def test_update_preprint_permission_write_contrib(self, app, preprint, url):
Expand Down Expand Up @@ -536,6 +549,16 @@ def test_update_original_publication_date(self, app, user, preprint, url):
preprint.reload()
assert preprint.original_publication_date == date

def test_update_custom_publication_citation(self, app, user, preprint, url):
citation = 'fake citation'
update_payload = build_preprint_update_payload(
preprint._id, attributes={'custom_publication_citation': citation}
)
res = app.patch_json_api(url, update_payload, auth=user.auth)
assert res.status_code == 200
preprint.reload()
assert preprint.custom_publication_citation == citation

@responses.activate
@mock.patch('osf.models.preprint.update_or_enqueue_on_preprint_updated', mock.Mock())
def test_update_article_doi(self, app, user, preprint, url):
Expand Down
1 change: 0 additions & 1 deletion osf/external/gravy_valet/translations.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ def create_waterbutler_log(self, *args, **kwargs):
def save(self):
pass


@dataclasses.dataclass
class EphemeralUserSettings:
'''Minimalist dataclass for storing the actually used properties of UserSettings.'''
Expand Down
18 changes: 18 additions & 0 deletions osf/migrations/0021_preprint_custom_publication_citation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.17 on 2024-05-15 15:07

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('osf', '0020_abstractprovider_advertise_on_discover_page'),
]

operations = [
migrations.AddField(
model_name='preprint',
name='custom_publication_citation',
field=models.TextField(blank=True, null=True),
),
]
2 changes: 2 additions & 0 deletions osf/models/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import markupsafe
import logging

import waffle

from django.apps import apps
from django.contrib.auth.models import Group, AnonymousUser
from django.core.exceptions import ObjectDoesNotExist, ValidationError
Expand Down
1 change: 1 addition & 0 deletions osf/models/preprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ class Preprint(DirtyFieldsMixin, GuidMixin, IdentifierMixin, ReviewableMixin, Ba
is_published = models.BooleanField(default=False, db_index=True)
date_published = NonNaiveDateTimeField(null=True, blank=True)
original_publication_date = NonNaiveDateTimeField(null=True, blank=True)
custom_publication_citation = models.TextField(null=True, blank=True)
license = models.ForeignKey('osf.NodeLicenseRecord',
on_delete=models.SET_NULL, null=True, blank=True)

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "OSF",
"version": "24.02.0",
"version": "24.04.0",
"description": "Facilitating Open Science",
"repository": "https://github.com/CenterForOpenScience/osf.io",
"author": "Center for Open Science",
Expand Down
11 changes: 7 additions & 4 deletions website/identifiers/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
from framework.celery_tasks.handlers import queued_task
from framework import sentry


@queued_task
@celery_app.task(ignore_results=True)
def update_doi_metadata_on_change(target_guid):
@celery_app.task(bind=True, max_retries=5, acks_late=True)
def task__update_doi_metadata_on_change(self, target_guid):
sentry.log_message('Updating DOI for guid', extra_data={'guid': target_guid}, level=logging.INFO)
Guid = apps.get_model('osf.Guid')
target_object = Guid.load(target_guid).referent
if target_object.get_identifier('doi'):
target_object.request_identifier_update(category='doi')

@queued_task
@celery_app.task(ignore_results=True)
def update_doi_metadata_on_change(target_guid):
task__update_doi_metadata_on_change(target_guid)
10 changes: 1 addition & 9 deletions website/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,15 +261,7 @@ def ember_app(path=None):
if request.path.strip('/').startswith(k):
ember_app = EXTERNAL_EMBER_APPS[k]
if k == 'preprints':
if request.path.rstrip('/').endswith('edit'):
# Route preprint edit pages to old preprint app
ember_app = EXTERNAL_EMBER_APPS.get('preprints', False) or ember_app
elif request.path.rstrip('/').endswith('submit'):
# Route preprint submit pages to old preprint app
ember_app = EXTERNAL_EMBER_APPS.get('preprints', False) or ember_app
else:
# Route other preprint pages to EOW
ember_app = EXTERNAL_EMBER_APPS.get('ember_osf_web', False) or ember_app
ember_app = EXTERNAL_EMBER_APPS.get('ember_osf_web', False) or ember_app
break

if not ember_app:
Expand Down
3 changes: 2 additions & 1 deletion website/settings/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ class CeleryConfig:
'website.mailchimp_utils',
'website.notifications.tasks',
'website.collections.tasks',
'website.identifier.tasks',
'website.identifiers.tasks',
'website.preprints.tasks',
'website.project.tasks',
}
Expand Down Expand Up @@ -516,6 +516,7 @@ class CeleryConfig:
'website.mailchimp_utils',
'website.notifications.tasks',
'website.archiver.tasks',
'website.identifiers.tasks',
'website.search.search',
'website.project.tasks',
'scripts.populate_new_and_noteworthy_projects',
Expand Down
3 changes: 0 additions & 3 deletions website/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
from api.waffle.utils import storage_i18n_flag_active, flag_is_active

logger = logging.getLogger(__name__)
preprints_dir = os.path.abspath(os.path.join(os.getcwd(), EXTERNAL_EMBER_APPS['preprints']['path']))
ember_osf_web_dir = os.path.abspath(os.path.join(os.getcwd(), EXTERNAL_EMBER_APPS['ember_osf_web']['path']))


Expand Down Expand Up @@ -331,8 +330,6 @@ def resolve_guid(guid, suffix=None):
if isinstance(resource, Preprint):
if resource.provider.domain_redirect_enabled:
return redirect(resource.absolute_url, http_status.HTTP_301_MOVED_PERMANENTLY)
if clean_suffix.endswith('edit'):
return stream_emberapp(EXTERNAL_EMBER_APPS['preprints']['server'], preprints_dir)
return use_ember_app()

elif isinstance(resource, Registration) and (clean_suffix in ('', 'comments', 'links', 'components', 'resources',)) and flag_is_active(request, features.EMBER_REGISTRIES_DETAIL_PAGE):
Expand Down
Loading