binalyze-air-sdk 1.0.1__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.
Files changed (82) hide show
  1. binalyze_air/__init__.py +77 -0
  2. binalyze_air/apis/__init__.py +27 -0
  3. binalyze_air/apis/authentication.py +27 -0
  4. binalyze_air/apis/auto_asset_tags.py +75 -0
  5. binalyze_air/apis/endpoints.py +22 -0
  6. binalyze_air/apis/event_subscription.py +97 -0
  7. binalyze_air/apis/evidence.py +53 -0
  8. binalyze_air/apis/evidences.py +216 -0
  9. binalyze_air/apis/interact.py +36 -0
  10. binalyze_air/apis/params.py +40 -0
  11. binalyze_air/apis/settings.py +27 -0
  12. binalyze_air/apis/user_management.py +74 -0
  13. binalyze_air/apis/users.py +68 -0
  14. binalyze_air/apis/webhooks.py +231 -0
  15. binalyze_air/base.py +133 -0
  16. binalyze_air/client.py +1338 -0
  17. binalyze_air/commands/__init__.py +146 -0
  18. binalyze_air/commands/acquisitions.py +387 -0
  19. binalyze_air/commands/assets.py +363 -0
  20. binalyze_air/commands/authentication.py +37 -0
  21. binalyze_air/commands/auto_asset_tags.py +231 -0
  22. binalyze_air/commands/baseline.py +396 -0
  23. binalyze_air/commands/cases.py +603 -0
  24. binalyze_air/commands/event_subscription.py +102 -0
  25. binalyze_air/commands/evidences.py +988 -0
  26. binalyze_air/commands/interact.py +58 -0
  27. binalyze_air/commands/organizations.py +221 -0
  28. binalyze_air/commands/policies.py +203 -0
  29. binalyze_air/commands/settings.py +29 -0
  30. binalyze_air/commands/tasks.py +56 -0
  31. binalyze_air/commands/triage.py +360 -0
  32. binalyze_air/commands/user_management.py +126 -0
  33. binalyze_air/commands/users.py +101 -0
  34. binalyze_air/config.py +245 -0
  35. binalyze_air/exceptions.py +50 -0
  36. binalyze_air/http_client.py +306 -0
  37. binalyze_air/models/__init__.py +285 -0
  38. binalyze_air/models/acquisitions.py +251 -0
  39. binalyze_air/models/assets.py +439 -0
  40. binalyze_air/models/audit.py +273 -0
  41. binalyze_air/models/authentication.py +70 -0
  42. binalyze_air/models/auto_asset_tags.py +117 -0
  43. binalyze_air/models/baseline.py +232 -0
  44. binalyze_air/models/cases.py +276 -0
  45. binalyze_air/models/endpoints.py +76 -0
  46. binalyze_air/models/event_subscription.py +172 -0
  47. binalyze_air/models/evidence.py +66 -0
  48. binalyze_air/models/evidences.py +349 -0
  49. binalyze_air/models/interact.py +136 -0
  50. binalyze_air/models/organizations.py +294 -0
  51. binalyze_air/models/params.py +128 -0
  52. binalyze_air/models/policies.py +250 -0
  53. binalyze_air/models/settings.py +84 -0
  54. binalyze_air/models/tasks.py +149 -0
  55. binalyze_air/models/triage.py +143 -0
  56. binalyze_air/models/user_management.py +97 -0
  57. binalyze_air/models/users.py +82 -0
  58. binalyze_air/queries/__init__.py +134 -0
  59. binalyze_air/queries/acquisitions.py +156 -0
  60. binalyze_air/queries/assets.py +105 -0
  61. binalyze_air/queries/audit.py +417 -0
  62. binalyze_air/queries/authentication.py +56 -0
  63. binalyze_air/queries/auto_asset_tags.py +60 -0
  64. binalyze_air/queries/baseline.py +185 -0
  65. binalyze_air/queries/cases.py +293 -0
  66. binalyze_air/queries/endpoints.py +25 -0
  67. binalyze_air/queries/event_subscription.py +55 -0
  68. binalyze_air/queries/evidence.py +140 -0
  69. binalyze_air/queries/evidences.py +280 -0
  70. binalyze_air/queries/interact.py +28 -0
  71. binalyze_air/queries/organizations.py +223 -0
  72. binalyze_air/queries/params.py +115 -0
  73. binalyze_air/queries/policies.py +150 -0
  74. binalyze_air/queries/settings.py +20 -0
  75. binalyze_air/queries/tasks.py +82 -0
  76. binalyze_air/queries/triage.py +231 -0
  77. binalyze_air/queries/user_management.py +83 -0
  78. binalyze_air/queries/users.py +69 -0
  79. binalyze_air_sdk-1.0.1.dist-info/METADATA +635 -0
  80. binalyze_air_sdk-1.0.1.dist-info/RECORD +82 -0
  81. binalyze_air_sdk-1.0.1.dist-info/WHEEL +5 -0
  82. binalyze_air_sdk-1.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,58 @@
