Skip to content

Commit

Permalink
Merge branch 'cancel-rendering-jobs' into 'main'
Browse files Browse the repository at this point in the history
Cancel rendering jobs

See merge request reportcreator/reportcreator!746
  • Loading branch information
MWedl committed Nov 5, 2024
2 parents 5ae0043 + 9fae5b3 commit 4b79ec2
Show file tree
Hide file tree
Showing 37 changed files with 945 additions and 469 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## Upcoming
* Experimental plugin system
* Disable static file compression
* Allow to cancel PDF rendering requests
* Show PDF render timing information


## v2024.81 - 2024-10-25
Expand Down
6 changes: 3 additions & 3 deletions api/src/reportcreator_api/conf/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -551,9 +551,9 @@
# Execute tasks locally, if no broker is configured
CELERY_TASK_ALWAYS_EAGER = not CELERY_BROKER_URL

# Time limits are only enforced if a broker is configured and an external worker is used (but not in eager mode).
# Self-hosted SysReptor instances use the eager mode by default, resulting in no PDF rendering time limits being applied.
PDF_RENDERING_TIME_LIMIT = config('PDF_RENDERING_TIME_LIMIT', cast=int, default=60)
# Maximum time a PDF rendering task is allowed to run. If a task takes longer, it gets cancelled.
# Set to 0 to disable the time limit
PDF_RENDERING_TIME_LIMIT = config('PDF_RENDERING_TIME_LIMIT', cast=int, default=5 * 60)


# History
Expand Down
7 changes: 6 additions & 1 deletion api/src/reportcreator_api/pentests/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
ReportSection,
ReviewStatus,
)
from reportcreator_api.utils.error_messages import ErrorMessage, MessageLevel, MessageLocationInfo, MessageLocationType
from reportcreator_api.tasks.rendering.error_messages import (
ErrorMessage,
MessageLevel,
MessageLocationInfo,
MessageLocationType,
)
from reportcreator_api.utils.utils import find_all_indices


Expand Down
2 changes: 1 addition & 1 deletion api/src/reportcreator_api/pentests/customfields/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
FieldOrigin,
ObjectField,
)
from reportcreator_api.utils.error_messages import format_path
from reportcreator_api.tasks.rendering.error_messages import format_path
from reportcreator_api.utils.utils import is_date_string, is_uuid


Expand Down
2 changes: 1 addition & 1 deletion api/src/reportcreator_api/pentests/models/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@
LockableMixin,
ReviewStatus,
)
from reportcreator_api.tasks.rendering.error_messages import ErrorMessage
from reportcreator_api.users.models import PentestUser
from reportcreator_api.utils.decorators import cache
from reportcreator_api.utils.error_messages import ErrorMessage
from reportcreator_api.utils.history import HistoricalRecords
from reportcreator_api.utils.models import BaseModel

Expand Down
5 changes: 3 additions & 2 deletions api/src/reportcreator_api/pentests/serializers/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
from rest_framework import serializers

from reportcreator_api.pentests.models import LockInfo
from reportcreator_api.tasks.rendering.error_messages import MessageLevel, MessageLocationType
from reportcreator_api.users.serializers import PentestUserSerializer, RelatedUserSerializer
from reportcreator_api.utils.error_messages import MessageLevel, MessageLocationType


class LockInfoSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -72,8 +72,9 @@ class ExportSerializer(serializers.Serializer):


class PdfResponseSerializer(serializers.Serializer):
messages = ErrorMessageSerializer(many=True, read_only=True)
pdf = extend_schema_field(OpenApiTypes.BYTE)(serializers.CharField(allow_null=True, read_only=True))
messages = ErrorMessageSerializer(many=True, read_only=True)
timings = serializers.DictField(child=serializers.FloatField(min_value=0), read_only=True)


class HistoryTimelineSerializer(serializers.Serializer):
Expand Down
17 changes: 8 additions & 9 deletions api/src/reportcreator_api/pentests/views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import contextlib
import functools
import operator
from base64 import b64decode
from datetime import datetime, timedelta
from io import BytesIO
from uuid import UUID, uuid4
Expand Down Expand Up @@ -587,7 +586,7 @@ async def preview(self, request, *args, **kwargs):
},
project_type=instance,
)
return Response(data=pdf_preview)
return Response(data=pdf_preview.to_dict())

def perform_export(self, instances):
return export_project_types(instances)
Expand Down Expand Up @@ -733,7 +732,7 @@ async def preview(self, request, *args, **kwargs):
options = serializer.validated_data

pdf_preview = await render_pdf(project=instance, **options)
return Response(data=pdf_preview)
return Response(data=pdf_preview.to_dict())

@extend_schema(responses={(200, 'application/pdf'): OpenApiTypes.BINARY, 400: PdfResponseSerializer})
@action(detail=True, methods=['post'], throttle_scope='pdf')
Expand All @@ -748,10 +747,10 @@ async def generate(self, request, *args, **kwargs):
password=options.get('password'),
can_compress_pdf=True,
)
if data.get('pdf'):
return FileResponseAsync(BytesIO(b64decode(data['pdf'])), content_type='application/pdf')
if data.pdf:
return FileResponseAsync(BytesIO(data.pdf), content_type='application/pdf')
else:
return Response(data=data, status=status.HTTP_400_BAD_REQUEST)
return Response(data=data.to_dict(), status=status.HTTP_400_BAD_REQUEST)

@extend_schema(responses={200: PentestProjectDetailSerializer, 400: ErrorMessageSerializer(many=True)})
@action(detail=True, methods=['post'], throttle_scope='pdf')
Expand Down Expand Up @@ -1096,10 +1095,10 @@ def sort(self, request, *arg, **kwargs):
async def export_pdf(self, request, *args, **kwargs):
instance = await self.aget_object()
data = await render_note_to_pdf(note=instance, request=request)
if data.get('pdf'):
return FileResponseAsync(BytesIO(b64decode(data['pdf'])), content_type='application/pdf')
if data.pdf:
return FileResponseAsync(BytesIO(data.pdf), content_type='application/pdf')
else:
return Response(data=data, status=status.HTTP_400_BAD_REQUEST)
return Response(data=data.to_dict(), status=status.HTTP_400_BAD_REQUEST)

@extend_schema(responses={(200, 'application/octet-stream'): OpenApiTypes.BINARY})
@action(detail=False, url_path='export', methods=['post'])
Expand Down
Loading

0 comments on commit 4b79ec2

Please sign in to comment.