Skip to content
Merged
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
7 changes: 4 additions & 3 deletions admin/preprints/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ class RecoverDeletedPreprintForm(forms.Form):
description = forms.CharField(widget=forms.Textarea, required=False)
file_guid = forms.CharField(
required=False,
label='Source file GUID',
help_text='Optional: an existing file GUID; its latest version is copied into this '
'version as the primary file.',
label='Source file or preprint GUID',
help_text='Optional: an existing file GUID, or a preprint GUID (e.g. abcde or abcde_v1) whose '
'primary file is used. The latest version of the file is copied into this version '
'as the primary file.',
)
ticket_reference = forms.CharField(
max_length=255,
Expand Down
12 changes: 9 additions & 3 deletions admin/preprints/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,14 +277,20 @@ class RecoverDeletedPreprintView(PermissionRequiredMixin, FormView):
form_class = RecoverDeletedPreprintForm

def _copy_primary_file(self, preprint, file_guid):
source_file = getattr(Guid.load(file_guid), 'referent', None)
source, _ = Guid.load_referent(file_guid)
if isinstance(source, Preprint):
source_file = source.primary_file
if source_file is None:
raise ValueError(f'Preprint "{file_guid}" has no primary file to copy.')
else:
source_file = source
if not isinstance(source_file, BaseFileNode):
raise ValueError(f'No file found for guid "{file_guid}".')
raise ValueError(f'No file or preprint found for guid "{file_guid}".')
latest_version = source_file.versions.order_by('-created').first()
if latest_version is None:
raise ValueError(f'File "{file_guid}" has no versions to copy.')
copied = copy_files(source_file, target_node=preprint, identifier=latest_version.identifier)
preprint.set_primary_file(copied, auth=self.request, save=True)
preprint.set_primary_file(copied, auth=self.request, save=True, ignore_permission=True)

def form_valid(self, form):
data = form.cleaned_data
Expand Down
30 changes: 30 additions & 0 deletions admin_tests/preprints/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1085,6 +1085,36 @@ def test_copies_primary_file_from_source_guid(self):
assert recovered.primary_file is not None
assert recovered.primary_file.copied_from_id == source_file.id

def test_copies_primary_file_from_source_preprint_versioned_guid(self):
source = PreprintFactory(provider=self.provider)
source_file = source.primary_file

response = self._post(self._base_data(file_guid=source._id))
assert response.status_code == 302

recovered = Preprint.load('abcde')
assert recovered.primary_file.copied_from_id == source_file.id

def test_copies_primary_file_when_admin_is_not_a_contributor(self):
source = PreprintFactory(provider=self.provider)
target = PreprintFactory(provider=self.provider)
guid_str = target._id.split('_v')[0]
target.deleted = timezone.now()
target.save()
assert not target.has_permission(self.user, 'write')

response = self._post(self._base_data(guid=guid_str, file_guid=source._id))
assert response.status_code == 302

recovered = Preprint.load(guid_str)
assert recovered.deleted is None
assert recovered.primary_file.copied_from_id == source.primary_file.id

def test_unknown_source_guid_shows_error(self):
response = self._post(self._base_data(file_guid='zzzzz_v1'))
assert response.status_code == 302
assert Preprint.load('abcde') is None

def _orphan_guid(self, provider):
# Leave a base Guid with a dangling referent (the deleted-preprint state we recover from).
# Detach the GenericRelation first so deleting the preprint doesn't cascade the Guid away.
Expand Down
2 changes: 1 addition & 1 deletion osf/models/preprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,7 @@ def set_primary_file(self, preprint_file, auth, save=False, **kwargs):
action=PreprintLog.FILE_UPDATED,
params={
'preprint': self._id,
'file': self.primary_file._id
'file': str(self.primary_file._id)
},
auth=auth,
save=False
Expand Down
Loading