Skip to content

Commit 1c9e98b

Browse files
authored
[ENG-7716] Allow for reinstatement of previous preprint versions (with date uploaded) via the admin app (#11118)
## Purpose improve exception handling and minor fixes ## Changes - improve exception handling - supplemental node permission error - set subjects from relationship to keep valid hierarchy - ignore unfinished/unpublished versions ## Ticket https://openscience.atlassian.net/browse/ENG-7716
1 parent a746e7c commit 1c9e98b

File tree

4 files changed

+36
-20
lines changed

4 files changed

+36
-20
lines changed

admin/preprints/views.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
from osf.exceptions import PreprintStateError
2626
from rest_framework.exceptions import PermissionDenied as DrfPermissionDenied
27+
from framework.exceptions import PermissionsError
2728

2829
from osf.management.commands.fix_preprints_has_data_links_and_why_no_data import process_wrong_why_not_data_preprints
2930
from osf.models import (
@@ -212,18 +213,25 @@ def post(self, request, *args, **kwargs):
212213
assign_version_number=1,
213214
auth=request,
214215
ignore_permission=True,
216+
ignore_existing_versions=True,
215217
)
218+
data_to_update = data_to_update or dict()
219+
216220
primary_file = copy_files(preprint.primary_file, target_node=new_preprint, identifier__in=file_versions)
221+
if primary_file is None:
222+
raise ValueError(f"Primary file {preprint.primary_file.id} doesn't have following versions: {file_versions}") # rollback changes
217223
data_to_update['primary_file'] = primary_file
218224

219225
# FIXME: currently it's not possible to ignore permission when update subjects
220226
# via serializer, remove this logic if deprecated
221227
subjects = data_to_update.pop('subjects', None)
222228
if subjects:
223-
new_preprint.set_subjects([subjects], auth=request, ignore_permission=True)
229+
new_preprint.set_subjects_from_relationships(subjects, auth=request, ignore_permission=True)
224230

225231
PreprintSerializer(new_preprint, context={'request': request, 'ignore_permission': True}).update(new_preprint, data_to_update)
226-
except DrfPermissionDenied as exc:
232+
except ValueError as exc:
233+
return HttpResponse(str(exc), status=400)
234+
except (PermissionsError, DrfPermissionDenied) as exc:
227235
return HttpResponse(f'Not enough permissions to perform this action : {str(exc)}', status=400)
228236

229237
return JsonResponse({'redirect': self.get_success_url(new_preprint._id)})

api/preprints/serializers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ def update(self, preprint, validated_data):
416416

417417
if 'node' in validated_data:
418418
node = validated_data.pop('node', None)
419-
self.set_field(preprint.set_supplemental_node, node, auth, ignore_permission=ignore_permission)
419+
self.set_field(preprint.set_supplemental_node, node, auth, ignore_node_permissions=ignore_permission, ignore_permission=ignore_permission)
420420

421421
if 'subjects' in validated_data:
422422
subjects = validated_data.pop('subjects', None)

osf/models/mixins.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,7 @@ def set_subjects(self, new_subjects, auth, add_log=True, **kwargs):
11911191
if hasattr(self, 'update_search'):
11921192
self.update_search()
11931193

1194-
def set_subjects_from_relationships(self, subjects_list, auth, add_log=True):
1194+
def set_subjects_from_relationships(self, subjects_list, auth, add_log=True, **kwargs):
11951195
""" Helper for setting M2M subjects field from list of flattened subjects received from UI.
11961196
Only authorized admins may set subjects.
11971197
@@ -1201,7 +1201,7 @@ def set_subjects_from_relationships(self, subjects_list, auth, add_log=True):
12011201
12021202
:return: None
12031203
"""
1204-
self.check_subject_perms(auth)
1204+
self.check_subject_perms(auth, **kwargs)
12051205
self.assert_subject_format(subjects_list, expect_list=True, error_msg='Expecting a list of subjects.')
12061206
if subjects_list:
12071207
self.assert_subject_format(subjects_list[0], expect_list=False, error_msg='Expecting a list of subjects.')

osf/models/preprint.py

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ def check_unfinished_or_unpublished_version(self):
404404
return None, None
405405

406406
@classmethod
407-
def create_version(cls, create_from_guid, auth, assign_version_number=None, ignore_permission=False):
407+
def create_version(cls, create_from_guid, auth, assign_version_number=None, ignore_permission=False, ignore_existing_versions=False):
408408
"""Create a new version for a given preprint. `create_from_guid` can be any existing versions of the preprint
409409
but `create_version` always finds the latest version and creates a new version from it. In addition, this
410410
creates an "incomplete" new preprint version object using the model class and returns both the new object and
@@ -425,19 +425,21 @@ def create_version(cls, create_from_guid, auth, assign_version_number=None, igno
425425
sentry.log_message(f'ADMIN permission for the latest version is required to create a new version: '
426426
f'[user={auth.user._id}, guid={guid_obj._id}, latest_version={latest_version._id}]')
427427
raise PermissionsError
428-
unfinished_version, unpublished_version = latest_version.check_unfinished_or_unpublished_version()
429-
if unpublished_version:
430-
logger.error('Failed to create a new version due to unpublished pending version already exists: '
431-
f'[version={unpublished_version.version}, '
432-
f'_id={unpublished_version._id}, '
433-
f'state={unpublished_version.machine_state}].')
434-
raise UnpublishedPendingPreprintVersionExists
435-
if unfinished_version:
436-
logger.warning(f'Use existing initiated but unfinished version instead of creating a new one: '
437-
f'[version={unfinished_version.version}, '
438-
f'_id={unfinished_version._id}, '
439-
f'state={unfinished_version.machine_state}].')
440-
return unfinished_version, None
428+
if not ignore_existing_versions:
429+
unfinished_version, unpublished_version = latest_version.check_unfinished_or_unpublished_version()
430+
if unpublished_version:
431+
message = ('Failed to create a new version due to unpublished pending version already exists: '
432+
f'[version={unpublished_version.version}, '
433+
f'_id={unpublished_version._id}, '
434+
f'state={unpublished_version.machine_state}].')
435+
logger.error(message)
436+
raise UnpublishedPendingPreprintVersionExists(message)
437+
if unfinished_version:
438+
logger.warning(f'Use existing initiated but unfinished version instead of creating a new one: '
439+
f'[version={unfinished_version.version}, '
440+
f'_id={unfinished_version._id}, '
441+
f'state={unfinished_version.machine_state}].')
442+
return unfinished_version, None
441443

442444
# Prepare the data to clone/update
443445
data_to_update = {
@@ -536,7 +538,13 @@ def create_version(cls, create_from_guid, auth, assign_version_number=None, igno
536538
guid_obj.save()
537539

538540
if latest_version.node:
539-
preprint.set_supplemental_node(latest_version.node, auth, save=False, ignore_node_permissions=True)
541+
preprint.set_supplemental_node(
542+
latest_version.node,
543+
auth,
544+
save=False,
545+
ignore_node_permissions=True,
546+
ignore_permission=ignore_permission
547+
)
540548

541549
return preprint, data_to_update
542550

0 commit comments

Comments
 (0)