|
6 | 6 | from django.utils import timezone |
7 | 7 | from django.core.exceptions import PermissionDenied, ValidationError |
8 | 8 | from django.urls import NoReverseMatch |
| 9 | +from django.db import transaction |
9 | 10 | from django.db.models import F, Case, When, IntegerField |
10 | 11 | from django.contrib import messages |
11 | 12 | from django.contrib.auth.mixins import PermissionRequiredMixin |
|
28 | 29 | from api.caching.tasks import update_storage_usage_cache |
29 | 30 |
|
30 | 31 | from osf.exceptions import NodeStateError, RegistrationStuckError |
| 32 | +from osf.management.commands.change_node_region import _update_schema_meta |
31 | 33 | from osf.models import ( |
| 34 | + Guid, |
32 | 35 | OSFUser, |
33 | 36 | NodeLog, |
34 | 37 | AbstractNode, |
35 | 38 | Registration, |
36 | 39 | RegistrationProvider, |
37 | 40 | RegistrationApproval, |
38 | | - SpamStatus |
| 41 | + SpamStatus, |
| 42 | + TrashedFile |
39 | 43 | ) |
40 | 44 | from osf.models.admin_log_entry import ( |
41 | 45 | update_admin_log, |
@@ -813,6 +817,36 @@ def post(self, request, *args, **kwargs): |
813 | 817 | return redirect(self.get_success_url()) |
814 | 818 |
|
815 | 819 |
|
| 820 | +class NodeRemoveFileView(NodeMixin, View): |
| 821 | + """ Allows an authorized user to remove file from node. |
| 822 | + """ |
| 823 | + permission_required = 'osf.change_node' |
| 824 | + |
| 825 | + def post(self, request, *args, **kwargs): |
| 826 | + def _remove_file_from_schema_response_blocks(registration, removed_file_id): |
| 827 | + file_input_keys = registration.registration_schema.schema_blocks.filter( |
| 828 | + block_type='file-input' |
| 829 | + ).values_list('registration_response_key', flat=True) |
| 830 | + for schema_response in registration.schema_responses.all(): |
| 831 | + for block in schema_response.response_blocks.filter(schema_key__in=file_input_keys): |
| 832 | + if not block.response: |
| 833 | + continue |
| 834 | + block.response = [entry for entry in block.response if entry.get('file_id') not in removed_file_id] |
| 835 | + block.save() |
| 836 | + |
| 837 | + node = self.get_object() |
| 838 | + guid_id = request.POST.get('remove-file-guid', '').strip() |
| 839 | + guid = Guid.load(guid_id) |
| 840 | + |
| 841 | + # delete file from registration and metadata and keep it for original project |
| 842 | + if guid and (file := guid.referent) and (file.target == node) and not isinstance(file, TrashedFile): |
| 843 | + with transaction.atomic(): |
| 844 | + file.delete() |
| 845 | + _update_schema_meta(file.target) |
| 846 | + _remove_file_from_schema_response_blocks(node, [file._id, file.copied_from._id]) |
| 847 | + return redirect(self.get_success_url()) |
| 848 | + |
| 849 | + |
816 | 850 | class RemoveStuckRegistrationsView(NodeMixin, View): |
817 | 851 | """ Allows an authorized user to remove a registrations if it's stuck in the archiving process. |
818 | 852 | """ |
|
0 commit comments