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.
Files changed (142) hide show
  1. binalyze_air/__init__.py +77 -77
  2. binalyze_air/apis/__init__.py +67 -27
  3. binalyze_air/apis/acquisitions.py +107 -0
  4. binalyze_air/apis/api_tokens.py +49 -0
  5. binalyze_air/apis/assets.py +161 -0
  6. binalyze_air/apis/audit_logs.py +26 -0
  7. binalyze_air/apis/{authentication.py → auth.py} +29 -27
  8. binalyze_air/apis/auto_asset_tags.py +79 -75
  9. binalyze_air/apis/backup.py +177 -0
  10. binalyze_air/apis/baseline.py +46 -0
  11. binalyze_air/apis/cases.py +225 -0
  12. binalyze_air/apis/cloud_forensics.py +116 -0
  13. binalyze_air/apis/event_subscription.py +96 -96
  14. binalyze_air/apis/evidence.py +249 -53
  15. binalyze_air/apis/interact.py +153 -36
  16. binalyze_air/apis/investigation_hub.py +234 -0
  17. binalyze_air/apis/license.py +104 -0
  18. binalyze_air/apis/logger.py +83 -0
  19. binalyze_air/apis/multipart_upload.py +201 -0
  20. binalyze_air/apis/notifications.py +115 -0
  21. binalyze_air/apis/organizations.py +267 -0
  22. binalyze_air/apis/params.py +44 -39
  23. binalyze_air/apis/policies.py +186 -0
  24. binalyze_air/apis/preset_filters.py +79 -0
  25. binalyze_air/apis/recent_activities.py +71 -0
  26. binalyze_air/apis/relay_server.py +104 -0
  27. binalyze_air/apis/settings.py +395 -27
  28. binalyze_air/apis/tasks.py +80 -0
  29. binalyze_air/apis/triage.py +197 -0
  30. binalyze_air/apis/user_management.py +183 -74
  31. binalyze_air/apis/webhook_executions.py +50 -0
  32. binalyze_air/apis/webhooks.py +322 -230
  33. binalyze_air/base.py +207 -133
  34. binalyze_air/client.py +217 -1337
  35. binalyze_air/commands/__init__.py +175 -145
  36. binalyze_air/commands/acquisitions.py +661 -387
  37. binalyze_air/commands/api_tokens.py +55 -0
  38. binalyze_air/commands/assets.py +324 -362
  39. binalyze_air/commands/{authentication.py → auth.py} +36 -36
  40. binalyze_air/commands/auto_asset_tags.py +230 -230
  41. binalyze_air/commands/backup.py +47 -0
  42. binalyze_air/commands/baseline.py +32 -396
  43. binalyze_air/commands/cases.py +609 -602
  44. binalyze_air/commands/cloud_forensics.py +88 -0
  45. binalyze_air/commands/event_subscription.py +101 -101
  46. binalyze_air/commands/evidences.py +918 -988
  47. binalyze_air/commands/interact.py +172 -58
  48. binalyze_air/commands/investigation_hub.py +315 -0
  49. binalyze_air/commands/license.py +183 -0
  50. binalyze_air/commands/logger.py +126 -0
  51. binalyze_air/commands/multipart_upload.py +363 -0
  52. binalyze_air/commands/notifications.py +45 -0
  53. binalyze_air/commands/organizations.py +200 -221
  54. binalyze_air/commands/policies.py +175 -203
  55. binalyze_air/commands/preset_filters.py +55 -0
  56. binalyze_air/commands/recent_activities.py +32 -0
  57. binalyze_air/commands/relay_server.py +144 -0
  58. binalyze_air/commands/settings.py +431 -29
  59. binalyze_air/commands/tasks.py +95 -56
  60. binalyze_air/commands/triage.py +224 -360
  61. binalyze_air/commands/user_management.py +351 -126
  62. binalyze_air/commands/webhook_executions.py +77 -0
  63. binalyze_air/config.py +244 -244
  64. binalyze_air/exceptions.py +49 -49
  65. binalyze_air/http_client.py +426 -305
  66. binalyze_air/models/__init__.py +287 -285
  67. binalyze_air/models/acquisitions.py +365 -250
  68. binalyze_air/models/api_tokens.py +73 -0
  69. binalyze_air/models/assets.py +438 -438
  70. binalyze_air/models/audit.py +247 -272
  71. binalyze_air/models/audit_logs.py +14 -0
  72. binalyze_air/models/{authentication.py → auth.py} +69 -69
  73. binalyze_air/models/auto_asset_tags.py +227 -116
  74. binalyze_air/models/backup.py +138 -0
  75. binalyze_air/models/baseline.py +231 -231
  76. binalyze_air/models/cases.py +275 -275
  77. binalyze_air/models/cloud_forensics.py +145 -0
  78. binalyze_air/models/event_subscription.py +170 -171
  79. binalyze_air/models/evidence.py +65 -65
  80. binalyze_air/models/evidences.py +367 -348
  81. binalyze_air/models/interact.py +266 -135
  82. binalyze_air/models/investigation_hub.py +265 -0
  83. binalyze_air/models/license.py +150 -0
  84. binalyze_air/models/logger.py +83 -0
  85. binalyze_air/models/multipart_upload.py +352 -0
  86. binalyze_air/models/notifications.py +138 -0
  87. binalyze_air/models/organizations.py +293 -293
  88. binalyze_air/models/params.py +153 -127
  89. binalyze_air/models/policies.py +260 -249
  90. binalyze_air/models/preset_filters.py +79 -0
  91. binalyze_air/models/recent_activities.py +70 -0
  92. binalyze_air/models/relay_server.py +121 -0
  93. binalyze_air/models/settings.py +538 -84
  94. binalyze_air/models/tasks.py +215 -149
  95. binalyze_air/models/triage.py +141 -142
  96. binalyze_air/models/user_management.py +200 -97
  97. binalyze_air/models/webhook_executions.py +33 -0
  98. binalyze_air/queries/__init__.py +121 -133
  99. binalyze_air/queries/acquisitions.py +155 -155
  100. binalyze_air/queries/api_tokens.py +46 -0
  101. binalyze_air/queries/assets.py +186 -105
  102. binalyze_air/queries/audit.py +400 -416
  103. binalyze_air/queries/{authentication.py → auth.py} +55 -55
  104. binalyze_air/queries/auto_asset_tags.py +59 -59
  105. binalyze_air/queries/backup.py +66 -0
  106. binalyze_air/queries/baseline.py +21 -185
  107. binalyze_air/queries/cases.py +292 -292
  108. binalyze_air/queries/cloud_forensics.py +137 -0
  109. binalyze_air/queries/event_subscription.py +54 -54
  110. binalyze_air/queries/evidence.py +139 -139
  111. binalyze_air/queries/evidences.py +279 -279
  112. binalyze_air/queries/interact.py +140 -28
  113. binalyze_air/queries/investigation_hub.py +329 -0
  114. binalyze_air/queries/license.py +85 -0
  115. binalyze_air/queries/logger.py +58 -0
  116. binalyze_air/queries/multipart_upload.py +180 -0
  117. binalyze_air/queries/notifications.py +71 -0
  118. binalyze_air/queries/organizations.py +222 -222
  119. binalyze_air/queries/params.py +154 -115
  120. binalyze_air/queries/policies.py +149 -149
  121. binalyze_air/queries/preset_filters.py +60 -0
  122. binalyze_air/queries/recent_activities.py +44 -0
  123. binalyze_air/queries/relay_server.py +42 -0
  124. binalyze_air/queries/settings.py +533 -20
  125. binalyze_air/queries/tasks.py +125 -81
  126. binalyze_air/queries/triage.py +230 -230
  127. binalyze_air/queries/user_management.py +193 -83
  128. binalyze_air/queries/webhook_executions.py +39 -0
  129. binalyze_air_sdk-1.0.3.dist-info/METADATA +752 -0
  130. binalyze_air_sdk-1.0.3.dist-info/RECORD +132 -0
  131. {binalyze_air_sdk-1.0.1.dist-info → binalyze_air_sdk-1.0.3.dist-info}/WHEEL +1 -1
  132. binalyze_air/apis/endpoints.py +0 -22
  133. binalyze_air/apis/evidences.py +0 -216
  134. binalyze_air/apis/users.py +0 -68
  135. binalyze_air/commands/users.py +0 -101
  136. binalyze_air/models/endpoints.py +0 -76
  137. binalyze_air/models/users.py +0 -82
  138. binalyze_air/queries/endpoints.py +0 -25
  139. binalyze_air/queries/users.py +0 -69
  140. binalyze_air_sdk-1.0.1.dist-info/METADATA +0 -635
  141. binalyze_air_sdk-1.0.1.dist-info/RECORD +0 -82
  142. {binalyze_air_sdk-1.0.1.dist-info → binalyze_air_sdk-1.0.3.dist-info}/top_level.txt +0 -0