1
+ """
2
+ Interact commands for the Binalyze AIR SDK.
3
+ """
4
+
5
+ from typing import Dict, Any, Union
6
+
7
+ from ..base import Command
8
+ from ..models.interact import (
9
+ InteractiveShellTaskResponse, AssignInteractiveShellTaskRequest,
10
+ ShellTaskResponse, AssignShellTaskRequest # Legacy models
11
+ )
12
+ from ..http_client import HTTPClient
13
+
14
+
15
+ class AssignInteractiveShellTaskCommand(Command[InteractiveShellTaskResponse]):
16
+ """Command to assign an interactive shell task."""
17
+
18
+ def __init__(self, http_client: HTTPClient, request: Union[AssignInteractiveShellTaskRequest, Dict[str, Any]]):
19
+ self.http_client = http_client
20
+ self.request = request
21
+
22
+ def execute(self) -> InteractiveShellTaskResponse:
23
+ """Execute the command to assign an interactive shell task."""
24
+ # Handle both dict and model objects
25
+ if isinstance(self.request, dict):
26
+ payload = self.request
27
+ else:
28
+ payload = self.request.model_dump(exclude_none=True, by_alias=True)
29
+
30
+ response = self.http_client.post("interact/shell/assign-task", json_data=payload)
31
+
32
+ if response.get("success"):
33
+ result_data = response.get("result", {})
34
+ # Use Pydantic parsing with proper field aliasing
35
+ return InteractiveShellTaskResponse.model_validate(result_data)
36
+
37
+ raise Exception(f"Failed to assign interactive shell task: {response.get('errors', [])}")
38
+
39
+
40
+ # Legacy command for backward compatibility (deprecated)
41
+ class AssignShellTaskCommand(Command[ShellTaskResponse]):
42
+ """Command to assign a shell interaction task (legacy)."""
43
+
44
+ def __init__(self, http_client: HTTPClient, request: Union[AssignShellTaskRequest, Dict[str, Any]]):
45
+ self.http_client = http_client
46
+ self.request = request
47
+
48
+ def execute(self) -> ShellTaskResponse:
49
+ """Execute the command to assign a shell task (legacy)."""
50
+ # Handle both dict and model objects
51
+ if isinstance(self.request, dict):
52
+ payload = self.request
53
+ else:
54
+ payload = self.request.model_dump(exclude_none=True)
55
+
56
+ response = self.http_client.post("interact/shell/assign-task", json_data=payload)
57
+
58
+ return ShellTaskResponse(**response.get("result", {}))
@@ -0,0 +1,221 @@
1
+ """
2
+ Organization-related commands for the Binalyze AIR SDK.
3
+ """
4
+
5
+ from typing import Dict, Any, List
6
+
7
+ from ..base import Command
8
+ from ..models.organizations import (
9
+ Organization, OrganizationUser, CreateOrganizationRequest,
10
+ UpdateOrganizationRequest, AddUserToOrganizationRequest, OrganizationSettings,
11
+ AssignUsersToOrganizationRequest, AddTagsToOrganizationRequest,
12
+ DeleteTagsFromOrganizationRequest, UpdateShareableDeploymentSettingsRequest,
13
+ UpdateDeploymentTokenRequest, DeploymentTokenUpdateResponse
14
+ )
15
+ from ..http_client import HTTPClient
16
+
17
+
18
+ class CreateOrganizationCommand(Command[Organization]):
19
+ """Command to create a new organization."""
20
+
21
+ def __init__(self, http_client: HTTPClient, request: CreateOrganizationRequest):
22
+ self.http_client = http_client
23
+ self.request = request
24
+
25
+ def execute(self) -> Organization:
26
+ """Execute the command to create an organization."""
27
+ data = self.request.model_dump(exclude_none=True, by_alias=True)
28
+
29
+ response = self.http_client.post("organizations", json_data=data)
30
+
31
+ entity_data = response.get("result", {})
32
+
33
+ # Use Pydantic model_validate for automatic field mapping via aliases
34
+ return Organization.model_validate(entity_data)
35
+
36
+
37
+ class UpdateOrganizationCommand(Command[Organization]):
38
+ """Command to update an existing organization."""
39
+
40
+ def __init__(self, http_client: HTTPClient, organization_id: str, request: UpdateOrganizationRequest):
41
+ self.http_client = http_client
42
+ self.organization_id = organization_id
43
+ self.request = request
44
+
45
+ def execute(self) -> Organization:
46
+ """Execute the command to update an organization."""
47
+ data = self.request.model_dump(exclude_none=True, by_alias=True)
48
+
49
+ response = self.http_client.patch(f"organizations/{self.organization_id}", json_data=data)
50
+
51
+ entity_data = response.get("result", {})
52
+
53
+ # Use Pydantic model_validate for automatic field mapping via aliases
54
+ return Organization.model_validate(entity_data)
55
+
56
+
57
+ class DeleteOrganizationCommand(Command[Dict[str, Any]]):
58
+ """Command to delete an organization."""
59
+
60
+ def __init__(self, http_client: HTTPClient, organization_id: str):
61
+ self.http_client = http_client
62
+ self.organization_id = organization_id
63
+
64
+ def execute(self) -> Dict[str, Any]:
65
+ """Execute the command to delete an organization."""
66
+ response = self.http_client.delete(f"organizations/{self.organization_id}")
67
+ return response
68
+
69
+
70
+ class AssignUsersToOrganizationCommand(Command[bool]):
71
+ """Command to assign multiple users to an organization using the /assign-users endpoint."""
72
+
73
+ def __init__(self, http_client: HTTPClient, organization_id: str, request: AssignUsersToOrganizationRequest):
74
+ self.http_client = http_client
75
+ self.organization_id = organization_id
76
+ self.request = request
77
+
78
+ def execute(self) -> bool:
79
+ """Execute the command to assign users to organization."""
80
+ data = self.request.model_dump(exclude_none=True, by_alias=True)
81
+
82
+ response = self.http_client.post(f"organizations/{self.organization_id}/assign-users", json_data=data)
83
+
84
+ return response.get("success", False)
85
+
86
+
87
+ class RemoveUserFromOrganizationCommand(Command[Dict[str, Any]]):
88
+ """Command to remove a user from an organization using the /remove-user/{userId} endpoint."""
89
+
90
+ def __init__(self, http_client: HTTPClient, organization_id: str, user_id: str):
91
+ self.http_client = http_client
92
+ self.organization_id = organization_id
93
+ self.user_id = user_id
94
+
95
+ def execute(self) -> Dict[str, Any]:
96
+ """Execute the command to remove user from organization."""
97
+ response = self.http_client.delete(f"organizations/{self.organization_id}/remove-user/{self.user_id}")
98
+
99
+ return response
100
+
101
+
102
+ class AddTagsToOrganizationCommand(Command[Organization]):
103
+ """Command to add tags to an organization."""
104
+
105
+ def __init__(self, http_client: HTTPClient, organization_id: str, request: AddTagsToOrganizationRequest):
106
+ self.http_client = http_client
107
+ self.organization_id = organization_id
108
+ self.request = request
109
+
110
+ def execute(self) -> Organization:
111
+ """Execute the command to add tags to organization."""
112
+ data = self.request.model_dump(exclude_none=True, by_alias=True)
113
+
114
+ response = self.http_client.patch(f"organizations/{self.organization_id}/tags", json_data=data)
115
+
116
+ entity_data = response.get("result", {})
117
+
118
+ # Use Pydantic model_validate for automatic field mapping
119
+ return Organization.model_validate(entity_data)
120
+
121
+
122
+ class DeleteTagsFromOrganizationCommand(Command[Organization]):
123
+ """Command to delete tags from an organization."""
124
+
125
+ def __init__(self, http_client: HTTPClient, organization_id: str, request: DeleteTagsFromOrganizationRequest):
126
+ self.http_client = http_client
127
+ self.organization_id = organization_id
128
+ self.request = request
129
+
130
+ def execute(self) -> Organization:
131
+ """Execute the command to delete tags from organization."""
132
+ data = self.request.model_dump(exclude_none=True, by_alias=True)
133
+
134
+ response = self.http_client.delete(f"organizations/{self.organization_id}/tags", json_data=data)
135
+
136
+ entity_data = response.get("result", {})
137
+
138
+ # Use Pydantic model_validate for automatic field mapping
139
+ return Organization.model_validate(entity_data)
140
+
141
+
142
+ class UpdateShareableDeploymentSettingsCommand(Command[bool]):
143
+ """Command to update organization shareable deployment settings."""
144
+
145
+ def __init__(self, http_client: HTTPClient, organization_id: str, request: UpdateShareableDeploymentSettingsRequest):
146
+ self.http_client = http_client
147
+ self.organization_id = organization_id
148
+ self.request = request
149
+
150
+ def execute(self) -> bool:
151
+ """Execute the command to update shareable deployment settings."""
152
+ data = self.request.model_dump(exclude_none=True, by_alias=True)
153
+
154
+ response = self.http_client.post(f"organizations/{self.organization_id}/shareable-deployment", json_data=data)
155
+
156
+ return response.get("success", False)
157
+
158
+
159
+ class UpdateDeploymentTokenCommand(Command[DeploymentTokenUpdateResponse]):
160
+ """Command to update organization deployment token."""
161
+
162
+ def __init__(self, http_client: HTTPClient, organization_id: str):
163
+ self.http_client = http_client
164
+ self.organization_id = organization_id
165
+
166
+ def execute(self) -> DeploymentTokenUpdateResponse:
167
+ """Execute the command to update deployment token."""
168
+ response = self.http_client.post(f"organizations/{self.organization_id}/deployment-token")
169
+
170
+ # Use Pydantic model_validate for automatic field mapping
171
+ return DeploymentTokenUpdateResponse.model_validate(response)
172
+
173
+
174
+ class UpdateOrganizationSettingsCommand(Command[OrganizationSettings]):
175
+ """Command to update organization settings."""
176
+
177
+ def __init__(self, http_client: HTTPClient, organization_id: str, settings: Dict[str, Any]):
178
+ self.http_client = http_client
179
+ self.organization_id = organization_id
180
+ self.settings = settings
181
+
182
+ def execute(self) -> OrganizationSettings:
183
+ """Execute the command to update organization settings."""
184
+ response = self.http_client.put(f"organizations/{self.organization_id}/settings", json_data=self.settings)
185
+
186
+ entity_data = response.get("result", {})
187
+
188
+ mapped_data = {
189
+ "organization_id": entity_data.get("organizationId"),
190
+ "retention_policy": entity_data.get("retentionPolicy", {}),
191
+ "security_settings": entity_data.get("securitySettings", {}),
192
+ "notification_settings": entity_data.get("notificationSettings", {}),
193
+ "api_settings": entity_data.get("apiSettings", {}),
194
+ "custom_settings": entity_data.get("customSettings", {}),
195
+ }
196
+
197
+ # Remove None values
198
+ mapped_data = {k: v for k, v in mapped_data.items() if v is not None}
199
+
200
+ return OrganizationSettings(**mapped_data)
201
+
202
+
203
+ # Legacy command for backward compatibility
204
+ class AddUserToOrganizationCommand(Command[OrganizationUser]):
205
+ """Legacy command to add a user to an organization (use AssignUsersToOrganizationCommand for new implementations)."""
206
+
207
+ def __init__(self, http_client: HTTPClient, organization_id: str, request: AddUserToOrganizationRequest):
208
+ self.http_client = http_client
209
+ self.organization_id = organization_id
210
+ self.request = request
211
+
212
+ def execute(self) -> OrganizationUser:
213
+ """Execute the command to add user to organization."""
214
+ data = self.request.model_dump(exclude_none=True)
215
+
216
+ response = self.http_client.post(f"organizations/{self.organization_id}/users", json_data=data)
217
+
218
+ entity_data = response.get("result", {})
219
+
220
+ # Use Pydantic model_validate for automatic field mapping
221
+ return OrganizationUser.model_validate(entity_data)
@@ -0,0 +1,203 @@
1
+ """
2
+ Policy-related commands for the Binalyze AIR SDK.
3
+ """
4
+
5
+ from typing import Dict, Any, List, Optional, Union
6
+
7
+ from ..base import Command
8
+ from ..models.policies import (
9
+ CreatePolicyRequest, UpdatePolicyRequest, UpdatePoliciesPrioritiesRequest,
10
+ Policy, PolicyPriority, AssignPolicyRequest
11
+ )
12
+ from ..http_client import HTTPClient
13
+
14
+
15
+ class CreatePolicyCommand(Command[Policy]):
16
+ """Command to create a new policy."""
17
+
18
+ def __init__(self, http_client: HTTPClient, policy_data: Union[CreatePolicyRequest, Dict[str, Any]]):
19
+ self.http_client = http_client
20
+ self.policy_data = policy_data
21
+
22
+ def execute(self) -> Policy:
23
+ """Execute the create policy command."""
24
+ # Handle both dict and model objects
25
+ if isinstance(self.policy_data, dict):
26
+ payload = self.policy_data.copy()
27
+ else:
28
+ # Convert model to dict using model_dump with aliases
29
+ payload = self.policy_data.model_dump(by_alias=True, exclude_none=True)
30
+
31
+ response = self.http_client.post("policies", json_data=payload)
32
+
33
+ # Parse using Pydantic models with automatic field mapping
34
+ return Policy.model_validate(response.get("result", {}))
35
+
36
+
37
+ class UpdatePolicyCommand(Command[Policy]):
38
+ """Command to update an existing policy."""
39
+
40
+ def __init__(self, http_client: HTTPClient, policy_id: str, update_data: Union[UpdatePolicyRequest, Dict[str, Any]]):
41
+ self.http_client = http_client
42
+ self.policy_id = policy_id
43
+ self.update_data = update_data
44
+
45
+ def execute(self) -> Policy:
46
+ """Execute the update policy command."""
47
+ # Handle both dict and model objects
48
+ if isinstance(self.update_data, dict):
49
+ payload = self.update_data.copy()
50
+ else:
51
+ # Convert model to dict using model_dump with aliases
52
+ payload = self.update_data.model_dump(by_alias=True, exclude_none=True)
53
+
54
+ response = self.http_client.put(f"policies/{self.policy_id}", json_data=payload)
55
+
56
+ # Parse using Pydantic models with automatic field mapping
57
+ return Policy.model_validate(response.get("result", {}))
58
+
59
+
60
+ class UpdatePoliciesPrioritiesCommand(Command[Dict[str, Any]]):
61
+ """Command to update policy priorities."""
62
+
63
+ def __init__(self, http_client: HTTPClient, priorities_data: Union[UpdatePoliciesPrioritiesRequest, Dict[str, Any]]):
64
+ self.http_client = http_client
65
+ self.priorities_data = priorities_data
66
+
67
+ def execute(self) -> Dict[str, Any]:
68
+ """Execute the update policy priorities command."""
69
+ # Handle both dict and model objects
70
+ if isinstance(self.priorities_data, dict):
71
+ payload = self.priorities_data.copy()
72
+ else:
73
+ # Convert model to dict using model_dump with aliases
74
+ payload = self.priorities_data.model_dump(by_alias=True, exclude_none=True)
75
+
76
+ return self.http_client.put("policies/priorities", json_data=payload)
77
+
78
+
79
+ class DeletePolicyCommand(Command[Dict[str, Any]]):
80
+ """Command to delete a policy."""
81
+
82
+ def __init__(self, http_client: HTTPClient, policy_id: str):
83
+ self.http_client = http_client
84
+ self.policy_id = policy_id
85
+
86
+ def execute(self) -> Dict[str, Any]:
87
+ """Execute the delete policy command."""
88
+ return self.http_client.delete(f"policies/{self.policy_id}")
89
+
90
+
91
+ class AssignPolicyCommand(Command[Dict[str, Any]]):
92
+ """Command to assign policy to endpoints."""
93
+
94
+ def __init__(self, http_client: HTTPClient, assignment_data: Union[AssignPolicyRequest, Dict[str, Any]]):
95
+ self.http_client = http_client
96
+ self.assignment_data = assignment_data
97
+
98
+ def execute(self) -> Dict[str, Any]:
99
+ """Execute the assign policy command."""
100
+ # Handle both dict and model objects
101
+ if isinstance(self.assignment_data, dict):
102
+ payload = self.assignment_data.copy()
103
+ else:
104
+ payload = {
105
+ "policyId": self.assignment_data.policy_id,
106
+ "endpointIds": self.assignment_data.endpoint_ids,
107
+ "organizationIds": self.assignment_data.organization_ids,
108
+ }
109
+
110
+ if self.assignment_data.filter_params:
111
+ payload["filter"] = self.assignment_data.filter_params
112
+
113
+ return self.http_client.post("policies/assign", json_data=payload)
114
+
115
+
116
+ class UnassignPolicyCommand(Command[Dict[str, Any]]):
117
+ """Command to unassign policy from endpoints."""
118
+
119
+ def __init__(self, http_client: HTTPClient, policy_id: str, endpoint_ids: List[str]):
120
+ self.http_client = http_client
121
+ self.policy_id = policy_id
122
+ self.endpoint_ids = endpoint_ids
123
+
124
+ def execute(self) -> Dict[str, Any]:
125
+ """Execute the unassign policy command."""
126
+ payload = {
127
+ "policyId": self.policy_id,
128
+ "endpointIds": self.endpoint_ids,
129
+ }
130
+
131
+ return self.http_client.post("policies/unassign", json_data=payload)
132
+
133
+
134
+ class ExecutePolicyCommand(Command[Dict[str, Any]]):
135
+ """Command to execute a policy on assigned endpoints."""
136
+
137
+ def __init__(self, http_client: HTTPClient, policy_id: str, endpoint_ids: Optional[List[str]] = None):
138
+ self.http_client = http_client
139
+ self.policy_id = policy_id
140
+ self.endpoint_ids = endpoint_ids
141
+
142
+ def execute(self) -> Dict[str, Any]:
143
+ """Execute the policy execution command."""
144
+ payload = {"policyId": self.policy_id}
145
+
146
+ if self.endpoint_ids:
147
+ payload["endpointIds"] = self.endpoint_ids
148
+
149
+ return self.http_client.post("policies/execute", json_data=payload)
150
+
151
+
152
+ class ActivatePolicyCommand(Command[Policy]):
153
+ """Command to activate a policy."""
154
+
155
+ def __init__(self, http_client: HTTPClient, policy_id: str):
156
+ self.http_client = http_client
157
+ self.policy_id = policy_id
158
+
159
+ def execute(self) -> Policy:
160
+ """Execute the activate policy command."""
161
+ payload = {"status": "active"}
162
+ response = self.http_client.put(f"policies/{self.policy_id}", json_data=payload)
163
+
164
+ entity_data = response.get("result", {})
165
+ return Policy(
166
+ id=entity_data.get("_id", self.policy_id),
167
+ name=entity_data.get("name", ""),
168
+ description=entity_data.get("description"),
169
+ type=entity_data.get("type", "custom"),
170
+ status=entity_data.get("status", "active"),
171
+ organization_ids=entity_data.get("organizationIds", [0]),
172
+ created_by=entity_data.get("createdBy", ""),
173
+ created_at=entity_data.get("createdAt"),
174
+ rules=entity_data.get("rules", []),
175
+ tags=entity_data.get("tags", [])
176
+ )
177
+
178
+
179
+ class DeactivatePolicyCommand(Command[Policy]):
180
+ """Command to deactivate a policy."""
181
+
182
+ def __init__(self, http_client: HTTPClient, policy_id: str):
183
+ self.http_client = http_client
184
+ self.policy_id = policy_id
185
+
186
+ def execute(self) -> Policy:
187
+ """Execute the deactivate policy command."""
188
+ payload = {"status": "inactive"}
189
+ response = self.http_client.put(f"policies/{self.policy_id}", json_data=payload)
190
+
191
+ entity_data = response.get("result", {})
192
+ return Policy(
193
+ id=entity_data.get("_id", self.policy_id),
194
+ name=entity_data.get("name", ""),
195
+ description=entity_data.get("description"),
196
+ type=entity_data.get("type", "custom"),
197
+ status=entity_data.get("status", "inactive"),
198
+ organization_ids=entity_data.get("organizationIds", [0]),
199
+ created_by=entity_data.get("createdBy", ""),
200
+ created_at=entity_data.get("createdAt"),
201
+ rules=entity_data.get("rules", []),
202
+ tags=entity_data.get("tags", [])
203
+ )
@@ -0,0 +1,29 @@
1
+ """
2
+ Settings commands for the Binalyze AIR SDK.
3
+ """
4
+
5
+ from typing import Dict, Any, Union
6
+
7
+ from ..base import Command
8
+ from ..models.settings import BannerSettings, UpdateBannerSettingsRequest
9
+ from ..http_client import HTTPClient
10
+
11
+
12
+ class UpdateBannerSettingsCommand(Command[BannerSettings]):
13
+ """Command to update banner settings."""
14
+
15
+ def __init__(self, http_client: HTTPClient, request: Union[UpdateBannerSettingsRequest, Dict[str, Any]]):
16
+ self.http_client = http_client
17
+ self.request = request
18
+
19
+ def execute(self):
20
+ """Execute the update banner settings command."""
21
+ # Handle both dict and model objects
22
+ if isinstance(self.request, dict):
23
+ payload = self.request
24
+ else:
25
+ # Use by_alias=True to ensure field aliases are properly mapped to API field names
26
+ payload = self.request.model_dump(exclude_none=True, by_alias=True)
27
+
28
+ response = self.http_client.put("settings/banner", json_data=payload)
29
+ return response
@@ -0,0 +1,56 @@
1
+ """
2
+ Task-related commands for the Binalyze AIR SDK.
3
+ """
4
+
5
+ from typing import Dict, Any
6
+
7
+ from ..base import Command
8
+ from ..http_client import HTTPClient
9
+
10
+
11
+ class CancelTaskCommand(Command[Dict[str, Any]]):
12
+ """Command to cancel a task."""
13
+
14
+ def __init__(self, http_client: HTTPClient, task_id: str):
15
+ self.http_client = http_client
16
+ self.task_id = task_id
17
+
18
+ def execute(self) -> Dict[str, Any]:
19
+ """Execute the cancel task command."""
20
+ return self.http_client.post(f"tasks/{self.task_id}/cancel", json_data={})
21
+
22
+
23
+ class CancelTaskAssignmentCommand(Command[Dict[str, Any]]):
24
+ """Command to cancel a task assignment."""
25
+
26
+ def __init__(self, http_client: HTTPClient, assignment_id: str):
27
+ self.http_client = http_client
28
+ self.assignment_id = assignment_id
29
+
30
+ def execute(self) -> Dict[str, Any]:
31
+ """Execute the cancel task assignment command."""
32
+ return self.http_client.post(f"tasks/assignments/{self.assignment_id}/cancel", json_data={})
33
+
34
+
35
+ class DeleteTaskAssignmentCommand(Command[Dict[str, Any]]):
36
+ """Command to delete a task assignment."""
37
+
38
+ def __init__(self, http_client: HTTPClient, assignment_id: str):
39
+ self.http_client = http_client
40
+ self.assignment_id = assignment_id
41
+
42
+ def execute(self) -> Dict[str, Any]:
43
+ """Execute the delete task assignment command."""
44
+ return self.http_client.delete(f"tasks/assignments/{self.assignment_id}")
45
+
46
+
47
+ class DeleteTaskCommand(Command[Dict[str, Any]]):
48
+ """Command to delete a task."""
49
+
50
+ def __init__(self, http_client: HTTPClient, task_id: str):
51
+ self.http_client = http_client
52
+ self.task_id = task_id
53
+
54
+ def execute(self) -> Dict[str, Any]:
55
+ """Execute the delete task command."""
56
+ return self.http_client.delete(f"tasks/{self.task_id}")