import logging import os from django.conf import settings from django.db.models import Q from django.http import JsonResponse, HttpResponseForbidden, HttpResponseNotFound from rest_framework.decorators import action from rest_framework.generics import get_object_or_404, GenericAPIView from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, DestroyModelMixin from rest_framework.viewsets import GenericViewSet from core.mixins import ApiPermissionCheckMixin from core.utils import store_file_response from devices.services.endpoint.endpoint_antivirus import EndpointAntivirusService from perms.models import Perm from storage.exception import StorageException from storage.models import DataStorage from storage.serializers import AntivirusStorageSerializer, StorageSerializer, StorageListSerializer _log = logging.getLogger() class StorageViewSet(ApiPermissionCheckMixin, ListModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet): console_permissions = [Perm.can_view_storage] ordering_fields = ['id', 'format', 'size', 'description', 'created', 'filename'] def get_serializer_class(self): if self.action == 'list': return StorageListSerializer return StorageSerializer def get_queryset(self): queryset = DataStorage.objects user = self.request.user storage_filter = Q(user=user) if not user.is_superuser: if user.has_perm(Perm.perm_req(Perm.can_download_rotation_files)): storage_filter |= Q(type=DataStorage.Type.DB_DUMP) queryset = queryset.filter(storage_filter).distinct() return queryset.all() class Meta: model = DataStorage @action(detail=True, name='download', methods=['GET']) def download(self, request, *args, **kwargs): cur = get_object_or_404(DataStorage, pk=kwargs['pk']) if cur.type == DataStorage.Type.DB_DUMP and not request.user.has_perm( Perm.perm_req(Perm.can_download_rotation_files)): _log.error( f'User [{request.user}] try to get storage with id [{cur.id}] without permissions [can_download_rotation_files] ') return HttpResponseForbidden() # Check that user owns this file if not request.user.is_superuser and cur.type != DataStorage.Type.DB_DUMP: if request.user != cur.user: _log.error(f'User [{request.user}] try to get storage with id [{id}] that belongs to [{cur.user}]') return HttpResponseForbidden() # Check that file exists file_path = os.path.join(settings.MEDIA_ROOT, cur.file.name) if not os.path.exists(file_path): _log.error(f'User [{request.user}] try to download file [{cur.pk}:{cur.file.name}] but file doesnt exist') return HttpResponseNotFound() _log.info(f'User [{request.user}] start download file [{cur.pk}:{cur.file.name}]') cur.save() return store_file_response(file_path) class AntivirusStorageView(ApiPermissionCheckMixin, GenericAPIView): serializer_class = AntivirusStorageSerializer console_permissions = [Perm.can_view_storage] def post(self, request, *args, **kwargs): if 'file' not in request.FILES: raise StorageException({'status': 'error', 'detail': 'Upload file is required'}) # Calculating file size for storage instance info file = request.FILES['file'] file.seek(0, os.SEEK_END) file_length = file.tell() # Setting up necessary service field values for storage field request.data['user'] = request.user.pk request.data['size'] = file_length serializer = self.get_serializer(data=request.data) if serializer.is_valid(): DataStorage.objects.filter(format=DataStorage.Type.CLAMAV).delete() serializer.save() _log.info('Update ClamAV signature database in storage') EndpointAntivirusService.all_update(True) return JsonResponse({'status': 'ok'}) else: raise StorageException({'status': 'err', 'message': serializer.errors})