@@ -1,273 +1,248 @@
1
- """
2
- Audit-related data models for the Binalyze AIR SDK.
3
- """
4
-
5
- from typing import List, Optional, Dict, Any
6
- from datetime import datetime
7
- from enum import Enum
8
-
9
- from ..base import AIRBaseModel, Filter
10
-
11
-
12
- class AuditLevel(str, Enum):
13
- """Audit log level."""
14
- INFO = "info"
15
- WARNING = "warning"
16
- ERROR = "error"
17
- CRITICAL = "critical"
18
-
19
-
20
- class AuditCategory(str, Enum):
21
- """Audit event category."""
22
- AUTHENTICATION = "authentication"
23
- AUTHORIZATION = "authorization"
24
- DATA_ACCESS = "data_access"
25
- SYSTEM_CHANGE = "system_change"
26
- USER_ACTION = "user_action"
27
- API_CALL = "api_call"
28
- POLICY_EXECUTION = "policy_execution"
29
- TASK_EXECUTION = "task_execution"
30
-
31
-
32
- class AuditAction(str, Enum):
33
- """Audit action type."""
34
- CREATE = "create"
35
- READ = "read"
36
- UPDATE = "update"
37
- DELETE = "delete"
38
- EXECUTE = "execute"
39
- LOGIN = "login"
40
- LOGOUT = "logout"
41
- DOWNLOAD = "download"
42
- UPLOAD = "upload"
43
-
44
-
45
- class AuditLog(AIRBaseModel):
46
- """Audit log model."""
47
-
48
- id: str
49
- timestamp: datetime
50
- user_id: Optional[str] = None
51
- username: Optional[str] = None
52
- organization_id: int = 0
53
- category: AuditCategory
54
- action: AuditAction
55
- resource_type: str
56
- resource_id: Optional[str] = None
57
- resource_name: Optional[str] = None
58
- level: AuditLevel = AuditLevel.INFO
59
- message: str
60
- details: Dict[str, Any] = {}
61
- ip_address: Optional[str] = None
62
- user_agent: Optional[str] = None
63
- session_id: Optional[str] = None
64
- correlation_id: Optional[str] = None
65
- success: bool = True
66
- error_code: Optional[str] = None
67
- duration: Optional[int] = None # milliseconds
68
- tags: List[str] = []
69
-
70
-
71
- class AuditSummary(AIRBaseModel):
72
- """Audit summary model."""
73
-
74
- organization_id: int
75
- date: datetime
76
- total_events: int = 0
77
- successful_events: int = 0
78
- failed_events: int = 0
79
- authentication_events: int = 0
80
- authorization_events: int = 0
81
- data_access_events: int = 0
82
- system_change_events: int = 0
83
- user_action_events: int = 0
84
- api_call_events: int = 0
85
- unique_users: int = 0
86
- unique_ips: int = 0
87
- top_users: List[Dict[str, Any]] = []
88
- top_actions: List[Dict[str, Any]] = []
89
- error_summary: List[Dict[str, Any]] = []
90
-
91
-
92
- class AuditUserActivity(AIRBaseModel):
93
- """User activity audit model."""
94
-
95
- user_id: str
96
- username: str
97
- organization_id: int
98
- date: datetime
99
- login_count: int = 0
100
- action_count: int = 0
101
- failed_login_count: int = 0
102
- last_login: Optional[datetime] = None
103
- last_action: Optional[datetime] = None
104
- unique_ips: List[str] = []
105
- actions_by_category: Dict[str, int] = {}
106
- risk_score: float = 0.0
107
-
108
-
109
- class AuditSystemEvent(AIRBaseModel):
110
- """System event audit model."""
111
-
112
- id: str
113
- timestamp: datetime
114
- event_type: str
115
- severity: AuditLevel
116
- component: str
117
- message: str
118
- details: Dict[str, Any] = {}
119
- organization_id: int = 0
120
- resolved: bool = False
121
- resolved_by: Optional[str] = None
122
- resolved_at: Optional[datetime] = None
123
-
124
-
125
- class AuditLogsFilter(Filter):
126
- """Filter for audit logs queries - matches NEW API specification exactly (POST with JSON body)."""
127
-
128
- # Search and identification
129
- search_term: Optional[str] = None
130
- name: Optional[str] = None
131
-
132
- # Audit log specific filters
133
- type: Optional[str] = None # audit log type filter (changed from List[str] to str)
134
- performed_by: Optional[str] = None # user who performed the action
135
- endpoint_name: Optional[str] = None # endpoint name filter
136
-
137
- # NEW PARAMETERS from updated API spec
138
- event_source: Optional[str] = None # NEW: event source filter
139
- occurred_at: Optional[str] = None # NEW: timestamp filter
140
- data_filter: Optional[str] = None # NEW: data filtering capability
141
-
142
- # Organization parameters - changed to single int instead of list
143
- organization_ids: Optional[int] = None # Changed from List[int] to int (API expects single number)
144
- all_organizations: Optional[bool] = None # true/false
145
-
146
- def to_json_body(self) -> Dict[str, Any]:
147
- """Convert filter to JSON body for POST request - NEW API FORMAT."""
148
- body = {}
149
-
150
- # Pagination parameters (top level in body)
151
- if self.page_number is not None:
152
- body["pageNumber"] = self.page_number
153
- if self.page_size is not None:
154
- body["pageSize"] = self.page_size
155
- if self.sort_by is not None:
156
- body["sortBy"] = self.sort_by
157
- if self.sort_type is not None:
158
- body["sortType"] = self.sort_type
159
-
160
- # Filter object (nested in body)
161
- filter_obj = {}
162
-
163
- if self.search_term is not None:
164
- filter_obj["searchTerm"] = self.search_term
165
- if self.name is not None:
166
- filter_obj["name"] = self.name
167
- if self.type is not None:
168
- filter_obj["type"] = self.type
169
- if self.performed_by is not None:
170
- filter_obj["performedBy"] = self.performed_by
171
- if self.endpoint_name is not None:
172
- filter_obj["endpointName"] = self.endpoint_name
173
-
174
- # NEW PARAMETERS
175
- if self.event_source is not None:
176
- filter_obj["eventSource"] = self.event_source
177
- if self.occurred_at is not None:
178
- filter_obj["occurredAt"] = self.occurred_at
179
- if self.data_filter is not None:
180
- filter_obj["dataFilter"] = self.data_filter
181
-
182
- # Organization parameters
183
- if self.organization_ids is not None:
184
- filter_obj["organizationIds"] = self.organization_ids
185
- if self.all_organizations is not None:
186
- filter_obj["allOrganizations"] = self.all_organizations
187
-
188
- # Only add filter object if it has content
189
- if filter_obj:
190
- body["filter"] = filter_obj
191
-
192
- return body
193
-
194
- def to_params(self) -> Dict[str, Any]:
195
- """DEPRECATED: Convert filter to query parameters - kept for backward compatibility."""
196
- # Keep the old method for backward compatibility but mark as deprecated
197
- import warnings
198
- warnings.warn(
199
- "to_params() is deprecated for audit logs. Use to_json_body() for new POST-based API.",
200
- DeprecationWarning,
201
- stacklevel=2
202
- )
203
-
204
- params = {}
205
-
206
- # Pagination parameters (not in filter namespace) - only if set
207
- if self.page_number is not None:
208
- params["pageNumber"] = self.page_number
209
- if self.page_size is not None:
210
- params["pageSize"] = self.page_size
211
- if self.sort_by is not None:
212
- params["sortBy"] = self.sort_by
213
- if self.sort_type is not None:
214
- params["sortType"] = self.sort_type
215
-
216
- # Add audit-specific filter parameters (use API field names)
217
- if self.search_term is not None:
218
- params["filter[searchTerm]"] = self.search_term
219
- if self.name is not None:
220
- params["filter[name]"] = self.name
221
- if self.type is not None:
222
- params["filter[type]"] = self.type
223
- if self.performed_by is not None:
224
- params["filter[performedBy]"] = self.performed_by
225
- if self.endpoint_name is not None:
226
- params["filter[endpointName]"] = self.endpoint_name
227
- if self.organization_ids is not None:
228
- params["filter[organizationIds]"] = str(self.organization_ids)
229
- if self.all_organizations is not None:
230
- params["filter[allOrganizations]"] = "true" if self.all_organizations else "false"
231
-
232
- return params
233
-
234
-
235
- class AuditFilter(Filter):
236
- """Filter for audit queries."""
237
-
238
- user_id: Optional[str] = None
239
- username: Optional[str] = None
240
- category: Optional[List[AuditCategory]] = None
241
- action: Optional[List[AuditAction]] = None
242
- level: Optional[List[AuditLevel]] = None
243
- resource_type: Optional[str] = None
244
- resource_id: Optional[str] = None
245
- ip_address: Optional[str] = None
246
- success: Optional[bool] = None
247
- start_date: Optional[datetime] = None
248
- end_date: Optional[datetime] = None
249
- tags: Optional[List[str]] = None
250
- correlation_id: Optional[str] = None
251
-
252
-
253
- class AuditExportRequest(AIRBaseModel):
254
- """Request model for exporting audit logs."""
255
-
256
- filter_params: AuditFilter
257
- format: str = "json" # json, csv, excel
258
- include_details: bool = True
259
- organization_ids: List[int] = []
260
-
261
-
262
- class AuditRetentionPolicy(AIRBaseModel):
263
- """Audit retention policy model."""
264
-
265
- organization_id: int
266
- retention_days: int = 365
267
- auto_archive: bool = True
268
- archive_location: Optional[str] = None
269
- compress_archives: bool = True
270
- delete_after_archive: bool = False
271
- created_at: Optional[datetime] = None
272
- updated_at: Optional[datetime] = None
1
+ """
2
+ Audit-related data models for the Binalyze AIR SDK.
3
+ """
4
+
5
+ from typing import List, Optional, Dict, Any
6
+ from datetime import datetime
7
+ from enum import Enum
8
+ from typing import Optional
9
+ from pydantic import Field
10
+
11
+ from ..base import AIRBaseModel, Filter
12
+
13
+
14
+ class AuditLevel(str, Enum):
15
+ """Audit log level."""
16
+ INFO = "info"
17
+ WARNING = "warning"
18
+ ERROR = "error"
19
+ CRITICAL = "critical"
20
+
21
+
22
+ class AuditCategory(str, Enum):
23
+ """Audit event category."""
24
+ AUTHENTICATION = "authentication"
25
+ AUTHORIZATION = "authorization"
26
+ DATA_ACCESS = "data_access"
27
+ SYSTEM_CHANGE = "system_change"
28
+ USER_ACTION = "user_action"
29
+ API_CALL = "api_call"
30
+ POLICY_EXECUTION = "policy_execution"
31
+ TASK_EXECUTION = "task_execution"
32
+
33
+
34
+ class AuditAction(str, Enum):
35
+ """Audit action type."""
36
+ CREATE = "create"
37
+ READ = "read"
38
+ UPDATE = "update"
39
+ DELETE = "delete"
40
+ EXECUTE = "execute"
41
+ LOGIN = "login"
42
+ LOGOUT = "logout"
43
+ DOWNLOAD = "download"
44
+ UPLOAD = "upload"
45
+
46
+
47
+ class AuditLog(AIRBaseModel):
48
+ """Audit log model."""
49
+
50
+ id: str
51
+ timestamp: datetime
52
+ user_id: Optional[str] = None
53
+ username: Optional[str] = None
54
+ organization_id: int = 0
55
+ category: AuditCategory
56
+ action: AuditAction
57
+ resource_type: str
58
+ resource_id: Optional[str] = None
59
+ resource_name: Optional[str] = None
60
+ level: AuditLevel = AuditLevel.INFO
61
+ message: str
62
+ details: Dict[str, Any] = {}
63
+ ip_address: Optional[str] = None
64
+ user_agent: Optional[str] = None
65
+ session_id: Optional[str] = None
66
+ correlation_id: Optional[str] = None
67
+ success: bool = True
68
+ error_code: Optional[str] = None
69
+ duration: Optional[int] = None # milliseconds
70
+ tags: List[str] = []
71
+
72
+
73
+ class AuditSummary(AIRBaseModel):
74
+ """Audit summary model."""
75
+
76
+ organization_id: int
77
+ date: datetime
78
+ total_events: int = 0
79
+ successful_events: int = 0
80
+ failed_events: int = 0
81
+ authentication_events: int = 0
82
+ authorization_events: int = 0
83
+ data_access_events: int = 0
84
+ system_change_events: int = 0
85
+ user_action_events: int = 0
86
+ api_call_events: int = 0
87
+ unique_users: int = 0
88
+ unique_ips: int = 0
89
+ top_users: List[Dict[str, Any]] = []
90
+ top_actions: List[Dict[str, Any]] = []
91
+ error_summary: List[Dict[str, Any]] = []
92
+
93
+
94
+ class AuditUserActivity(AIRBaseModel):
95
+ """User activity audit model."""
96
+
97
+ user_id: str
98
+ username: str
99
+ organization_id: int
100
+ date: datetime
101
+ login_count: int = 0
102
+ action_count: int = 0
103
+ failed_login_count: int = 0
104
+ last_login: Optional[datetime] = None
105
+ last_action: Optional[datetime] = None
106
+ unique_ips: List[str] = []
107
+ actions_by_category: Dict[str, int] = {}
108
+ risk_score: float = 0.0
109
+
110
+
111
+ class AuditSystemEvent(AIRBaseModel):
112
+ """System event audit model."""
113
+
114
+ id: str
115
+ timestamp: datetime
116
+ event_type: str
117
+ severity: AuditLevel
118
+ component: str
119
+ message: str
120
+ details: Dict[str, Any] = {}
121
+ organization_id: int = 0
122
+ resolved: bool = False
123
+ resolved_by: Optional[str] = None
124
+ resolved_at: Optional[datetime] = None
125
+
126
+
127
+ class AuditLogsFilter(Filter):
128
+ """Filter for audit logs queries - matches NEW API specification exactly (POST with JSON body)."""
129
+
130
+ # Search and identification
131
+ search_term: Optional[str] = None
132
+ name: Optional[str] = None
133
+
134
+ # Audit log specific filters
135
+ type: Optional[str] = None # audit log type filter (changed from List[str] to str)
136
+ performed_by: Optional[str] = None # user who performed the action
137
+ endpoint_name: Optional[str] = None # endpoint name filter
138
+
139
+ # NEW PARAMETERS from updated API spec
140
+ event_source: Optional[str] = None # NEW: event source filter
141
+ occurred_at: Optional[str] = None # NEW: timestamp filter
142
+ data_filter: Optional[str] = None # NEW: data filtering capability
143
+
144
+ # Organization parameters - changed to single int instead of list
145
+ organization_ids: Optional[int] = Field(default=None, alias="organizationIds") # API expects camelCase
146
+ all_organizations: Optional[bool] = None # true/false
147
+
148
+ def to_json_body(self) -> Dict[str, Any]:
149
+ """Convert filter to JSON body for POST request - NEW API FORMAT."""
150
+ body = {}
151
+
152
+ # Pagination parameters (top level in body)
153
+ if self.page_number is not None:
154
+ body["pageNumber"] = self.page_number
155
+ if self.page_size is not None:
156
+ body["pageSize"] = self.page_size
157
+ if self.sort_by is not None:
158
+ body["sortBy"] = self.sort_by
159
+ if self.sort_type is not None:
160
+ body["sortType"] = self.sort_type
161
+
162
+ # Filter object (nested in body)
163
+ filter_obj = {}
164
+
165
+ if self.search_term is not None:
166
+ filter_obj["searchTerm"] = self.search_term
167
+ if self.name is not None:
168
+ filter_obj["name"] = self.name
169
+ if self.type is not None:
170
+ filter_obj["type"] = self.type
171
+ if self.performed_by is not None:
172
+ filter_obj["performedBy"] = self.performed_by
173
+ if self.endpoint_name is not None:
174
+ filter_obj["endpointName"] = self.endpoint_name
175
+
176
+ # NEW PARAMETERS
177
+ if self.event_source is not None:
178
+ filter_obj["eventSource"] = self.event_source
179
+ if self.occurred_at is not None:
180
+ filter_obj["occurredAt"] = self.occurred_at
181
+ if self.data_filter is not None:
182
+ filter_obj["dataFilter"] = self.data_filter
183
+
184
+ # Organization parameters - API requires organizationIds to be empty
185
+ # Don't include organizationIds in filter as API requires it to be empty
186
+ # if self.organization_ids is not None:
187
+ # filter_obj["organizationIds"] = self.organization_ids
188
+ if self.all_organizations is not None:
189
+ filter_obj["allOrganizations"] = self.all_organizations
190
+
191
+ # Only add filter object if it has content
192
+ if filter_obj:
193
+ body["filter"] = filter_obj
194
+
195
+ return body
196
+
197
+ def to_params(self) -> Dict[str, Any]:
198
+ """Convert filter to API parameters with correct camelCase naming."""
199
+ # Get base parameters
200
+ params = super().to_params()
201
+
202
+ # Fix organization_ids parameter name to match API specification
203
+ if 'filter[organization_ids]' in params:
204
+ # Move from snake_case to camelCase as required by API
205
+ params['filter[organizationIds]'] = params.pop('filter[organization_ids]')
206
+
207
+ return params
208
+
209
+
210
+ class AuditFilter(Filter):
211
+ """Filter for audit queries."""
212
+
213
+ user_id: Optional[str] = None
214
+ username: Optional[str] = None
215
+ category: Optional[List[AuditCategory]] = None
216
+ action: Optional[List[AuditAction]] = None
217
+ level: Optional[List[AuditLevel]] = None
218
+ resource_type: Optional[str] = None
219
+ resource_id: Optional[str] = None
220
+ ip_address: Optional[str] = None
221
+ success: Optional[bool] = None
222
+ start_date: Optional[datetime] = None
223
+ end_date: Optional[datetime] = None
224
+ tags: Optional[List[str]] = None
225
+ correlation_id: Optional[str] = None
226
+
227
+
228
+ class AuditExportRequest(AIRBaseModel):
229
+ """Request model for exporting audit logs."""
230
+
231
+ filter_params: AuditFilter
232
+ format: str = "json" # json, csv, excel
233
+ include_details: bool = True
234
+ organization_ids: List[int] = []
235
+
236
+
237
+ class AuditRetentionPolicy(AIRBaseModel):
238
+ """Audit retention policy model."""
239
+
240
+ organization_id: int
241
+ retention_days: int = 365
242
+ auto_archive: bool = True
243
+ archive_location: Optional[str] = None
244
+ compress_archives: bool = True
245
+ delete_after_archive: bool = False
246
+ created_at: Optional[datetime] = None
247
+ updated_at: Optional[datetime] = None
273
248
  created_by: str
@@ -0,0 +1,14 @@
1
+ from typing import Optional, List
2
+ from pydantic import Field
3
+ from ..base import Filter
4
+
5
+ class AuditLogsFilter(Filter):
6
+ """Filter for audit logs queries."""
7
+
8
+ search_term: Optional[str] = None
9
+ organization_ids: Optional[List[int]] = None
10
+ start_date: Optional[str] = Field(default=None, alias="startDate") # ISO 8601 format
11
+ end_date: Optional[str] = Field(default=None, alias="endDate") # ISO 8601 format
12
+ user_id: Optional[str] = None
13
+ action: Optional[str] = None
14
+ resource: Optional[str] = None