1111from django .db .models .functions import Trunc
1212from django .http import FileResponse
1313from django .utils .timezone import now
14- from drf_spectacular .types import OpenApiTypes
15- from drf_spectacular .utils import extend_schema as add_docs
16- from drf_spectacular .utils import inline_serializer
1714from elasticsearch_dsl import Q as QElastic
1815from elasticsearch_dsl import Search
19- from rest_framework import serializers as rfs
2016from rest_framework import status , viewsets
2117from rest_framework .decorators import action , api_view
2218from rest_framework .exceptions import NotFound , PermissionDenied , ValidationError
8480# REST API endpoints
8581
8682
87- @add_docs (
88- description = """
89- This is useful to avoid repeating the same analysis multiple times.
90- By default this API checks if there are existing analysis related to the md5 in
91- status "running" or "reported_without_fails"
92- Also, you need to specify the analyzers needed because, otherwise, it is
93- highly probable that you won't get all the results that you expect""" ,
94- request = JobAvailabilitySerializer ,
95- responses = {
96- 200 : inline_serializer (
97- name = "AskAnalysisAvailabilitySuccessResponse" ,
98- fields = {
99- "status" : rfs .StringRelatedField (),
100- "job_id" : rfs .StringRelatedField (),
101- "analyzers_to_execute" : OpenApiTypes .OBJECT ,
102- },
103- ),
104- },
105- )
10683@deprecated_endpoint (deprecation_date = "01-07-2023" )
10784@api_view (["POST" ])
10885def ask_analysis_availability (request ):
@@ -137,17 +114,6 @@ def ask_analysis_availability(request):
137114 )
138115
139116
140- @add_docs (
141- description = """
142- This is useful to avoid repeating the same analysis multiple times.
143- By default this API checks if there are existing analysis related to the md5 in
144- status "running" or "reported_without_fails"
145- Also, you need to specify the analyzers needed because, otherwise, it is
146- highly probable that you won't get all the results that you expect.
147- NOTE: This API is similar to ask_analysis_availability, but it allows multiple
148- md5s to be checked at the same time.""" ,
149- responses = {200 : JobAvailabilitySerializer (many = True )},
150- )
151117@api_view (["POST" ])
152118def ask_multi_analysis_availability (request ):
153119 """
@@ -182,12 +148,6 @@ def ask_multi_analysis_availability(request):
182148 )
183149
184150
185- @add_docs (
186- description = "This endpoint allows to start a Job related for a single File."
187- " Retained for retro-compatibility" ,
188- request = FileJobSerializer ,
189- responses = {200 : JobResponseSerializer (many = True )},
190- )
191151@api_view (["POST" ])
192152def analyze_file (request ):
193153 """
@@ -197,6 +157,8 @@ def analyze_file(request):
197157 specified analyzers. The file-related information and analyzers should be provided
198158 in the request data.
199159
160+ Retained for retro-compatibility
161+
200162 Parameters:
201163 - request (POST): Contains file data and analyzer details.
202164
@@ -215,24 +177,6 @@ def analyze_file(request):
215177 )
216178
217179
218- @add_docs (
219- description = "This endpoint allows to start Jobs related to multiple Files" ,
220- # It should be better to link the doc to the related MultipleFileAnalysisSerializer.
221- # It is not straightforward because you can't just add a class
222- # which extends a ListSerializer.
223- # Follow this doc to try to find a fix:
224- # https://drf-spectacular.readthedocs.io/en/latest/customization.html#declare-serializer-magic-with
225- # -openapiserializerextension
226- request = inline_serializer (
227- name = "MultipleFilesSerializer" ,
228- fields = {
229- "files" : rfs .ListField (child = rfs .FileField ()),
230- "file_names" : rfs .ListField (child = rfs .CharField ()),
231- "file_mimetypes" : rfs .ListField (child = rfs .CharField ()),
232- },
233- ),
234- responses = {200 : JobResponseSerializer },
235- )
236180@api_view (["POST" ])
237181def analyze_multiple_files (request ):
238182 """
@@ -260,12 +204,6 @@ def analyze_multiple_files(request):
260204 )
261205
262206
263- @add_docs (
264- description = "This endpoint allows to start a Job related to an observable. "
265- "Retained for retro-compatibility" ,
266- request = ObservableAnalysisSerializer ,
267- responses = {200 : JobResponseSerializer },
268- )
269207@api_view (["POST" ])
270208def analyze_observable (request ):
271209 """
@@ -275,6 +213,8 @@ def analyze_observable(request):
275213 and sends it to the specified analyzers. The observable-related information and analyzers should be
276214 provided in the request data.
277215
216+ Retained for retro-compatibility
217+
278218 Parameters:
279219 - request (POST): Contains observable data and analyzer details.
280220
@@ -293,20 +233,6 @@ def analyze_observable(request):
293233 )
294234
295235
296- @add_docs (
297- description = """This endpoint allows to start Jobs related to multiple observables.
298- Observable parameter must be composed like this:
299- [(<observable_classification>, <observable_name>), ...]""" ,
300- request = inline_serializer (
301- name = "MultipleObservableSerializer" ,
302- fields = {
303- "observables" : rfs .ListField (
304- child = rfs .ListField (max_length = 2 , min_length = 2 )
305- )
306- },
307- ),
308- responses = {200 : JobResponseSerializer },
309- )
310236@api_view (["POST" ])
311237def analyze_multiple_observables (request ):
312238 """
@@ -339,13 +265,6 @@ def analyze_multiple_observables(request):
339265 )
340266
341267
342- @add_docs (
343- description = """
344- REST endpoint to fetch list of job comments or
345- retrieve/delete a job comment with job comment ID.
346- Requires authentication.
347- """
348- )
349268class CommentViewSet (ModelViewSet ):
350269 """
351270 CommentViewSet provides the following actions:
@@ -407,12 +326,6 @@ def get_queryset(self):
407326 return queryset .visible_for_user (self .request .user )
408327
409328
410- @add_docs (
411- description = """
412- REST endpoint to fetch list of jobs or retrieve/delete a job with job ID.
413- Requires authentication.
414- """
415- )
416329class JobViewSet (ReadAndDeleteOnlyViewSet , SerializerActionMixin ):
417330 """
418331 JobViewSet provides the following actions:
@@ -590,13 +503,6 @@ def rescan(self, request, pk=None):
590503 logger .info (f"rescan request for job: { pk } generated job: { new_job .pk } " )
591504 return Response (data = {"id" : new_job .pk }, status = status .HTTP_202_ACCEPTED )
592505
593- @add_docs (
594- description = "Kill running job by closing celery tasks and marking as killed" ,
595- request = None ,
596- responses = {
597- 204 : None ,
598- },
599- )
600506 @action (detail = True , methods = ["patch" ])
601507 def kill (self , request , pk = None ):
602508 """
@@ -617,11 +523,6 @@ def kill(self, request, pk=None):
617523 job .kill_if_ongoing ()
618524 return Response (status = status .HTTP_204_NO_CONTENT )
619525
620- @add_docs (
621- description = "Download file/sample associated with a job" ,
622- request = None ,
623- responses = {200 : OpenApiTypes .BINARY , 400 : None },
624- )
625526 @action (detail = True , methods = ["get" ])
626527 def download_sample (self , request , pk = None ):
627528 """
@@ -650,7 +551,6 @@ def download_sample(self, request, pk=None):
650551 as_attachment = True ,
651552 )
652553
653- @add_docs (description = "Pivot a job" )
654554 @action (
655555 detail = True , methods = ["post" ]
656556 ) # , url_path="pivot-(?P<pivot_config_pk>\d+)")
@@ -996,12 +896,6 @@ def __parse_range(request):
996896 return parse_humanized_range (range_str )
997897
998898
999- @add_docs (
1000- description = """
1001- REST endpoint to perform CRUD operations on ``Tag`` model.
1002- Requires authentication.
1003- """
1004- )
1005899class TagViewSet (viewsets .ModelViewSet ):
1006900 """
1007901 A viewset that provides CRUD (Create, Read, Update, Delete) operations
@@ -1077,18 +971,6 @@ def get_permissions(self):
1077971 return permissions
1078972
1079973
1080- @add_docs (
1081- description = """This endpoint allows organization owners
1082- and members to view plugin state.""" ,
1083- responses = {
1084- 200 : inline_serializer (
1085- name = "PluginStateViewerResponseSerializer" ,
1086- fields = {
1087- "data" : rfs .JSONField (),
1088- },
1089- ),
1090- },
1091- )
1092974@api_view (["GET" ])
1093975def plugin_state_viewer (request ):
1094976 """
@@ -1260,13 +1142,6 @@ def perform_retry(report: AbstractReport):
12601142 )
12611143 runner ()
12621144
1263- @add_docs (
1264- description = "Kill running plugin by closing celery task and marking as killed" ,
1265- request = None ,
1266- responses = {
1267- 204 : None ,
1268- },
1269- )
12701145 @action (detail = False , methods = ["patch" ])
12711146 def kill (self , request , job_id , report_id ):
12721147 """
@@ -1301,13 +1176,6 @@ def kill(self, request, job_id, report_id):
13011176 self .perform_kill (report )
13021177 return Response (status = status .HTTP_204_NO_CONTENT )
13031178
1304- @add_docs (
1305- description = "Retry a plugin run if it failed/was killed previously" ,
1306- request = None ,
1307- responses = {
1308- 204 : None ,
1309- },
1310- )
13111179 @action (detail = False , methods = ["patch" ])
13121180 def retry (self , request , job_id , report_id ):
13131181 """
@@ -1372,11 +1240,6 @@ class AbstractConfigViewSet(
13721240 ordering = ["name" ]
13731241 lookup_field = "name"
13741242
1375- @add_docs (
1376- description = "Disable/Enable plugin for your organization" ,
1377- request = None ,
1378- responses = {201 : {}, 202 : {}},
1379- )
13801243 @action (
13811244 methods = ["post" ],
13821245 detail = True ,
@@ -1472,19 +1335,6 @@ def get_queryset(self):
14721335 "python_module__parameters"
14731336 )
14741337
1475- @add_docs (
1476- description = "Health Check: "
1477- "if server instance associated with plugin is up or not" ,
1478- request = None ,
1479- responses = {
1480- 200 : inline_serializer (
1481- name = "PluginHealthCheckSuccessResponse" ,
1482- fields = {
1483- "status" : rfs .BooleanField (allow_null = True ),
1484- },
1485- ),
1486- },
1487- )
14881338 @action (
14891339 methods = ["get" ],
14901340 detail = True ,
@@ -1569,12 +1419,6 @@ def pull(self, request, name=None):
15691419 return Response (data = {"status" : update_status }, status = status .HTTP_200_OK )
15701420
15711421
1572- @add_docs (
1573- description = """
1574- REST endpoint to fetch list of PluginConfig or retrieve/delete a CustomConfig.
1575- Requires authentication. Allows access to only authorized CustomConfigs.
1576- """
1577- )
15781422class PluginConfigViewSet (ModelWithOwnershipViewSet ):
15791423 """
15801424 A viewset for managing `PluginConfig` objects with ownership-based access control.
@@ -1690,34 +1534,8 @@ def create(self, request, name=None):
16901534 return Response (serializer .data , status = status .HTTP_201_CREATED )
16911535
16921536
1693- description = (
1694- """This endpoint allows users to search analyzer, connector and pivot reports. ELASTIC REQUIRED""" ,
1695- )
1696- responses = (
1697- {
1698- 200 : inline_serializer (
1699- name = "ElasticResponseSerializer" ,
1700- fields = {
1701- "data" : rfs .JSONField (),
1702- },
1703- ),
1704- },
1705- )
1706-
1707-
17081537class ElasticSearchView (GenericAPIView ):
17091538
1710- @add_docs (
1711- description = """This endpoint allows users to search analyzer, connector and pivot reports. ELASTIC REQUIRED""" ,
1712- responses = {
1713- 200 : inline_serializer (
1714- name = "ElasticResponseSerializer" ,
1715- fields = {
1716- "data" : rfs .JSONField (),
1717- },
1718- ),
1719- },
1720- )
17211539 def get (self , request ):
17221540 """
17231541 View enabled only with elastic. Allow to perform queries in the Plugin reports.
0 commit comments