Add: modelviewsets for all models
This commit is contained in:
parent
90d7e64db3
commit
3f37ed95ed
@ -0,0 +1,25 @@
|
||||
# Generated by Django 4.2 on 2023-08-10 03:24
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('collector', '0007_rename_upload_ticket_attempts'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='ticket',
|
||||
name='attempts',
|
||||
field=models.IntegerField(default=5, validators=[django.core.validators.MaxValueValidator(10), django.core.validators.MinValueValidator(0)]),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticket',
|
||||
name='token',
|
||||
field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True),
|
||||
),
|
||||
]
|
@ -41,7 +41,7 @@ class Archive(models.Model):
|
||||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# calculate sha 1 hash sum and write md5 field to db
|
||||
# calculate md5 hash sum and write md5 field to db
|
||||
with self.file.open('rb') as f:
|
||||
md5 = hashlib.md5()
|
||||
for byte_block in iter(lambda: f.read(4096), b""):
|
||||
@ -72,7 +72,7 @@ class Ticket(models.Model):
|
||||
number = models.IntegerField(unique=True, db_index=True)
|
||||
resolved = models.BooleanField(default=False)
|
||||
note = models.TextField(blank=True)
|
||||
token = models.UUIDField(default=uuid.uuid4, editable=False)
|
||||
token = models.UUIDField(unique=True, default=uuid.uuid4, editable=False)
|
||||
attempts = models.IntegerField(default=5, validators=[
|
||||
MaxValueValidator(10),
|
||||
MinValueValidator(0)
|
||||
|
13
logs_collector/collector/permissions.py
Normal file
13
logs_collector/collector/permissions.py
Normal file
@ -0,0 +1,13 @@
|
||||
from rest_framework import permissions
|
||||
|
||||
|
||||
class IsGuestUpload(permissions.BasePermission):
|
||||
"""
|
||||
Special permission class for the ability to upload attachments
|
||||
to an unauthorized user using a ticket token
|
||||
"""
|
||||
def has_permission(self, request, view):
|
||||
if request.method in ('HEAD', 'OPTIONS', 'POST',):
|
||||
return True
|
||||
|
||||
return request.user.is_authenticated
|
@ -1,11 +1,59 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from .models import Archive
|
||||
from .models import Archive, Platform, Ticket
|
||||
|
||||
|
||||
class TimestampField(serializers.Field):
|
||||
def to_representation(self, value):
|
||||
return value.timestamp()
|
||||
|
||||
|
||||
class JsTimestampField(serializers.Field):
|
||||
def to_representation(self, value):
|
||||
return round(value.timestamp()*1000)
|
||||
|
||||
|
||||
class PublicArchiveUploadSerializer(serializers.ModelSerializer):
|
||||
ticket = serializers.ReadOnlyField(source='ticket.token')
|
||||
|
||||
class Meta:
|
||||
model = Archive
|
||||
fields = ['file', 'ticket']
|
||||
|
||||
|
||||
class ArchiveSerializer(serializers.ModelSerializer):
|
||||
time_create = JsTimestampField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Archive
|
||||
fields = ['id', 'file', 'ticket', 'time_create']
|
||||
|
||||
def to_representation(self, instance):
|
||||
print(int(round(instance.time_create.timestamp())))
|
||||
return super().to_representation(instance)
|
||||
|
||||
|
||||
class PlatformSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Platform
|
||||
fields = ['id', 'name', 'pretty_name']
|
||||
|
||||
|
||||
class TicketSerializer(serializers.ModelSerializer):
|
||||
time_create = JsTimestampField(read_only=True)
|
||||
time_update = JsTimestampField(read_only=True)
|
||||
token = serializers.UUIDField(read_only=True)
|
||||
user = serializers.ReadOnlyField(source='user.username')
|
||||
|
||||
class Meta:
|
||||
model = Ticket
|
||||
fields = [
|
||||
'id',
|
||||
'number',
|
||||
'resolved',
|
||||
'token',
|
||||
'attempts',
|
||||
'platform',
|
||||
'time_create',
|
||||
'time_update',
|
||||
'user'
|
||||
]
|
||||
|
@ -7,7 +7,9 @@ from . import views
|
||||
app_name = 'collector'
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
router.register(r'archives', views.PublicArchiveUploadViewSet)
|
||||
router.register(r'archives', views.ArchiveViewSet)
|
||||
router.register(r'platforms', views.PlatformViewSet)
|
||||
router.register(r'tickets', views.TicketViewSet)
|
||||
|
||||
urlpatterns = [
|
||||
|
||||
|
@ -3,8 +3,8 @@ import os
|
||||
|
||||
def logs_dir_path(instance, filename):
|
||||
# file will be uploaded to
|
||||
# MEDIA_ROOT_FOR_SENSITIVE_FILES/<ticket>/<filename>
|
||||
return f'{instance.ticket}/{filename}'
|
||||
# MEDIA_ROOT_FOR_SENSITIVE_FILES/<ticket-token>/<filename>
|
||||
return f'{instance.ticket.number}/{filename}'
|
||||
|
||||
|
||||
def get_file_size(file_path, unit='bytes'):
|
||||
|
@ -1,5 +1,5 @@
|
||||
import json
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.exceptions import ValidationError, ObjectDoesNotExist
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import FileResponse, JsonResponse
|
||||
from django.views import generic
|
||||
@ -8,17 +8,25 @@ from django.urls import reverse_lazy
|
||||
from django.db.models import Q
|
||||
|
||||
from rest_framework import status
|
||||
from rest_framework.response import Response
|
||||
# from rest_framework.decorators import action
|
||||
from rest_framework.parsers import FormParser, MultiPartParser
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
|
||||
from rest_framework import mixins
|
||||
from rest_framework.viewsets import GenericViewSet
|
||||
# from rest_framework import mixins
|
||||
from rest_framework import viewsets
|
||||
|
||||
from .models import Archive, Ticket
|
||||
from .models import Archive, Ticket, Platform
|
||||
from .forms import TicketForm
|
||||
from .utils import PageTitleViewMixin, is_ajax
|
||||
from .permissions import IsGuestUpload
|
||||
|
||||
from .serializers import PublicArchiveUploadSerializer
|
||||
from .serializers import (
|
||||
PublicArchiveUploadSerializer,
|
||||
ArchiveSerializer,
|
||||
PlatformSerializer,
|
||||
TicketSerializer
|
||||
)
|
||||
|
||||
|
||||
class ArchiveHandlerView(LoginRequiredMixin, SingleObjectMixin, generic.View):
|
||||
@ -174,15 +182,16 @@ class DeleteTicketHandler(SingleObjectMixin, generic.View):
|
||||
)
|
||||
|
||||
|
||||
class PublicArchiveUploadViewSet(mixins.CreateModelMixin, GenericViewSet):
|
||||
class ArchiveViewSet(viewsets.ModelViewSet):
|
||||
queryset = Archive.objects.order_by('-time_create')
|
||||
serializer_class = PublicArchiveUploadSerializer
|
||||
serializer_class = ArchiveSerializer
|
||||
parser_classes = (MultiPartParser, FormParser)
|
||||
permission_classes = (IsGuestUpload, )
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
# ! upload-token protection:
|
||||
upload_token = request.headers.get('upload-token', '')
|
||||
if upload_token:
|
||||
if not request.user.is_authenticated and upload_token:
|
||||
try:
|
||||
bound_ticket = Ticket.objects.get(token=upload_token)
|
||||
if bound_ticket.resolved:
|
||||
@ -198,13 +207,15 @@ class PublicArchiveUploadViewSet(mixins.CreateModelMixin, GenericViewSet):
|
||||
bound_ticket.attempts -= 1
|
||||
bound_ticket.save()
|
||||
# ? mixin bound ticket to request.data from user
|
||||
request.data['ticket'] = bound_ticket
|
||||
except ValidationError:
|
||||
request.data['ticket'] = bound_ticket.number
|
||||
# ? change serializer for guest user
|
||||
self.serializer_class = PublicArchiveUploadSerializer
|
||||
except (ValidationError, ObjectDoesNotExist,):
|
||||
return Response(
|
||||
{'error': f'token {upload_token} is not valid'},
|
||||
status=status.HTTP_403_FORBIDDEN
|
||||
)
|
||||
else:
|
||||
elif not request.user.is_authenticated:
|
||||
return Response(
|
||||
{'error': 'Header Upload-Token is required'},
|
||||
status=status.HTTP_401_UNAUTHORIZED
|
||||
@ -220,5 +231,16 @@ class PublicArchiveUploadViewSet(mixins.CreateModelMixin, GenericViewSet):
|
||||
headers=headers
|
||||
)
|
||||
|
||||
def perform_create(self, serializer):
|
||||
serializer.save(ticket=self.request.data['ticket'])
|
||||
|
||||
class PlatformViewSet(viewsets.ModelViewSet):
|
||||
queryset = Platform.objects.all()
|
||||
lookup_field = 'name'
|
||||
serializer_class = PlatformSerializer
|
||||
permission_classes = (IsAuthenticated, )
|
||||
|
||||
|
||||
class TicketViewSet(viewsets.ModelViewSet):
|
||||
queryset = Ticket.objects.order_by('-time_create')
|
||||
lookup_field = 'number'
|
||||
serializer_class = TicketSerializer
|
||||
permission_classes = (IsAuthenticated, )
|
||||
|
@ -135,3 +135,18 @@ MEDIA_URL_FOR_SENSITIVE_FILES = '/archives/'
|
||||
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
|
||||
|
||||
CRISPY_TEMPLATE_PACK = "bootstrap5"
|
||||
|
||||
# https://www.django-rest-framework.org/api-guide/settings/
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_RENDERER_CLASSES': [
|
||||
'rest_framework.renderers.JSONRenderer',
|
||||
'rest_framework.renderers.BrowsableAPIRenderer',
|
||||
],
|
||||
'DEFAULT_PARSER_CLASSES': [
|
||||
'rest_framework.parsers.JSONParser',
|
||||
'rest_framework.renderers.BrowsableAPIRenderer',
|
||||
'rest_framework.parsers.MultiPartParser'
|
||||
],
|
||||
# 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', # noqa:E501
|
||||
# 'PAGE_SIZE': 3,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user