binalyze-air-sdk 1.0.1__py3-none-any.whl → 1.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- binalyze_air/__init__.py +77 -77
- binalyze_air/apis/__init__.py +67 -27
- binalyze_air/apis/acquisitions.py +107 -0
- binalyze_air/apis/api_tokens.py +49 -0
- binalyze_air/apis/assets.py +161 -0
- binalyze_air/apis/audit_logs.py +26 -0
- binalyze_air/apis/{authentication.py → auth.py} +29 -27
- binalyze_air/apis/auto_asset_tags.py +79 -75
- binalyze_air/apis/backup.py +177 -0
- binalyze_air/apis/baseline.py +46 -0
- binalyze_air/apis/cases.py +225 -0
- binalyze_air/apis/cloud_forensics.py +116 -0
- binalyze_air/apis/event_subscription.py +96 -96
- binalyze_air/apis/evidence.py +249 -53
- binalyze_air/apis/interact.py +153 -36
- binalyze_air/apis/investigation_hub.py +234 -0
- binalyze_air/apis/license.py +104 -0
- binalyze_air/apis/logger.py +83 -0
- binalyze_air/apis/multipart_upload.py +201 -0
- binalyze_air/apis/notifications.py +115 -0
- binalyze_air/apis/organizations.py +267 -0
- binalyze_air/apis/params.py +44 -39
- binalyze_air/apis/policies.py +186 -0
- binalyze_air/apis/preset_filters.py +79 -0
- binalyze_air/apis/recent_activities.py +71 -0
- binalyze_air/apis/relay_server.py +104 -0
- binalyze_air/apis/settings.py +395 -27
- binalyze_air/apis/tasks.py +80 -0
- binalyze_air/apis/triage.py +197 -0
- binalyze_air/apis/user_management.py +183 -74
- binalyze_air/apis/webhook_executions.py +50 -0
- binalyze_air/apis/webhooks.py +322 -230
- binalyze_air/base.py +207 -133
- binalyze_air/client.py +217 -1337
- binalyze_air/commands/__init__.py +175 -145
- binalyze_air/commands/acquisitions.py +661 -387
- binalyze_air/commands/api_tokens.py +55 -0
- binalyze_air/commands/assets.py +324 -362
- binalyze_air/commands/{authentication.py → auth.py} +36 -36
- binalyze_air/commands/auto_asset_tags.py +230 -230
- binalyze_air/commands/backup.py +47 -0
- binalyze_air/commands/baseline.py +32 -396
- binalyze_air/commands/cases.py +609 -602
- binalyze_air/commands/cloud_forensics.py +88 -0
- binalyze_air/commands/event_subscription.py +101 -101
- binalyze_air/commands/evidences.py +918 -988
- binalyze_air/commands/interact.py +172 -58
- binalyze_air/commands/investigation_hub.py +315 -0
- binalyze_air/commands/license.py +183 -0
- binalyze_air/commands/logger.py +126 -0
- binalyze_air/commands/multipart_upload.py +363 -0
- binalyze_air/commands/notifications.py +45 -0
- binalyze_air/commands/organizations.py +200 -221
- binalyze_air/commands/policies.py +175 -203
- binalyze_air/commands/preset_filters.py +55 -0
- binalyze_air/commands/recent_activities.py +32 -0
- binalyze_air/commands/relay_server.py +144 -0
- binalyze_air/commands/settings.py +431 -29
- binalyze_air/commands/tasks.py +95 -56
- binalyze_air/commands/triage.py +224 -360
- binalyze_air/commands/user_management.py +351 -126
- binalyze_air/commands/webhook_executions.py +77 -0
- binalyze_air/config.py +244 -244
- binalyze_air/exceptions.py +49 -49
- binalyze_air/http_client.py +426 -305
- binalyze_air/models/__init__.py +287 -285
- binalyze_air/models/acquisitions.py +365 -250
- binalyze_air/models/api_tokens.py +73 -0
- binalyze_air/models/assets.py +438 -438
- binalyze_air/models/audit.py +247 -272
- binalyze_air/models/audit_logs.py +14 -0
- binalyze_air/models/{authentication.py → auth.py} +69 -69
- binalyze_air/models/auto_asset_tags.py +227 -116
- binalyze_air/models/backup.py +138 -0
- binalyze_air/models/baseline.py +231 -231
- binalyze_air/models/cases.py +275 -275
- binalyze_air/models/cloud_forensics.py +145 -0
- binalyze_air/models/event_subscription.py +170 -171
- binalyze_air/models/evidence.py +65 -65
- binalyze_air/models/evidences.py +367 -348
- binalyze_air/models/interact.py +266 -135
- binalyze_air/models/investigation_hub.py +265 -0
- binalyze_air/models/license.py +150 -0
- binalyze_air/models/logger.py +83 -0
- binalyze_air/models/multipart_upload.py +352 -0
- binalyze_air/models/notifications.py +138 -0
- binalyze_air/models/organizations.py +293 -293
- binalyze_air/models/params.py +153 -127
- binalyze_air/models/policies.py +260 -249
- binalyze_air/models/preset_filters.py +79 -0
- binalyze_air/models/recent_activities.py +70 -0
- binalyze_air/models/relay_server.py +121 -0
- binalyze_air/models/settings.py +538 -84
- binalyze_air/models/tasks.py +215 -149
- binalyze_air/models/triage.py +141 -142
- binalyze_air/models/user_management.py +200 -97
- binalyze_air/models/webhook_executions.py +33 -0
- binalyze_air/queries/__init__.py +121 -133
- binalyze_air/queries/acquisitions.py +155 -155
- binalyze_air/queries/api_tokens.py +46 -0
- binalyze_air/queries/assets.py +186 -105
- binalyze_air/queries/audit.py +400 -416
- binalyze_air/queries/{authentication.py → auth.py} +55 -55
- binalyze_air/queries/auto_asset_tags.py +59 -59
- binalyze_air/queries/backup.py +66 -0
- binalyze_air/queries/baseline.py +21 -185
- binalyze_air/queries/cases.py +292 -292
- binalyze_air/queries/cloud_forensics.py +137 -0
- binalyze_air/queries/event_subscription.py +54 -54
- binalyze_air/queries/evidence.py +139 -139
- binalyze_air/queries/evidences.py +279 -279
- binalyze_air/queries/interact.py +140 -28
- binalyze_air/queries/investigation_hub.py +329 -0
- binalyze_air/queries/license.py +85 -0
- binalyze_air/queries/logger.py +58 -0
- binalyze_air/queries/multipart_upload.py +180 -0
- binalyze_air/queries/notifications.py +71 -0
- binalyze_air/queries/organizations.py +222 -222
- binalyze_air/queries/params.py +154 -115
- binalyze_air/queries/policies.py +149 -149
- binalyze_air/queries/preset_filters.py +60 -0
- binalyze_air/queries/recent_activities.py +44 -0
- binalyze_air/queries/relay_server.py +42 -0
- binalyze_air/queries/settings.py +533 -20
- binalyze_air/queries/tasks.py +125 -81
- binalyze_air/queries/triage.py +230 -230
- binalyze_air/queries/user_management.py +193 -83
- binalyze_air/queries/webhook_executions.py +39 -0
- binalyze_air_sdk-1.0.3.dist-info/METADATA +752 -0
- binalyze_air_sdk-1.0.3.dist-info/RECORD +132 -0
- {binalyze_air_sdk-1.0.1.dist-info → binalyze_air_sdk-1.0.3.dist-info}/WHEEL +1 -1
- binalyze_air/apis/endpoints.py +0 -22
- binalyze_air/apis/evidences.py +0 -216
- binalyze_air/apis/users.py +0 -68
- binalyze_air/commands/users.py +0 -101
- binalyze_air/models/endpoints.py +0 -76
- binalyze_air/models/users.py +0 -82
- binalyze_air/queries/endpoints.py +0 -25
- binalyze_air/queries/users.py +0 -69
- binalyze_air_sdk-1.0.1.dist-info/METADATA +0 -635
- binalyze_air_sdk-1.0.1.dist-info/RECORD +0 -82
- {binalyze_air_sdk-1.0.1.dist-info → binalyze_air_sdk-1.0.3.dist-info}/top_level.txt +0 -0
@@ -1,58 +1,172 @@
|
|
1
|
-
"""
|
2
|
-
Interact commands for the Binalyze AIR SDK.
|
3
|
-
"""
|
4
|
-
|
5
|
-
from typing import Dict, Any, Union
|
6
|
-
|
7
|
-
|
8
|
-
from ..
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
payload = self.request
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
1
|
+
"""
|
2
|
+
Interact commands for the Binalyze AIR SDK.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import Dict, Any, Union, List, Optional
|
6
|
+
import json
|
7
|
+
|
8
|
+
from ..base import Command
|
9
|
+
from ..models.interact import (
|
10
|
+
InteractiveShellTaskResponse, AssignInteractiveShellTaskRequest,
|
11
|
+
ExecuteCommandRequest, ExecuteCommandResponse, LibraryFile,
|
12
|
+
InterruptCommandRequest, CloseSessionRequest, FileExistsResponse
|
13
|
+
)
|
14
|
+
from ..http_client import HTTPClient
|
15
|
+
|
16
|
+
|
17
|
+
class AssignInteractiveShellTaskCommand(Command[InteractiveShellTaskResponse]):
|
18
|
+
"""Command to assign an interactive shell task."""
|
19
|
+
|
20
|
+
def __init__(self, http_client: HTTPClient, request: Union[AssignInteractiveShellTaskRequest, Dict[str, Any]]):
|
21
|
+
self.http_client = http_client
|
22
|
+
self.request = request
|
23
|
+
|
24
|
+
def execute(self) -> InteractiveShellTaskResponse:
|
25
|
+
"""Execute the command to assign an interactive shell task."""
|
26
|
+
# Handle both dict and model objects
|
27
|
+
if isinstance(self.request, dict):
|
28
|
+
payload = self.request
|
29
|
+
else:
|
30
|
+
payload = self.request.model_dump(exclude_none=True, by_alias=True)
|
31
|
+
|
32
|
+
response = self.http_client.post("interact/shell/assign-task", json_data=payload)
|
33
|
+
|
34
|
+
if response.get("success"):
|
35
|
+
result_data = response.get("result", {})
|
36
|
+
# Use Pydantic parsing with proper field aliasing
|
37
|
+
return InteractiveShellTaskResponse.model_validate(result_data)
|
38
|
+
|
39
|
+
raise Exception(f"Failed to assign interactive shell task: {response.get('errors', [])}")
|
40
|
+
|
41
|
+
|
42
|
+
# LIBRARY FILE COMMANDS
|
43
|
+
|
44
|
+
class UploadFileToLibraryCommand(Command[Optional[LibraryFile]]):
|
45
|
+
"""Command to upload a file to the library."""
|
46
|
+
|
47
|
+
def __init__(self, http_client: HTTPClient, file_content: bytes, filename: str, organization_ids: Optional[List[int]] = None):
|
48
|
+
self.http_client = http_client
|
49
|
+
self.file_content = file_content
|
50
|
+
self.filename = filename
|
51
|
+
self.organization_ids = organization_ids
|
52
|
+
|
53
|
+
def execute(self) -> Optional[LibraryFile]:
|
54
|
+
"""Execute the command to upload a file to the library."""
|
55
|
+
# Prepare multipart form data
|
56
|
+
files = {"file": (self.filename, self.file_content)}
|
57
|
+
data = {}
|
58
|
+
|
59
|
+
if self.organization_ids:
|
60
|
+
# API expects organizationIds as JSON string array, not comma-separated
|
61
|
+
data["organizationIds"] = json.dumps(self.organization_ids)
|
62
|
+
|
63
|
+
response = self.http_client.upload_multipart("interact/library/upload", files=files, data=data)
|
64
|
+
|
65
|
+
result_data = response.get("result")
|
66
|
+
# Handle null result properly - API may return null on success
|
67
|
+
if result_data is None:
|
68
|
+
return None
|
69
|
+
|
70
|
+
return LibraryFile.model_validate(result_data)
|
71
|
+
|
72
|
+
|
73
|
+
class DeleteFileFromLibraryCommand(Command[Dict[str, Any]]):
|
74
|
+
"""Command to delete a file from the library."""
|
75
|
+
|
76
|
+
def __init__(self, http_client: HTTPClient, filename: str):
|
77
|
+
self.http_client = http_client
|
78
|
+
self.filename = filename
|
79
|
+
|
80
|
+
def execute(self) -> Dict[str, Any]:
|
81
|
+
"""Execute the command to delete a file from the library."""
|
82
|
+
params = {"filename": self.filename}
|
83
|
+
response = self.http_client.delete("interact/library/delete", params=params)
|
84
|
+
|
85
|
+
return response
|
86
|
+
|
87
|
+
|
88
|
+
# SHELL SESSION COMMANDS
|
89
|
+
|
90
|
+
class ExecuteCommandCommand(Command[ExecuteCommandResponse]):
|
91
|
+
"""Command to execute a command in a shell session."""
|
92
|
+
|
93
|
+
def __init__(self, http_client: HTTPClient, session_id: str, request: Union[ExecuteCommandRequest, Dict[str, Any]]):
|
94
|
+
self.http_client = http_client
|
95
|
+
self.session_id = session_id
|
96
|
+
self.request = request
|
97
|
+
|
98
|
+
def execute(self) -> ExecuteCommandResponse:
|
99
|
+
"""Execute the command in the shell session."""
|
100
|
+
# Handle both dict and model objects
|
101
|
+
if isinstance(self.request, dict):
|
102
|
+
payload = self.request
|
103
|
+
else:
|
104
|
+
payload = self.request.model_dump(exclude_none=True, by_alias=True)
|
105
|
+
|
106
|
+
response = self.http_client.post(
|
107
|
+
f"interact/shell/sessions/{self.session_id}/execute-command",
|
108
|
+
json_data=payload
|
109
|
+
)
|
110
|
+
|
111
|
+
result_data = response.get("result", {})
|
112
|
+
return ExecuteCommandResponse.model_validate(result_data)
|
113
|
+
|
114
|
+
|
115
|
+
class ExecuteAsyncCommandCommand(Command[ExecuteCommandResponse]):
|
116
|
+
"""Command to execute an async command in a shell session."""
|
117
|
+
|
118
|
+
def __init__(self, http_client: HTTPClient, session_id: str, request: Union[ExecuteCommandRequest, Dict[str, Any]]):
|
119
|
+
self.http_client = http_client
|
120
|
+
self.session_id = session_id
|
121
|
+
self.request = request
|
122
|
+
|
123
|
+
def execute(self) -> ExecuteCommandResponse:
|
124
|
+
"""Execute the async command in the shell session."""
|
125
|
+
# Handle both dict and model objects
|
126
|
+
if isinstance(self.request, dict):
|
127
|
+
payload = self.request
|
128
|
+
else:
|
129
|
+
payload = self.request.model_dump(exclude_none=True, by_alias=True)
|
130
|
+
|
131
|
+
response = self.http_client.post(
|
132
|
+
f"interact/shell/sessions/{self.session_id}/execute-async-command",
|
133
|
+
json_data=payload
|
134
|
+
)
|
135
|
+
|
136
|
+
result_data = response.get("result", {})
|
137
|
+
return ExecuteCommandResponse.model_validate(result_data)
|
138
|
+
|
139
|
+
|
140
|
+
class InterruptCommandCommand(Command[Dict[str, Any]]):
|
141
|
+
"""Command to interrupt a command in a shell session."""
|
142
|
+
|
143
|
+
def __init__(self, http_client: HTTPClient, session_id: str, message_id: str):
|
144
|
+
self.http_client = http_client
|
145
|
+
self.session_id = session_id
|
146
|
+
self.message_id = message_id
|
147
|
+
|
148
|
+
def execute(self) -> Dict[str, Any]:
|
149
|
+
"""Execute the command to interrupt a running command."""
|
150
|
+
response = self.http_client.post(
|
151
|
+
f"interact/shell/sessions/{self.session_id}/messages/{self.message_id}/interrupt-command",
|
152
|
+
json_data={}
|
153
|
+
)
|
154
|
+
|
155
|
+
return response
|
156
|
+
|
157
|
+
|
158
|
+
class CloseSessionCommand(Command[Dict[str, Any]]):
|
159
|
+
"""Command to close a shell session."""
|
160
|
+
|
161
|
+
def __init__(self, http_client: HTTPClient, session_id: str):
|
162
|
+
self.http_client = http_client
|
163
|
+
self.session_id = session_id
|
164
|
+
|
165
|
+
def execute(self) -> Dict[str, Any]:
|
166
|
+
"""Execute the command to close a shell session."""
|
167
|
+
response = self.http_client.post(
|
168
|
+
f"interact/shell/sessions/{self.session_id}/close",
|
169
|
+
json_data={}
|
170
|
+
)
|
171
|
+
|
172
|
+
return response
|
@@ -0,0 +1,315 @@
|
|
1
|
+
"""
|
2
|
+
Investigation Hub commands for the Binalyze AIR SDK.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import Dict, Any, List
|
6
|
+
|
7
|
+
from ..base import Command
|
8
|
+
from ..models.investigation_hub import (
|
9
|
+
Investigation, UpdateInvestigationRequest, FlagEvidenceRequest,
|
10
|
+
AddNoteRequest, CreateCommentRequest, InvestigationComment,
|
11
|
+
MarkActivityAsReadRequest, CreateAdvancedFilterRequest,
|
12
|
+
UpdateAdvancedFilterRequest, AdvancedFilter, ExportRequest
|
13
|
+
)
|
14
|
+
from ..http_client import HTTPClient
|
15
|
+
|
16
|
+
|
17
|
+
class UpdateInvestigationCommand(Command[Investigation]):
|
18
|
+
"""Command to update an investigation."""
|
19
|
+
|
20
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str,
|
21
|
+
request: UpdateInvestigationRequest):
|
22
|
+
self.http_client = http_client
|
23
|
+
self.investigation_id = investigation_id
|
24
|
+
self.request = request
|
25
|
+
|
26
|
+
def execute(self) -> Investigation:
|
27
|
+
"""Execute the command."""
|
28
|
+
response = self.http_client.put(
|
29
|
+
f"investigation-hub/investigations/{self.investigation_id}",
|
30
|
+
json_data=self.request.model_dump(by_alias=True, exclude_none=True)
|
31
|
+
)
|
32
|
+
return Investigation(**response["result"])
|
33
|
+
|
34
|
+
|
35
|
+
class DeleteInvestigationCommand(Command[Dict[str, Any]]):
|
36
|
+
"""Command to delete an investigation."""
|
37
|
+
|
38
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str):
|
39
|
+
self.http_client = http_client
|
40
|
+
self.investigation_id = investigation_id
|
41
|
+
|
42
|
+
def execute(self) -> Dict[str, Any]:
|
43
|
+
"""Execute the command."""
|
44
|
+
response = self.http_client.delete(f"investigation-hub/investigations/{self.investigation_id}")
|
45
|
+
return response
|
46
|
+
|
47
|
+
|
48
|
+
class FlagEvidenceCommand(Command[Dict[str, Any]]):
|
49
|
+
"""Command to flag evidence records."""
|
50
|
+
|
51
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str,
|
52
|
+
request: FlagEvidenceRequest):
|
53
|
+
self.http_client = http_client
|
54
|
+
self.investigation_id = investigation_id
|
55
|
+
self.request = request
|
56
|
+
|
57
|
+
def execute(self) -> Dict[str, Any]:
|
58
|
+
"""Execute the command."""
|
59
|
+
response = self.http_client.post(
|
60
|
+
f"investigation-hub/investigations/{self.investigation_id}/section/flag",
|
61
|
+
json_data=self.request.model_dump(by_alias=True, exclude_none=True)
|
62
|
+
)
|
63
|
+
return response
|
64
|
+
|
65
|
+
|
66
|
+
class UnflagEvidenceCommand(Command[Dict[str, Any]]):
|
67
|
+
"""Command to unflag evidence records."""
|
68
|
+
|
69
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str,
|
70
|
+
records: List[Dict[str, Any]], section: str):
|
71
|
+
self.http_client = http_client
|
72
|
+
self.investigation_id = investigation_id
|
73
|
+
self.records = records
|
74
|
+
self.section = section
|
75
|
+
|
76
|
+
def execute(self) -> Dict[str, Any]:
|
77
|
+
"""Execute the command."""
|
78
|
+
payload = {
|
79
|
+
"records": self.records,
|
80
|
+
"section": self.section
|
81
|
+
}
|
82
|
+
response = self.http_client.delete(
|
83
|
+
f"investigation-hub/investigations/{self.investigation_id}/section/flag",
|
84
|
+
json_data=payload
|
85
|
+
)
|
86
|
+
return response
|
87
|
+
|
88
|
+
|
89
|
+
class AddNoteToEvidenceCommand(Command[Dict[str, Any]]):
|
90
|
+
"""Command to add a note to evidence records."""
|
91
|
+
|
92
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str,
|
93
|
+
request: AddNoteRequest):
|
94
|
+
self.http_client = http_client
|
95
|
+
self.investigation_id = investigation_id
|
96
|
+
self.request = request
|
97
|
+
|
98
|
+
def execute(self) -> Dict[str, Any]:
|
99
|
+
"""Execute the command."""
|
100
|
+
response = self.http_client.put(
|
101
|
+
f"investigation-hub/investigations/{self.investigation_id}/notes",
|
102
|
+
json_data=self.request.model_dump(by_alias=True, exclude_none=True)
|
103
|
+
)
|
104
|
+
return response
|
105
|
+
|
106
|
+
|
107
|
+
class CreateCommentCommand(Command[InvestigationComment]):
|
108
|
+
"""Command to create a comment in an investigation."""
|
109
|
+
|
110
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str,
|
111
|
+
request: CreateCommentRequest):
|
112
|
+
self.http_client = http_client
|
113
|
+
self.investigation_id = investigation_id
|
114
|
+
self.request = request
|
115
|
+
|
116
|
+
def execute(self) -> InvestigationComment:
|
117
|
+
"""Execute the command."""
|
118
|
+
response = self.http_client.post(
|
119
|
+
f"investigation-hub/investigations/{self.investigation_id}/comments",
|
120
|
+
json_data=self.request.model_dump(by_alias=True, exclude_none=True)
|
121
|
+
)
|
122
|
+
return InvestigationComment(**response["result"])
|
123
|
+
|
124
|
+
|
125
|
+
class UpdateCommentCommand(Command[InvestigationComment]):
|
126
|
+
"""Command to update a comment in an investigation."""
|
127
|
+
|
128
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str,
|
129
|
+
comment_id: str, content: str):
|
130
|
+
self.http_client = http_client
|
131
|
+
self.investigation_id = investigation_id
|
132
|
+
self.comment_id = comment_id
|
133
|
+
self.content = content
|
134
|
+
|
135
|
+
def execute(self) -> InvestigationComment:
|
136
|
+
"""Execute the command."""
|
137
|
+
payload = {"content": self.content}
|
138
|
+
response = self.http_client.put(
|
139
|
+
f"investigation-hub/investigations/{self.investigation_id}/comments/{self.comment_id}",
|
140
|
+
json_data=payload
|
141
|
+
)
|
142
|
+
return InvestigationComment(**response["result"])
|
143
|
+
|
144
|
+
|
145
|
+
class DeleteCommentCommand(Command[Dict[str, Any]]):
|
146
|
+
"""Command to delete a comment from an investigation."""
|
147
|
+
|
148
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str, comment_id: str):
|
149
|
+
self.http_client = http_client
|
150
|
+
self.investigation_id = investigation_id
|
151
|
+
self.comment_id = comment_id
|
152
|
+
|
153
|
+
def execute(self) -> Dict[str, Any]:
|
154
|
+
"""Execute the command."""
|
155
|
+
response = self.http_client.delete(
|
156
|
+
f"investigation-hub/investigations/{self.investigation_id}/comments/{self.comment_id}"
|
157
|
+
)
|
158
|
+
return response
|
159
|
+
|
160
|
+
|
161
|
+
class MarkActivitiesAsReadCommand(Command[Dict[str, Any]]):
|
162
|
+
"""Command to mark activities as read."""
|
163
|
+
|
164
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str,
|
165
|
+
request: MarkActivityAsReadRequest):
|
166
|
+
self.http_client = http_client
|
167
|
+
self.investigation_id = investigation_id
|
168
|
+
self.request = request
|
169
|
+
|
170
|
+
def execute(self) -> Dict[str, Any]:
|
171
|
+
"""Execute the command."""
|
172
|
+
response = self.http_client.post(
|
173
|
+
f"investigation-hub/investigations/{self.investigation_id}/activities/mark-as-read",
|
174
|
+
json_data=self.request.model_dump(by_alias=True, exclude_none=True)
|
175
|
+
)
|
176
|
+
return response
|
177
|
+
|
178
|
+
|
179
|
+
class CreateAdvancedFilterCommand(Command[AdvancedFilter]):
|
180
|
+
"""Command to create an advanced filter."""
|
181
|
+
|
182
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str,
|
183
|
+
request: CreateAdvancedFilterRequest):
|
184
|
+
self.http_client = http_client
|
185
|
+
self.investigation_id = investigation_id
|
186
|
+
self.request = request
|
187
|
+
|
188
|
+
def execute(self) -> AdvancedFilter:
|
189
|
+
"""Execute the command."""
|
190
|
+
response = self.http_client.post(
|
191
|
+
f"investigation-hub/advanced-filters",
|
192
|
+
json_data=self.request.model_dump(by_alias=True, exclude_none=True)
|
193
|
+
)
|
194
|
+
return AdvancedFilter(**response["result"])
|
195
|
+
|
196
|
+
|
197
|
+
class UpdateAdvancedFilterCommand(Command[AdvancedFilter]):
|
198
|
+
"""Command to update an advanced filter."""
|
199
|
+
|
200
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str,
|
201
|
+
filter_id: int, request: UpdateAdvancedFilterRequest):
|
202
|
+
self.http_client = http_client
|
203
|
+
self.investigation_id = investigation_id
|
204
|
+
self.filter_id = filter_id
|
205
|
+
self.request = request
|
206
|
+
|
207
|
+
def execute(self) -> AdvancedFilter:
|
208
|
+
"""Execute the command."""
|
209
|
+
response = self.http_client.put(
|
210
|
+
f"investigation-hub/advanced-filters/{self.filter_id}",
|
211
|
+
json_data=self.request.model_dump(by_alias=True, exclude_none=True)
|
212
|
+
)
|
213
|
+
return AdvancedFilter(**response["result"])
|
214
|
+
|
215
|
+
|
216
|
+
class DeleteAdvancedFilterCommand(Command[Dict[str, Any]]):
|
217
|
+
"""Command to delete an advanced filter."""
|
218
|
+
|
219
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str, filter_id: int):
|
220
|
+
self.http_client = http_client
|
221
|
+
self.investigation_id = investigation_id
|
222
|
+
self.filter_id = filter_id
|
223
|
+
|
224
|
+
def execute(self) -> Dict[str, Any]:
|
225
|
+
"""Execute the command."""
|
226
|
+
response = self.http_client.delete(
|
227
|
+
f"investigation-hub/advanced-filters/{self.filter_id}"
|
228
|
+
)
|
229
|
+
return response
|
230
|
+
|
231
|
+
|
232
|
+
class ExportEvidenceCommand(Command[Dict[str, Any]]):
|
233
|
+
"""Command to export evidence data."""
|
234
|
+
|
235
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str,
|
236
|
+
request: ExportRequest):
|
237
|
+
self.http_client = http_client
|
238
|
+
self.investigation_id = investigation_id
|
239
|
+
self.request = request
|
240
|
+
|
241
|
+
def execute(self) -> Dict[str, Any]:
|
242
|
+
"""Execute the command."""
|
243
|
+
response = self.http_client.post(
|
244
|
+
f"investigation-hub/investigations/{self.investigation_id}/export-flags",
|
245
|
+
json_data=self.request.model_dump(by_alias=True, exclude_none=True)
|
246
|
+
)
|
247
|
+
return response
|
248
|
+
|
249
|
+
|
250
|
+
class GenerateReportCommand(Command[Dict[str, Any]]):
|
251
|
+
"""Command to generate an investigation report."""
|
252
|
+
|
253
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str,
|
254
|
+
report_type: str = "comprehensive", include_evidence: bool = True):
|
255
|
+
self.http_client = http_client
|
256
|
+
self.investigation_id = investigation_id
|
257
|
+
self.report_type = report_type
|
258
|
+
self.include_evidence = include_evidence
|
259
|
+
|
260
|
+
def execute(self) -> Dict[str, Any]:
|
261
|
+
"""Execute the command."""
|
262
|
+
payload = {
|
263
|
+
"reportType": self.report_type,
|
264
|
+
"includeEvidence": self.include_evidence
|
265
|
+
}
|
266
|
+
response = self.http_client.post(
|
267
|
+
f"investigation-hub/investigations/{self.investigation_id}/generate-report",
|
268
|
+
json_data=payload
|
269
|
+
)
|
270
|
+
return response
|
271
|
+
|
272
|
+
|
273
|
+
class RefreshInvestigationCommand(Command[Investigation]):
|
274
|
+
"""Command to refresh/rebuild an investigation."""
|
275
|
+
|
276
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str):
|
277
|
+
self.http_client = http_client
|
278
|
+
self.investigation_id = investigation_id
|
279
|
+
|
280
|
+
def execute(self) -> Investigation:
|
281
|
+
"""Execute the command."""
|
282
|
+
response = self.http_client.post(
|
283
|
+
f"investigation-hub/investigations/{self.investigation_id}/refresh"
|
284
|
+
)
|
285
|
+
return Investigation(**response["result"])
|
286
|
+
|
287
|
+
|
288
|
+
class ArchiveInvestigationCommand(Command[Dict[str, Any]]):
|
289
|
+
"""Command to archive an investigation."""
|
290
|
+
|
291
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str):
|
292
|
+
self.http_client = http_client
|
293
|
+
self.investigation_id = investigation_id
|
294
|
+
|
295
|
+
def execute(self) -> Dict[str, Any]:
|
296
|
+
"""Execute the command."""
|
297
|
+
response = self.http_client.post(
|
298
|
+
f"investigation-hub/investigations/{self.investigation_id}/archive"
|
299
|
+
)
|
300
|
+
return response
|
301
|
+
|
302
|
+
|
303
|
+
class RestoreInvestigationCommand(Command[Investigation]):
|
304
|
+
"""Command to restore an archived investigation."""
|
305
|
+
|
306
|
+
def __init__(self, http_client: HTTPClient, investigation_id: str):
|
307
|
+
self.http_client = http_client
|
308
|
+
self.investigation_id = investigation_id
|
309
|
+
|
310
|
+
def execute(self) -> Investigation:
|
311
|
+
"""Execute the command."""
|
312
|
+
response = self.http_client.post(
|
313
|
+
f"investigation-hub/investigations/{self.investigation_id}/restore"
|
314
|
+
)
|
315
|
+
return Investigation(**response["result"])
|